Pluggable application framework for building extensible desktop-like web applications with plugin architecture support
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
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
});The application startup process follows a specific sequence of steps:
start() has already been calledautoStart: true plus any specified in startPluginsMonitoring 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');
});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 processingkeyup: Key release handling for command completioncontextmenu: Right-click context menu activationresize: Window resize handling for layout updatesEvent 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()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);
}
}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('');
}
}
}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);start() once - subsequent calls return the same promiserequires/optional dependencies rather than startPlugins for plugin orderingstart() if using a custom hostIDbubblingKeydown: true if you need to handle keyboard events in your own code first