glimpse-sdk 0.5.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -30
- package/dist/src/app.d.ts +16 -12
- package/dist/src/app.js +83 -7
- package/dist/src/events.d.ts +1 -1
- package/dist/src/events.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/protocol.d.ts +10 -15
- package/dist/src/protocol.js +15 -18
- package/dist/src/widgets.d.ts +415 -256
- package/dist/src/widgets.js +396 -457
- package/package.json +1 -1
- package/src/app.ts +94 -17
- package/src/events.ts +2 -2
- package/src/index.ts +39 -36
- package/src/protocol.ts +18 -23
- package/src/widgets.ts +365 -794
package/README.md
CHANGED
|
@@ -15,19 +15,19 @@ npm install glimpse-sdk
|
|
|
15
15
|
Create and live-run a TypeScript applet project with the Glimpse tooling:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
glimpse-
|
|
18
|
+
glimpse-shell applets new counter --lang typescript
|
|
19
19
|
cd counter
|
|
20
|
-
glimpse-
|
|
20
|
+
glimpse-shell applets dev
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Read `docs/custom-applets/tooling.md` for project layout, `applet.toml`, dev applets, linking, and diagnostics.
|
|
23
|
+
Read `docs/custom-applets/tooling.md` for project layout, `applet.toml`, dev applets, local linking, distribution, and diagnostics.
|
|
24
24
|
|
|
25
25
|
## Goals
|
|
26
26
|
|
|
27
27
|
- typed protocol models
|
|
28
28
|
- typed widget builders
|
|
29
29
|
- async runtime
|
|
30
|
-
- explicit typed handler registration
|
|
30
|
+
- widget-local callbacks, with explicit typed handler registration available when needed
|
|
31
31
|
- separate `status(state)` and `popover(state)` methods; state mutation via `await this.setState(...)`
|
|
32
32
|
|
|
33
33
|
## Example
|
|
@@ -35,12 +35,11 @@ Read `docs/custom-applets/tooling.md` for project layout, `applet.toml`, dev app
|
|
|
35
35
|
```ts
|
|
36
36
|
import {
|
|
37
37
|
Applet,
|
|
38
|
-
|
|
39
|
-
Button,
|
|
38
|
+
Column,
|
|
40
39
|
Hero,
|
|
41
|
-
Icon,
|
|
42
40
|
Label,
|
|
43
41
|
StatusItem,
|
|
42
|
+
Tile,
|
|
44
43
|
type TreeNode,
|
|
45
44
|
} from "glimpse-sdk";
|
|
46
45
|
|
|
@@ -50,42 +49,43 @@ interface DeployState {
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
class DeployApplet extends Applet<DeployState> {
|
|
53
|
-
protected initialState(): DeployState {
|
|
54
|
-
return { version: "2026.04.07", status: "Ready" };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
52
|
constructor() {
|
|
58
53
|
super();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected initialState(): DeployState {
|
|
57
|
+
return { version: "2026.04.07", status: "Ready" };
|
|
62
58
|
}
|
|
63
59
|
|
|
64
60
|
protected async status(state: DeployState): Promise<StatusItem[]> {
|
|
65
61
|
return [
|
|
66
62
|
new StatusItem({
|
|
67
63
|
id: "deploy",
|
|
68
|
-
icon:
|
|
64
|
+
icon: "software-update-available-symbolic",
|
|
69
65
|
label: state.status,
|
|
70
66
|
}),
|
|
71
67
|
];
|
|
72
68
|
}
|
|
73
69
|
|
|
74
70
|
protected async popover(state: DeployState): Promise<TreeNode | null> {
|
|
75
|
-
return
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
71
|
+
return new Column({
|
|
72
|
+
children: [
|
|
73
|
+
new Hero({
|
|
74
|
+
icon: "software-update-available-symbolic",
|
|
75
|
+
title: "Deploy",
|
|
76
|
+
subtitle: state.version,
|
|
77
|
+
}),
|
|
78
|
+
new Label("Version"),
|
|
79
|
+
new Tile({
|
|
80
|
+
id: "deploy_now",
|
|
81
|
+
primary: "Deploy now",
|
|
82
|
+
left_icon: "media-playback-start-symbolic",
|
|
83
|
+
on_click: async () => {
|
|
84
|
+
await this.setState({ status: "Deploying" });
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -94,7 +94,9 @@ await new DeployApplet().run();
|
|
|
94
94
|
|
|
95
95
|
## Handler Registration
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
Prefer widget-local callbacks for controls rendered in `popover(state)`.
|
|
98
|
+
Explicit registration helpers are still available when the handler should live
|
|
99
|
+
outside the widget tree:
|
|
98
100
|
|
|
99
101
|
- `this.onClick(id, handler)`
|
|
100
102
|
- `this.onScroll(id, handler)`
|
package/dist/src/app.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CallbackEvent, type ChangeEvent, type ClickEvent, type InitEvent, type InputEvent, type ScrollEvent, type ToggleEvent } from "./events.js";
|
|
1
|
+
import { type CallbackEvent, type ChangeEvent, type ClickEvent, type InitEvent, type InputEvent, type PopoverEvent, type ScrollEvent, type ToggleEvent } from "./events.js";
|
|
2
2
|
import { StatusItem } from "./protocol.js";
|
|
3
3
|
import { type TreeNode } from "./widgets.js";
|
|
4
4
|
type Handler<EventT> = (event: EventT) => void | Promise<void>;
|
|
@@ -7,16 +7,13 @@ interface OutgoingMessage {
|
|
|
7
7
|
data: unknown;
|
|
8
8
|
line: string;
|
|
9
9
|
}
|
|
10
|
-
interface
|
|
11
|
-
summary: string;
|
|
10
|
+
interface ShowNotificationOptions {
|
|
12
11
|
body?: string;
|
|
13
|
-
urgency?: string;
|
|
14
12
|
}
|
|
15
|
-
interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
text: string;
|
|
13
|
+
export interface CommandResult {
|
|
14
|
+
stdout: string;
|
|
15
|
+
stderr: string;
|
|
16
|
+
rc: number;
|
|
20
17
|
}
|
|
21
18
|
interface DismissNotificationArgs {
|
|
22
19
|
id: number;
|
|
@@ -24,6 +21,7 @@ interface DismissNotificationArgs {
|
|
|
24
21
|
export declare abstract class Applet<State extends object> {
|
|
25
22
|
state: State;
|
|
26
23
|
private readonly handlerMap;
|
|
24
|
+
private inlineHandlerMap;
|
|
27
25
|
private readonly outgoing;
|
|
28
26
|
private flushPromise;
|
|
29
27
|
private renderQueued;
|
|
@@ -32,6 +30,7 @@ export declare abstract class Applet<State extends object> {
|
|
|
32
30
|
private popoverOpen;
|
|
33
31
|
protected constructor();
|
|
34
32
|
protected abstract initialState(): State;
|
|
33
|
+
protected cssClass(): string | null;
|
|
35
34
|
protected onStart(): Promise<void>;
|
|
36
35
|
protected onInit(_event: InitEvent): Promise<void>;
|
|
37
36
|
protected onCallback(_event: CallbackEvent): Promise<void>;
|
|
@@ -43,12 +42,16 @@ export declare abstract class Applet<State extends object> {
|
|
|
43
42
|
onInput(id: string, handler: Handler<InputEvent>): void;
|
|
44
43
|
onChange(id: string, handler: Handler<ChangeEvent>): void;
|
|
45
44
|
onToggle(id: string, handler: Handler<ToggleEvent>): void;
|
|
45
|
+
onPopover(handler: Handler<PopoverEvent>): void;
|
|
46
46
|
isPopoverOpen(): boolean;
|
|
47
|
-
|
|
48
|
-
protected
|
|
49
|
-
protected
|
|
47
|
+
log(...args: unknown[]): void;
|
|
48
|
+
protected showNotification(summary: string, options?: ShowNotificationOptions): Promise<void>;
|
|
49
|
+
protected openUri(uri: string): Promise<void>;
|
|
50
|
+
protected copyToClipboard(text: string): Promise<void>;
|
|
51
|
+
protected runCommand(command: string[]): Promise<CommandResult>;
|
|
50
52
|
protected dismissNotification(args: DismissNotificationArgs): void;
|
|
51
53
|
protected closePopover(): void;
|
|
54
|
+
protected runDesktopCommand(command: string, args: string[], input?: string): Promise<void>;
|
|
52
55
|
run(): Promise<void>;
|
|
53
56
|
protected drainOutgoingForTest(): Promise<OutgoingMessage[]>;
|
|
54
57
|
private register;
|
|
@@ -59,4 +62,5 @@ export declare abstract class Applet<State extends object> {
|
|
|
59
62
|
private emit;
|
|
60
63
|
private emitAction;
|
|
61
64
|
}
|
|
65
|
+
export declare function runCommand(command: string[]): Promise<CommandResult>;
|
|
62
66
|
export {};
|
package/dist/src/app.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { createInterface } from "node:readline";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
2
3
|
import { parseCallbackEvent, parseInitEvent, } from "./events.js";
|
|
4
|
+
import { InlineHandlerRegistry } from "./widgets.js";
|
|
3
5
|
export class Applet {
|
|
4
6
|
state;
|
|
5
7
|
handlerMap = new Map();
|
|
8
|
+
inlineHandlerMap = new Map();
|
|
6
9
|
outgoing = [];
|
|
7
10
|
flushPromise = null;
|
|
8
11
|
renderQueued = false;
|
|
@@ -12,6 +15,9 @@ export class Applet {
|
|
|
12
15
|
constructor() {
|
|
13
16
|
this.state = this.initialState();
|
|
14
17
|
}
|
|
18
|
+
cssClass() {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
15
21
|
async onStart() { }
|
|
16
22
|
async onInit(_event) { }
|
|
17
23
|
async onCallback(_event) { }
|
|
@@ -40,17 +46,31 @@ export class Applet {
|
|
|
40
46
|
onToggle(id, handler) {
|
|
41
47
|
this.register("toggle", id, handler);
|
|
42
48
|
}
|
|
49
|
+
onPopover(handler) {
|
|
50
|
+
this.register("open", "popover", handler);
|
|
51
|
+
this.register("close", "popover", handler);
|
|
52
|
+
}
|
|
43
53
|
isPopoverOpen() {
|
|
44
54
|
return this.popoverOpen;
|
|
45
55
|
}
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
log(...args) {
|
|
57
|
+
process.stderr.write(args.map(String).join(" ") + "\n");
|
|
58
|
+
}
|
|
59
|
+
async showNotification(summary, options = {}) {
|
|
60
|
+
const args = [summary];
|
|
61
|
+
if (options.body !== undefined) {
|
|
62
|
+
args.push(options.body);
|
|
63
|
+
}
|
|
64
|
+
await this.runDesktopCommand("notify-send", args);
|
|
65
|
+
}
|
|
66
|
+
async openUri(uri) {
|
|
67
|
+
await this.runDesktopCommand("xdg-open", [uri]);
|
|
48
68
|
}
|
|
49
|
-
|
|
50
|
-
this.
|
|
69
|
+
async copyToClipboard(text) {
|
|
70
|
+
await this.runDesktopCommand("wl-copy", [], text);
|
|
51
71
|
}
|
|
52
|
-
|
|
53
|
-
|
|
72
|
+
async runCommand(command) {
|
|
73
|
+
return await runCommand(command);
|
|
54
74
|
}
|
|
55
75
|
dismissNotification(args) {
|
|
56
76
|
this.emitAction("dismiss_notification", args);
|
|
@@ -58,6 +78,9 @@ export class Applet {
|
|
|
58
78
|
closePopover() {
|
|
59
79
|
this.emitAction("close_popover", {});
|
|
60
80
|
}
|
|
81
|
+
async runDesktopCommand(command, args, input) {
|
|
82
|
+
await runDesktopCommand([command, ...args], input);
|
|
83
|
+
}
|
|
61
84
|
async run() {
|
|
62
85
|
process.stdout.on("error", (err) => {
|
|
63
86
|
if (err.code === "EPIPE") {
|
|
@@ -65,6 +88,10 @@ export class Applet {
|
|
|
65
88
|
}
|
|
66
89
|
});
|
|
67
90
|
await this.onStart();
|
|
91
|
+
const cssClass = this.cssClass();
|
|
92
|
+
if (cssClass !== null) {
|
|
93
|
+
process.stdout.write(`class ${cssClass}\n`);
|
|
94
|
+
}
|
|
68
95
|
await this.scheduleRender();
|
|
69
96
|
const rl = createInterface({
|
|
70
97
|
input: process.stdin,
|
|
@@ -104,7 +131,13 @@ export class Applet {
|
|
|
104
131
|
this.handlerMap.set(`${event}:${id}`, handler);
|
|
105
132
|
}
|
|
106
133
|
async dispatchCallback(event) {
|
|
107
|
-
const
|
|
134
|
+
const key = `${event.event}:${event.id}`;
|
|
135
|
+
const inlineHandler = this.inlineHandlerMap.get(key);
|
|
136
|
+
if (inlineHandler !== undefined) {
|
|
137
|
+
await inlineHandler(event);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const handler = this.handlerMap.get(key);
|
|
108
141
|
if (handler !== undefined) {
|
|
109
142
|
await handler(event);
|
|
110
143
|
return;
|
|
@@ -151,6 +184,14 @@ export class Applet {
|
|
|
151
184
|
this.emit("status", { items: status });
|
|
152
185
|
}
|
|
153
186
|
const widget = await this.popover(this.state);
|
|
187
|
+
if (widget !== null) {
|
|
188
|
+
const registry = new InlineHandlerRegistry();
|
|
189
|
+
widget.bindHandlers?.(registry, []);
|
|
190
|
+
this.inlineHandlerMap = registry.handlers;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
this.inlineHandlerMap = new Map();
|
|
194
|
+
}
|
|
154
195
|
const tree = { root: widget?.toProtocol() ?? null };
|
|
155
196
|
if (!deepEqual(tree, this.lastTree)) {
|
|
156
197
|
this.lastTree = tree;
|
|
@@ -194,3 +235,38 @@ function deepEqual(left, right) {
|
|
|
194
235
|
function isPopoverEvent(event) {
|
|
195
236
|
return event.event === "open" || event.event === "close";
|
|
196
237
|
}
|
|
238
|
+
export async function runCommand(command) {
|
|
239
|
+
return await runCommandWithInput(command);
|
|
240
|
+
}
|
|
241
|
+
async function runDesktopCommand(command, input) {
|
|
242
|
+
const result = await runCommandWithInput(command, input);
|
|
243
|
+
if (result.rc !== 0) {
|
|
244
|
+
throw new Error(`${command[0]} exited with status ${result.rc}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async function runCommandWithInput(command, input) {
|
|
248
|
+
if (command.length === 0) {
|
|
249
|
+
throw new Error("command must not be empty");
|
|
250
|
+
}
|
|
251
|
+
return await new Promise((resolve, reject) => {
|
|
252
|
+
const child = spawn(command[0], command.slice(1), { stdio: ["pipe", "pipe", "pipe"] });
|
|
253
|
+
const stdout = [];
|
|
254
|
+
const stderr = [];
|
|
255
|
+
child.on("error", reject);
|
|
256
|
+
child.stdout.on("data", (chunk) => stdout.push(chunk));
|
|
257
|
+
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
258
|
+
child.on("close", (code) => {
|
|
259
|
+
resolve({
|
|
260
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
261
|
+
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
262
|
+
rc: code ?? -1,
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
if (input !== undefined) {
|
|
266
|
+
child.stdin.end(input);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
child.stdin.end();
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
package/dist/src/events.d.ts
CHANGED
package/dist/src/events.js
CHANGED
|
@@ -8,7 +8,7 @@ export function parseCallbackEvent(payload) {
|
|
|
8
8
|
const event = String(payload.type ?? payload.event ?? "");
|
|
9
9
|
const id = String(payload.id ?? "");
|
|
10
10
|
if (event === "click") {
|
|
11
|
-
return { id, event, button: payload.button === undefined ?
|
|
11
|
+
return { id, event, button: payload.button === undefined ? null : String(payload.button) };
|
|
12
12
|
}
|
|
13
13
|
if (event === "scroll") {
|
|
14
14
|
return {
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Applet } from "./app.js";
|
|
1
|
+
export { Applet, runCommand } from "./app.js";
|
|
2
2
|
export { type CallbackEvent, type ChangeEvent, type ClickEvent, type InitEvent, type InputEvent, type PopoverEvent, type ScrollEvent, type ToggleEvent, parseCallbackEvent, parseInitEvent, } from "./events.js";
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
3
|
+
export { ipc, IpcError, Subscriber } from "./ipc.js";
|
|
4
|
+
export { StatusItem } from "./protocol.js";
|
|
5
|
+
export { Badge, type BadgeKind, BatteryHero, BoxedList, ButtonRow, Calendar, CameraIndicator, Choice, ChoiceList, ChoiceTile, CircleBox, Column, Container, DateHero, EmptyState, EventItem, Events, ExpanderTile, Header, Hero, KeyValueGrid, Label, LocationIndicator, Meter, MicIndicator, MutedIndicator, type PagerAppearance, PagerItem, PagerStrip, PanelIndicator, PopoverShell, type PopoverSize, Row, ScreenCastIndicator, Scroll, SegmentedTile, Separator, SliderTile, Spinner, StatusDot, type StatusDotStatus, SwitchTile, Tile, type TreeNode, WeatherForecastItem, WeatherForecastList, WeatherHourlyItem, WeatherHourlyStrip, WidgetBase, WorldClock, WorldClockRow, } from "./widgets.js";
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Applet } from "./app.js";
|
|
1
|
+
export { Applet, runCommand } from "./app.js";
|
|
2
2
|
export { parseCallbackEvent, parseInitEvent, } from "./events.js";
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
3
|
+
export { ipc, IpcError, Subscriber } from "./ipc.js";
|
|
4
|
+
export { StatusItem } from "./protocol.js";
|
|
5
|
+
export { Badge, BatteryHero, BoxedList, ButtonRow, Calendar, CameraIndicator, Choice, ChoiceList, ChoiceTile, CircleBox, Column, Container, DateHero, EmptyState, EventItem, Events, ExpanderTile, Header, Hero, KeyValueGrid, Label, LocationIndicator, Meter, MicIndicator, MutedIndicator, PagerItem, PagerStrip, PanelIndicator, PopoverShell, Row, ScreenCastIndicator, Scroll, SegmentedTile, Separator, SliderTile, Spinner, StatusDot, SwitchTile, Tile, WeatherForecastItem, WeatherForecastList, WeatherHourlyItem, WeatherHourlyStrip, WidgetBase, WorldClock, WorldClockRow, } from "./widgets.js";
|
package/dist/src/protocol.d.ts
CHANGED
|
@@ -1,28 +1,23 @@
|
|
|
1
|
-
export type IconKind = "name" | "path";
|
|
2
|
-
export declare class Icon {
|
|
3
|
-
readonly kind: IconKind;
|
|
4
|
-
readonly value: string;
|
|
5
|
-
constructor(kind: IconKind, value: string);
|
|
6
|
-
static name(value: string): Icon;
|
|
7
|
-
static path(value: string): Icon;
|
|
8
|
-
toProtocol(): {
|
|
9
|
-
name: string;
|
|
10
|
-
} | {
|
|
11
|
-
path: string;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
1
|
export declare class StatusItem {
|
|
15
2
|
readonly options: {
|
|
16
3
|
id?: string;
|
|
17
|
-
icon?:
|
|
4
|
+
icon?: string;
|
|
18
5
|
label?: string;
|
|
19
6
|
tooltip?: string;
|
|
7
|
+
cssClasses?: string[];
|
|
20
8
|
};
|
|
21
9
|
constructor(options?: {
|
|
22
10
|
id?: string;
|
|
23
|
-
icon?:
|
|
11
|
+
icon?: string;
|
|
24
12
|
label?: string;
|
|
25
13
|
tooltip?: string;
|
|
14
|
+
cssClasses?: string[];
|
|
26
15
|
});
|
|
16
|
+
/**
|
|
17
|
+
* Return a copy with `cssClass` appended to `cssClasses`. Immutable-update
|
|
18
|
+
* form that mirrors the Rust SDK's `css_class()` builder so SDK-hopping
|
|
19
|
+
* users see equivalent ergonomics across languages.
|
|
20
|
+
*/
|
|
21
|
+
withCssClass(cssClass: string): StatusItem;
|
|
27
22
|
toProtocol(): Record<string, unknown>;
|
|
28
23
|
}
|
package/dist/src/protocol.js
CHANGED
|
@@ -1,32 +1,26 @@
|
|
|
1
|
-
export class Icon {
|
|
2
|
-
kind;
|
|
3
|
-
value;
|
|
4
|
-
constructor(kind, value) {
|
|
5
|
-
this.kind = kind;
|
|
6
|
-
this.value = value;
|
|
7
|
-
}
|
|
8
|
-
static name(value) {
|
|
9
|
-
return new Icon("name", value);
|
|
10
|
-
}
|
|
11
|
-
static path(value) {
|
|
12
|
-
return new Icon("path", value);
|
|
13
|
-
}
|
|
14
|
-
toProtocol() {
|
|
15
|
-
return this.kind === "name" ? { name: this.value } : { path: this.value };
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
1
|
export class StatusItem {
|
|
19
2
|
options;
|
|
20
3
|
constructor(options = {}) {
|
|
21
4
|
this.options = options;
|
|
22
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Return a copy with `cssClass` appended to `cssClasses`. Immutable-update
|
|
8
|
+
* form that mirrors the Rust SDK's `css_class()` builder so SDK-hopping
|
|
9
|
+
* users see equivalent ergonomics across languages.
|
|
10
|
+
*/
|
|
11
|
+
withCssClass(cssClass) {
|
|
12
|
+
return new StatusItem({
|
|
13
|
+
...this.options,
|
|
14
|
+
cssClasses: [...(this.options.cssClasses ?? []), cssClass],
|
|
15
|
+
});
|
|
16
|
+
}
|
|
23
17
|
toProtocol() {
|
|
24
18
|
const payload = {};
|
|
25
19
|
if (this.options.id !== undefined) {
|
|
26
20
|
payload.id = this.options.id;
|
|
27
21
|
}
|
|
28
22
|
if (this.options.icon !== undefined) {
|
|
29
|
-
payload.icon = this.options.icon
|
|
23
|
+
payload.icon = this.options.icon;
|
|
30
24
|
}
|
|
31
25
|
if (this.options.label !== undefined) {
|
|
32
26
|
payload.label = this.options.label;
|
|
@@ -34,6 +28,9 @@ export class StatusItem {
|
|
|
34
28
|
if (this.options.tooltip !== undefined) {
|
|
35
29
|
payload.tooltip = this.options.tooltip;
|
|
36
30
|
}
|
|
31
|
+
if (this.options.cssClasses && this.options.cssClasses.length > 0) {
|
|
32
|
+
payload.css_classes = [...this.options.cssClasses];
|
|
33
|
+
}
|
|
37
34
|
return payload;
|
|
38
35
|
}
|
|
39
36
|
}
|