Widget JS API тАФ @seelen-ui/lib
This page covers the runtime JS/TS API a widget actually calls once it's loaded тАФ how it initializes itself, how it calls backend commands, and how it listens for backend events. Read widget guidelines first for how a widget is declared and packaged; this page is about what your widget's code does once it's running.
1. Lifecycle тАФ Widget.self, init(), ready()
Every widget runs inside a webview that Seelen UI injects a runtime handle into. Access it with:
import { Widget } from "@seelen-ui/lib";
const widget = Widget.self;
This throws if the code is not actually running inside a Seelen UI widget webview.
Widget.getCurrent()still exists but is deprecated тАФ use theWidget.selfgetter instead.
init()
Call this before any other action. It applies the widget's preset behavior (sizing, positioning, theming) but does
not show the widget yet тАФ the widget stays in a pending state.
await widget.init({ ...options });
All options are optional тАФ omit anything you want the preset's default behavior for. The full InitWidgetOptions type,
its fields, and their defaults are documented via doc comments in libs/core/src/state/widget/interfaces.ts тАФ read that
file directly rather than relying on a copy of the field list here.
ready()
Call this once your widget has actually mounted and is visually ready. It marks the widget ready, runs the auto-sizer,
and тАФ unless the widget is lazy or you pass show: false тАФ shows the window. Calling ready() before init()
throws.
await widget.ready(); // show: !widget.lazy by default
ready() is also what flushes a pending trigger event тАФ if something tried to open this widget (e.g. a toolbar
plugin calling trigger(widgetId)) before the widget finished loading, that trigger is queued and delivered once
ready() runs.
Typical bootstrap
import { Widget } from "@seelen-ui/lib";
import { mount } from "./app"; // your framework's mount function
const widget = Widget.self;
await widget.init();
mount(document.getElementById("root")!);
await widget.ready();
Both methods, their full option types (InitWidgetOptions, ReadyWidgetOptions), and their doc comments live in
libs/core/src/state/widget/mod.ts and libs/core/src/state/widget/interfaces.ts тАФ read those directly if you need
behavior not summarized above.
2. Calling the backend тАФ invoke
import { invoke, SeelenCommand } from "@seelen-ui/lib";
const workspaces = await invoke(SeelenCommand.StateGetVirtualDesktops);
await invoke(SeelenCommand.SwitchWorkspace, { workspaceId });
invoke is a thin, strongly-typed wrapper around Tauri's own invoke тАФ the command name and argument/return types are
all inferred from the SeelenCommand enum value you pass, so passing the wrong argument shape is a compile-time error,
not a runtime one.
Do not look for a list of commands in this doc. Every backend command Seelen UI exposes is declared in one place,
and that declaration is the only source of truth (names, arguments, and return types all live together, and the
SeelenCommand enum plus the TS argument/return types are generated straight from it):
libs/core/src/handlers/commands.rs
Read the slu_commands_declaration! { ... } block there. After a change to that file, SeelenCommand and its typed
argument/return maps are regenerated into libs/core/src/handlers/commands.ts тАФ never edit that generated file by hand.
3. Listening for backend events тАФ subscribe
import { SeelenEvent, subscribe } from "@seelen-ui/lib";
const unsubscribe = await subscribe(SeelenEvent.VirtualDesktopsChanged, (event) => {
console.log(event.payload); // typed as VirtualDesktops
});
// later, if needed
unsubscribe();
subscribe is a thin, strongly-typed wrapper around Tauri's listen тАФ the payload type is inferred from the
SeelenEvent value you pass.
Do not look for a list of events in this doc, for the same reason as commands тАФ the single source of truth is:
libs/core/src/handlers/events.rs
Read the slu_events_declaration! { ... } block there (EventName(PayloadType) as "wire-event-name"). The
SeelenEvent enum and its typed payload map are regenerated from this file into libs/core/src/handlers/events.ts тАФ
never edit that generated file by hand.
4. Regenerating bindings after touching either file
If you add or change a command or event in the Rust files above, regenerate the TS bindings before using the new name from a widget:
cd libs/core && deno task build:rs
Both invoke and subscribe themselves тАФ the wrapper functions shown in sections 2 and 3 тАФ are defined in
libs/core/src/handlers/mod.ts, which also re-exports the generated SeelenCommand/SeelenEvent enums. That file is
the right place to look if you need to understand exactly how the typing or the Tauri call is wired, beyond what's shown
here.