Plugin System Overview

Overview

Editor UI plugins are registered through the UI host and exposed in a Figma-like flow:

  1. Right-click the canvas.
  2. Click Plugins....
  3. Select a plugin from the launcher list.
  4. Use plugin actions inside the plugin modal.
  5. (Optional) Run quick plugin actions from context menu or launcher.

Registration

The host is installed against an editor instance and then plugins are registered:

import { UiPluginHost } from '@designful/ui-plugin-host'
import { createHelloWorldUiPlugin } from '@designful/hello-world-ui-plugin'

const host = new UiPluginHost()
host.install(editor)
host.registerPlugin(createHelloWorldUiPlugin())

You can also configure timeout and document scope for plugin storage:

const host = new UiPluginHost({ defaultActionTimeoutMs: 15000, documentScopeId: 'doc-1' })

Shared Command Path

Both modal button interactions and API calls run through the same validation and command execution path:

  • Validate plugin definition
  • Validate command payload
  • Validate action input payload (for parameterized actions)
  • Execute command on editor
  • Return standardized result payload

This keeps UI behavior and API behavior consistent.

API Access

After installation, the editor exposes uiPlugins:

editor.uiPlugins?.openLauncher()
editor.uiPlugins?.openPluginModal('hello-world-ui-plugin')
await editor.uiPlugins?.executeAction('hello-world-ui-plugin', 'nudge-selection')
await editor.uiPlugins?.executeAction('hello-world-ui-plugin', 'nudge-selection-custom', { dx: 12, dy: -8 })
editor.uiPlugins?.getNotifications()

executeAction is asynchronous in V2-oriented host runtime. The host also prevents duplicate action triggers while one action is running. The host enforces manifest capabilities and provides storage/notification APIs through action context, and records relaunch metadata for processed objects.

History

Selection update commands use grouped transactions, and create commands use editor creation APIs. One plugin action maps to one grouped history step, so undo/redo stays deterministic.

Live Demo

Open /guide/ui-plugins-live-demo to test:

  • async action execution
  • parameterized action inputs
  • capability denial behavior
  • relaunch from context menu