CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lumino--application

Pluggable application framework for building extensible desktop-like web applications with plugin architecture support

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

application-lifecycle.mddocs/

Application Lifecycle

Application startup process and event handling for managing the complete application lifecycle from initialization to shutdown. The Application class provides comprehensive lifecycle management including plugin activation, DOM attachment, and event listener setup.

Capabilities

Application Startup

Start the application with optional configuration for hosting, plugin selection, and event handling behavior.

/**
 * Start the application.
 * @param options - The options for starting the application
 * @returns A promise which resolves when all bootstrapping work is complete and the shell is mounted to the DOM
 */
start(options?: Application.IStartOptions): Promise<void>;

interface Application.IStartOptions {
  /** The ID of the DOM node to host the application shell */
  hostID?: string;
  /** The plugins to activate on startup (in addition to autoStart plugins) */
  startPlugins?: string[];
  /** The plugins to NOT activate on startup (overrides startPlugins and autoStart) */
  ignorePlugins?: string[];
  /** Whether to capture keydown events at bubbling or capturing phase */
  bubblingKeydown?: boolean;
}

Usage Examples:

import { Application } from "@lumino/application";
import { Widget } from "@lumino/widgets";

const app = new Application({ shell: new Widget() });

// Basic startup
await app.start();

// Startup with custom host element
await app.start({
  hostID: 'my-app-container'
});

// Startup with specific plugins
await app.start({
  startPlugins: ['essential-plugin', 'ui-plugin'],
  ignorePlugins: ['debug-plugin']
});

// Startup with custom event handling
await app.start({
  bubblingKeydown: true // Use bubbling phase for keyboard events
});

Startup Process

The application startup process follows a specific sequence of steps:

  1. Check if Already Started: Returns immediately if start() has already been called
  2. Mark as Started: Sets internal started flag to prevent multiple startups
  3. Configure Event Handling: Sets up keydown event capture mode
  4. Activate Startup Plugins: Activates plugins marked with autoStart: true plus any specified in startPlugins
  5. Attach Shell: Mounts the shell widget to the DOM
  6. Add Event Listeners: Registers application-wide event handlers
  7. Resolve Started Promise: Signals that startup is complete

Monitoring Startup:

// Check if application has started
if (await app.started) {
  console.log('Application startup complete');
}

// Wait for startup completion
app.start().then(() => {
  console.log('Application is now running');
});

// Monitor startup with multiple operations
Promise.all([
  app.start(),
  // other async operations
]).then(() => {
  console.log('Everything is ready');
});

Event Handling System

The Application class implements comprehensive DOM event handling for application-wide functionality.

/**
 * Handle the DOM events for the application.
 * @param event - The DOM event sent to the application
 */
handleEvent(event: Event): void;

Supported Events:

  • keydown: Keyboard shortcuts and command processing
  • keyup: Key release handling for command completion
  • contextmenu: Right-click context menu activation
  • resize: Window resize handling for layout updates

Event Handling Behavior:

// The application automatically handles these events:

// Keyboard events - processed by command registry
document.addEventListener('keydown', app); // Triggers app.commands.processKeydownEvent()
document.addEventListener('keyup', app);   // Triggers app.commands.processKeyupEvent()

// Context menu events - opens application context menu
document.addEventListener('contextmenu', app); // Opens app.contextMenu if not shift-clicked

// Window events - updates shell layout
window.addEventListener('resize', app); // Triggers app.shell.update()

Custom Event Handling

Subclasses can override event handling methods for custom behavior:

/**
 * A method invoked on a document 'keydown' event.
 * @param event - The keyboard event
 */
protected evtKeydown(event: KeyboardEvent): void;

/**
 * A method invoked on a document 'keyup' event.
 * @param event - The keyboard event  
 */
protected evtKeyup(event: KeyboardEvent): void;

/**
 * A method invoked on a document 'contextmenu' event.
 * @param event - The pointer event
 */
protected evtContextMenu(event: PointerEvent): void;

/**
 * A method invoked on a window 'resize' event.
 * @param event - The resize event
 */
protected evtResize(event: Event): void;

Custom Event Handling Example:

class CustomApplication extends Application {
  protected evtKeydown(event: KeyboardEvent): void {
    // Add custom keyboard shortcuts
    if (event.ctrlKey && event.key === 'k') {
      console.log('Custom shortcut triggered');
      event.preventDefault();
      return;
    }
    
    // Fall back to default behavior
    super.evtKeydown(event);
  }
  
  protected evtContextMenu(event: PointerEvent): void {
    // Custom context menu logic
    if (event.target instanceof Element && event.target.classList.contains('no-context')) {
      return; // Skip context menu for certain elements
    }
    
    super.evtContextMenu(event);
  }
  
  protected evtResize(event: Event): void {
    console.log('Window resized, updating layout');
    super.evtResize(event);
  }
}

DOM Integration

The application integrates with the DOM through shell attachment and event listener registration:

/**
 * Attach the application shell to the DOM.
 * @param id - The ID of the host node for the shell, or empty string
 */
protected attachShell(id: string): void;

/**
 * Add the application event listeners.
 */
protected addEventListeners(): void;

Shell Attachment:

// Default behavior - attaches to document.body if no ID provided
app.start(); // Shell attached to document.body

// Custom host element
app.start({ hostID: 'app-root' }); // Shell attached to element with id="app-root"

// Custom attachment logic
class CustomApplication extends Application {
  protected attachShell(id: string): void {
    const host = id ? document.getElementById(id) : document.querySelector('.app-container');
    if (host) {
      Widget.attach(this.shell, host);
    } else {
      console.warn('Host element not found, using document.body');
      super.attachShell('');
    }
  }
}

Application State

The Application class provides properties to monitor application state:

/** A promise which resolves after the application has started */
readonly started: Promise<void>;

/** The list of all the deferred plugins */  
readonly deferredPlugins: string[];

State Monitoring:

// Wait for application startup
await app.started;
console.log('Application is running');

// Check deferred plugins
const deferred = app.deferredPlugins;
if (deferred.length > 0) {
  console.log('Deferred plugins:', deferred);
  
  // Activate them later
  await app.activateDeferredPlugins();
  console.log('All deferred plugins now active');
}

// Check if specific functionality is available
const hasStarted = app.started.then(() => true).catch(() => false);

Lifecycle Best Practices

  1. Single Startup: Only call start() once - subsequent calls return the same promise
  2. Plugin Order: Use requires/optional dependencies rather than startPlugins for plugin ordering
  3. Error Handling: Handle startup failures gracefully as some plugins may fail to activate
  4. DOM Ready: Ensure the DOM is ready before calling start() if using a custom hostID
  5. Event Bubbling: Consider bubblingKeydown: true if you need to handle keyboard events in your own code first
  6. Cleanup: The Application class doesn't provide explicit cleanup methods - manage this in your own application code

docs

application-core.md

application-lifecycle.md

index.md

plugin-management.md

service-resolution.md

tile.json