Widget Runtime
This page is for contributors working on widget internals.
Runtime Goals
- deterministic widget lifecycle
- snapshot-based binding resolution
- per-widget failure isolation
- clean plugin registration contract
Plugin Contract
A widget plugin must provide:
typeName(non-empty string)newInstance(settings, callback)
Recommended static members:
labelfields(widget, dashboard, general)preferredRows
Registration validation is enforced in runtime plugin loading.
Widget Instance Lifecycle
Typical instance methods:
render(element)onSettingsChanged(newSettings)processDatasourceUpdate(datasource, context)onResize(size)onDispose()
Optional:
getPreferredRows(settings, snapshot)
Snapshot and Binding Model
Bindings resolve against dashboard snapshot shape:
js
{
datasources: { [datasourceId]: value },
datasourceTitles: { [title]: datasourceId },
[datasourceId]: value,
[datasourceTitle]: value // when unique
}Supported binding styles:
datasources.<id>.<path><title>.<path>- dot and bracket notation
Reactive widget helpers:
getBinding(path)getTemplate(template)
Update Context
Widgets receive context with each update:
changedDatasourcechangedDatasourceIdchangedDatasourceTitlesnapshottimestamp
Error Handling
- errors are trapped per widget
- widget wrapper stores
lastError - UI can show per-widget fallback message
- one widget failing does not stop dashboard update propagation
Pane Height Integration
- widget preferred rows come from
getPreferredRows()or plugin metadata - dashboard computes pane minimum rows from contained widgets
- grid enforces
min-hand layout clamping
Contributor Flow (Short)
- create widget file under
packages/ui/src/widgets/ - implement plugin class + instance lifecycle
- register plugin in
packages/ui/src/stores/pluginRegistry.ts - validate bindings and resize behavior
- document in
Widget Referenceif user-facing
For full standards (responsive/security/testing/review), use Widget Developer Guide.