glimpse-sdk 0.1.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/src/widgets.ts ADDED
@@ -0,0 +1,820 @@
1
+ import { Icon, MenuItem } from "./protocol.js";
2
+
3
+ export type Align = "fill" | "start" | "end" | "center" | "baseline";
4
+ export type Orientation = "horizontal" | "vertical";
5
+ export type Variant = "normal" | "muted" | "accent" | "success" | "warning" | "danger";
6
+
7
+ export interface WidgetNode {
8
+ toProtocol(): Record<string, unknown>;
9
+ }
10
+
11
+ export interface CommonProps {
12
+ id?: string;
13
+ visible?: boolean;
14
+ hexpand?: boolean;
15
+ vexpand?: boolean;
16
+ halign?: Align;
17
+ valign?: Align;
18
+ tooltip?: string;
19
+ variant?: Variant;
20
+ }
21
+
22
+ function applyCommonProps(
23
+ payload: Record<string, unknown>,
24
+ props: CommonProps,
25
+ ): Record<string, unknown> {
26
+ if (props.id !== undefined) payload.id = props.id;
27
+ if (props.visible !== undefined) payload.visible = props.visible;
28
+ if (props.hexpand !== undefined) payload.hexpand = props.hexpand;
29
+ if (props.vexpand !== undefined) payload.vexpand = props.vexpand;
30
+ if (props.halign !== undefined) payload.halign = props.halign;
31
+ if (props.valign !== undefined) payload.valign = props.valign;
32
+ if (props.tooltip !== undefined) payload.tooltip = props.tooltip;
33
+ if (props.variant !== undefined) payload.variant = props.variant;
34
+ return payload;
35
+ }
36
+
37
+ abstract class WidgetBase implements WidgetNode {
38
+ protected constructor(protected readonly common: CommonProps = {}) {}
39
+
40
+ protected withCommon(payload: Record<string, unknown>): Record<string, unknown> {
41
+ return applyCommonProps(payload, this.common);
42
+ }
43
+
44
+ abstract toProtocol(): Record<string, unknown>;
45
+ }
46
+
47
+ export class Label extends WidgetBase {
48
+ constructor(
49
+ public readonly text: string,
50
+ private readonly options: CommonProps & {
51
+ wrap?: boolean;
52
+ xalign?: number;
53
+ selectable?: boolean;
54
+ } = {},
55
+ ) {
56
+ super(options);
57
+ }
58
+
59
+ toProtocol(): Record<string, unknown> {
60
+ const payload = this.withCommon({ text: this.text });
61
+ if (this.options.wrap !== undefined) payload.wrap = this.options.wrap;
62
+ if (this.options.xalign !== undefined) payload.xalign = this.options.xalign;
63
+ if (this.options.selectable !== undefined) payload.selectable = this.options.selectable;
64
+ return { type: "label", data: payload };
65
+ }
66
+ }
67
+
68
+ export class Image extends WidgetBase {
69
+ constructor(
70
+ public readonly icon: Icon,
71
+ private readonly options: CommonProps & { pixel_size?: number } = {},
72
+ ) {
73
+ super(options);
74
+ }
75
+
76
+ toProtocol(): Record<string, unknown> {
77
+ const payload = this.withCommon({ icon: this.icon.toProtocol() });
78
+ if (this.options.pixel_size !== undefined) payload.pixel_size = this.options.pixel_size;
79
+ return { type: "image", data: payload };
80
+ }
81
+ }
82
+
83
+ export class IconWidget extends WidgetBase {
84
+ constructor(
85
+ public readonly icon: Icon,
86
+ private readonly options: CommonProps & { pixel_size?: number } = {},
87
+ ) {
88
+ super(options);
89
+ }
90
+
91
+ toProtocol(): Record<string, unknown> {
92
+ const payload = this.withCommon({ icon: this.icon.toProtocol() });
93
+ if (this.options.pixel_size !== undefined) payload.pixel_size = this.options.pixel_size;
94
+ return { type: "icon", data: payload };
95
+ }
96
+ }
97
+
98
+ export class Progress extends WidgetBase {
99
+ constructor(
100
+ private readonly options: CommonProps & {
101
+ value: number;
102
+ max?: number;
103
+ show_text?: boolean;
104
+ text?: string;
105
+ },
106
+ ) {
107
+ super(options);
108
+ }
109
+
110
+ toProtocol(): Record<string, unknown> {
111
+ const payload = this.withCommon({
112
+ value: this.options.value,
113
+ max: this.options.max ?? 1,
114
+ });
115
+ if (this.options.show_text !== undefined) payload.show_text = this.options.show_text;
116
+ if (this.options.text !== undefined) payload.text = this.options.text;
117
+ return { type: "progress", data: payload };
118
+ }
119
+ }
120
+
121
+ export class Button extends WidgetBase {
122
+ constructor(
123
+ private readonly options: CommonProps & {
124
+ label?: string;
125
+ icon?: Icon;
126
+ child?: TreeNode;
127
+ } = {},
128
+ ) {
129
+ super(options);
130
+ }
131
+
132
+ toProtocol(): Record<string, unknown> {
133
+ const payload = this.withCommon({});
134
+ if (this.options.label !== undefined) payload.label = this.options.label;
135
+ if (this.options.icon !== undefined) payload.icon = this.options.icon.toProtocol();
136
+ if (this.options.child !== undefined) payload.child = this.options.child.toProtocol();
137
+ return { type: "button", data: payload };
138
+ }
139
+ }
140
+
141
+ export class Switch extends WidgetBase {
142
+ constructor(
143
+ private readonly options: CommonProps & {
144
+ label?: string;
145
+ active?: boolean;
146
+ } = {},
147
+ ) {
148
+ super(options);
149
+ }
150
+
151
+ toProtocol(): Record<string, unknown> {
152
+ const payload = this.withCommon({ active: this.options.active ?? false });
153
+ if (this.options.label !== undefined) payload.label = this.options.label;
154
+ return { type: "switch", data: payload };
155
+ }
156
+ }
157
+
158
+ export class Scale extends WidgetBase {
159
+ constructor(
160
+ private readonly options: CommonProps & {
161
+ min?: number;
162
+ max?: number;
163
+ step?: number;
164
+ value?: number;
165
+ orientation?: Orientation;
166
+ draw_value?: boolean;
167
+ } = {},
168
+ ) {
169
+ super(options);
170
+ }
171
+
172
+ toProtocol(): Record<string, unknown> {
173
+ const payload = this.withCommon({
174
+ min: this.options.min ?? 0,
175
+ max: this.options.max ?? 1,
176
+ step: this.options.step ?? 0.1,
177
+ value: this.options.value ?? 0,
178
+ });
179
+ if (this.options.orientation !== undefined) payload.orientation = this.options.orientation;
180
+ if (this.options.draw_value !== undefined) payload.draw_value = this.options.draw_value;
181
+ return { type: "scale", data: payload };
182
+ }
183
+ }
184
+
185
+ export class Checkbox extends WidgetBase {
186
+ constructor(
187
+ private readonly options: CommonProps & {
188
+ label?: string;
189
+ active?: boolean;
190
+ } = {},
191
+ ) {
192
+ super(options);
193
+ }
194
+
195
+ toProtocol(): Record<string, unknown> {
196
+ const payload = this.withCommon({ active: this.options.active ?? false });
197
+ if (this.options.label !== undefined) payload.label = this.options.label;
198
+ return { type: "checkbox", data: payload };
199
+ }
200
+ }
201
+
202
+ export class DropdownItem {
203
+ constructor(
204
+ public readonly id: string,
205
+ public readonly label: string,
206
+ ) {}
207
+
208
+ toProtocol(): Record<string, unknown> {
209
+ return { id: this.id, label: this.label };
210
+ }
211
+ }
212
+
213
+ export class Dropdown extends WidgetBase {
214
+ constructor(
215
+ private readonly options: CommonProps & {
216
+ items?: DropdownItem[];
217
+ selected?: number;
218
+ } = {},
219
+ ) {
220
+ super(options);
221
+ }
222
+
223
+ toProtocol(): Record<string, unknown> {
224
+ const payload = this.withCommon({
225
+ items: (this.options.items ?? []).map((item) => item.toProtocol()),
226
+ });
227
+ if (this.options.selected !== undefined) payload.selected = this.options.selected;
228
+ return { type: "dropdown", data: payload };
229
+ }
230
+ }
231
+
232
+ export class Separator extends WidgetBase {
233
+ constructor(private readonly options: CommonProps & { orientation?: Orientation } = {}) {
234
+ super(options);
235
+ }
236
+
237
+ toProtocol(): Record<string, unknown> {
238
+ const payload = this.withCommon({});
239
+ if (this.options.orientation !== undefined) payload.orientation = this.options.orientation;
240
+ return { type: "separator", data: payload };
241
+ }
242
+ }
243
+
244
+ export class Scroll extends WidgetBase {
245
+ constructor(
246
+ private readonly child: TreeNode,
247
+ options: CommonProps = {},
248
+ ) {
249
+ super(options);
250
+ }
251
+
252
+ toProtocol(): Record<string, unknown> {
253
+ return { type: "scroll", data: this.withCommon({ child: this.child.toProtocol() }) };
254
+ }
255
+ }
256
+
257
+ export class GridChild {
258
+ constructor(
259
+ public readonly row: number,
260
+ public readonly column: number,
261
+ public readonly child: TreeNode,
262
+ public readonly width: number = 1,
263
+ public readonly height: number = 1,
264
+ ) {}
265
+
266
+ toProtocol(): Record<string, unknown> {
267
+ return {
268
+ row: this.row,
269
+ column: this.column,
270
+ width: this.width,
271
+ height: this.height,
272
+ child: this.child.toProtocol(),
273
+ };
274
+ }
275
+ }
276
+
277
+ export class Grid extends WidgetBase {
278
+ constructor(
279
+ private readonly options: CommonProps & {
280
+ children?: GridChild[];
281
+ row_spacing?: number;
282
+ column_spacing?: number;
283
+ } = {},
284
+ ) {
285
+ super(options);
286
+ }
287
+
288
+ toProtocol(): Record<string, unknown> {
289
+ return {
290
+ type: "grid",
291
+ data: this.withCommon({
292
+ row_spacing: this.options.row_spacing ?? 0,
293
+ column_spacing: this.options.column_spacing ?? 0,
294
+ children: (this.options.children ?? []).map((child) => child.toProtocol()),
295
+ }),
296
+ };
297
+ }
298
+ }
299
+
300
+ export class Hero extends WidgetBase {
301
+ constructor(
302
+ private readonly options: CommonProps & {
303
+ title: string;
304
+ subtitle: string;
305
+ icon?: Icon;
306
+ },
307
+ ) {
308
+ super(options);
309
+ }
310
+
311
+ toProtocol(): Record<string, unknown> {
312
+ const payload = this.withCommon({
313
+ title: this.options.title,
314
+ subtitle: this.options.subtitle,
315
+ });
316
+ if (this.options.icon !== undefined) payload.icon = this.options.icon.toProtocol();
317
+ return { type: "hero", data: payload };
318
+ }
319
+ }
320
+
321
+ export class Card extends WidgetBase {
322
+ constructor(
323
+ private readonly options: CommonProps & {
324
+ children?: TreeNode[];
325
+ } = {},
326
+ ) {
327
+ super(options);
328
+ }
329
+
330
+ toProtocol(): Record<string, unknown> {
331
+ return {
332
+ type: "card",
333
+ data: this.withCommon({
334
+ children: (this.options.children ?? []).map((child) => child.toProtocol()),
335
+ }),
336
+ };
337
+ }
338
+ }
339
+
340
+ export class Header {
341
+ constructor(
342
+ public readonly title: string,
343
+ public readonly subtitle = "",
344
+ ) {}
345
+
346
+ toProtocol(): Record<string, unknown> {
347
+ const payload: Record<string, unknown> = { title: this.title };
348
+ if (this.subtitle !== "") payload.subtitle = this.subtitle;
349
+ return payload;
350
+ }
351
+ }
352
+
353
+ export class Section extends WidgetBase {
354
+ constructor(
355
+ private readonly options: CommonProps & {
356
+ title?: string;
357
+ subtitle?: string;
358
+ header?: Header;
359
+ body?: TreeNode[];
360
+ children?: TreeNode[];
361
+ },
362
+ ) {
363
+ super(options);
364
+ }
365
+
366
+ toProtocol(): Record<string, unknown> {
367
+ const header =
368
+ this.options.header ??
369
+ (this.options.title === undefined
370
+ ? undefined
371
+ : new Header(this.options.title, this.options.subtitle ?? ""));
372
+ const body = this.options.body ?? this.options.children ?? [];
373
+ return {
374
+ type: "section",
375
+ data: this.withCommon({
376
+ ...(header === undefined ? {} : { header: header.toProtocol() }),
377
+ body: body.map((child) => child.toProtocol()),
378
+ }),
379
+ };
380
+ }
381
+ }
382
+
383
+ export class Collapsible extends WidgetBase {
384
+ constructor(
385
+ private readonly options: CommonProps & {
386
+ title?: string;
387
+ subtitle?: string;
388
+ header?: Header;
389
+ expanded?: boolean;
390
+ body?: TreeNode[];
391
+ children?: TreeNode[];
392
+ },
393
+ ) {
394
+ super(options);
395
+ }
396
+
397
+ toProtocol(): Record<string, unknown> {
398
+ const header =
399
+ this.options.header ??
400
+ (this.options.title === undefined
401
+ ? undefined
402
+ : new Header(this.options.title, this.options.subtitle ?? ""));
403
+ const body = this.options.body ?? this.options.children ?? [];
404
+ return {
405
+ type: "collapsible",
406
+ data: this.withCommon({
407
+ ...(header === undefined ? {} : { header: header.toProtocol() }),
408
+ expanded: this.options.expanded ?? false,
409
+ body: body.map((child) => child.toProtocol()),
410
+ }),
411
+ };
412
+ }
413
+ }
414
+
415
+ export class Item extends WidgetBase {
416
+ constructor(
417
+ private readonly options: CommonProps & {
418
+ left?: TreeNode;
419
+ label?: string;
420
+ right?: TreeNode;
421
+ clickable?: boolean;
422
+ menu?: MenuItem[];
423
+ } = {},
424
+ ) {
425
+ super(options);
426
+ }
427
+
428
+ toProtocol(): Record<string, unknown> {
429
+ const payload = this.withCommon({
430
+ label: this.options.label ?? "",
431
+ clickable: this.options.clickable ?? false,
432
+ menu: (this.options.menu ?? []).map((item) => item.toProtocol()),
433
+ });
434
+ if (this.options.left !== undefined) payload.left = this.options.left.toProtocol();
435
+ if (this.options.right !== undefined) payload.right = this.options.right.toProtocol();
436
+ return { type: "item", data: payload };
437
+ }
438
+ }
439
+
440
+ export class CollapsibleItem extends WidgetBase {
441
+ constructor(
442
+ private readonly options: CommonProps & {
443
+ left?: TreeNode;
444
+ label?: string;
445
+ right?: TreeNode;
446
+ expanded?: boolean;
447
+ body?: TreeNode[];
448
+ children?: TreeNode[];
449
+ } = {},
450
+ ) {
451
+ super(options);
452
+ }
453
+
454
+ toProtocol(): Record<string, unknown> {
455
+ const payload = this.withCommon({
456
+ label: this.options.label ?? "",
457
+ expanded: this.options.expanded ?? false,
458
+ body: (this.options.body ?? this.options.children ?? []).map((child) => child.toProtocol()),
459
+ });
460
+ if (this.options.left !== undefined) payload.left = this.options.left.toProtocol();
461
+ if (this.options.right !== undefined) payload.right = this.options.right.toProtocol();
462
+ return { type: "collapsible_item", data: payload };
463
+ }
464
+ }
465
+
466
+ export class Meter extends WidgetBase {
467
+ constructor(
468
+ private readonly options: CommonProps & {
469
+ icon?: Icon;
470
+ label?: string;
471
+ value: number;
472
+ min?: number;
473
+ max?: number;
474
+ step?: number;
475
+ text?: string;
476
+ interactive?: boolean;
477
+ },
478
+ ) {
479
+ super(options);
480
+ }
481
+
482
+ toProtocol(): Record<string, unknown> {
483
+ const payload = this.withCommon({
484
+ label: this.options.label ?? "",
485
+ value: this.options.value,
486
+ min: this.options.min ?? 0,
487
+ max: this.options.max ?? 1,
488
+ step: this.options.step ?? 0.01,
489
+ interactive: this.options.interactive ?? false,
490
+ });
491
+ if (this.options.icon !== undefined) payload.icon = this.options.icon.toProtocol();
492
+ if (this.options.text !== undefined) payload.text = this.options.text;
493
+ return { type: "meter", data: payload };
494
+ }
495
+ }
496
+
497
+ export class Copyable extends WidgetBase {
498
+ constructor(
499
+ private readonly options: CommonProps & {
500
+ label?: string;
501
+ value: string;
502
+ },
503
+ ) {
504
+ super(options);
505
+ }
506
+
507
+ toProtocol(): Record<string, unknown> {
508
+ return {
509
+ type: "copyable",
510
+ data: this.withCommon({
511
+ label: this.options.label ?? "",
512
+ value: this.options.value,
513
+ }),
514
+ };
515
+ }
516
+ }
517
+
518
+ export class ToastAction {
519
+ constructor(
520
+ public readonly id: string,
521
+ public readonly label: string,
522
+ ) {}
523
+
524
+ toProtocol(): Record<string, unknown> {
525
+ return { id: this.id, label: this.label };
526
+ }
527
+ }
528
+
529
+ export class Toast extends WidgetBase {
530
+ constructor(
531
+ private readonly options: CommonProps & {
532
+ icon?: Icon;
533
+ title: string;
534
+ message?: string;
535
+ action?: ToastAction;
536
+ },
537
+ ) {
538
+ super(options);
539
+ }
540
+
541
+ toProtocol(): Record<string, unknown> {
542
+ const payload = this.withCommon({
543
+ title: this.options.title,
544
+ message: this.options.message ?? "",
545
+ });
546
+ if (this.options.icon !== undefined) payload.icon = this.options.icon.toProtocol();
547
+ if (this.options.action !== undefined) payload.action = this.options.action.toProtocol();
548
+ return { type: "toast", data: payload };
549
+ }
550
+ }
551
+
552
+ export class ActionRow extends WidgetBase {
553
+ constructor(
554
+ private readonly options: CommonProps & {
555
+ title: string;
556
+ subtitle?: string;
557
+ meta?: string;
558
+ icon?: Icon;
559
+ },
560
+ ) {
561
+ super(options);
562
+ }
563
+
564
+ toProtocol(): Record<string, unknown> {
565
+ const payload = this.withCommon({
566
+ title: this.options.title,
567
+ subtitle: this.options.subtitle ?? "",
568
+ meta: this.options.meta ?? "",
569
+ });
570
+ if (this.options.icon !== undefined) payload.icon = this.options.icon.toProtocol();
571
+ return { type: "action_row", data: payload };
572
+ }
573
+ }
574
+
575
+ export class Row extends WidgetBase {
576
+ constructor(
577
+ private readonly options: CommonProps & {
578
+ spacing?: number;
579
+ children?: TreeNode[];
580
+ } = {},
581
+ ) {
582
+ super(options);
583
+ }
584
+
585
+ toProtocol(): Record<string, unknown> {
586
+ return {
587
+ type: "row",
588
+ data: this.withCommon({
589
+ spacing: this.options.spacing ?? 0,
590
+ children: (this.options.children ?? []).map((child) => child.toProtocol()),
591
+ }),
592
+ };
593
+ }
594
+ }
595
+
596
+ export class Column extends WidgetBase {
597
+ constructor(
598
+ private readonly options: CommonProps & {
599
+ spacing?: number;
600
+ children?: TreeNode[];
601
+ } = {},
602
+ ) {
603
+ super(options);
604
+ }
605
+
606
+ toProtocol(): Record<string, unknown> {
607
+ return {
608
+ type: "column",
609
+ data: this.withCommon({
610
+ spacing: this.options.spacing ?? 0,
611
+ children: (this.options.children ?? []).map((child) => child.toProtocol()),
612
+ }),
613
+ };
614
+ }
615
+ }
616
+
617
+ export class ActionMenuItem {
618
+ constructor(
619
+ public readonly options: {
620
+ id: string;
621
+ label: string;
622
+ icon?: Icon;
623
+ visible?: boolean;
624
+ checked?: boolean;
625
+ selectable?: boolean;
626
+ },
627
+ ) {}
628
+
629
+ toProtocol(): Record<string, unknown> {
630
+ const payload: Record<string, unknown> = {
631
+ id: this.options.id,
632
+ label: this.options.label,
633
+ };
634
+ if (this.options.icon !== undefined) payload.icon = this.options.icon.toProtocol();
635
+ if (this.options.visible !== undefined) payload.visible = this.options.visible;
636
+ if (this.options.checked !== undefined) payload.checked = this.options.checked;
637
+ if (this.options.selectable !== undefined) payload.selectable = this.options.selectable;
638
+ return payload;
639
+ }
640
+ }
641
+
642
+ export class ActionMenu extends WidgetBase {
643
+ constructor(
644
+ private readonly options: CommonProps & {
645
+ header?: string;
646
+ items?: ActionMenuItem[];
647
+ } = {},
648
+ ) {
649
+ super(options);
650
+ }
651
+
652
+ toProtocol(): Record<string, unknown> {
653
+ const payload = this.withCommon({
654
+ items: (this.options.items ?? []).map((item) => item.toProtocol()),
655
+ });
656
+ if (this.options.header !== undefined) payload.header = this.options.header;
657
+ return { type: "action_menu", data: payload };
658
+ }
659
+ }
660
+
661
+ export class Spinner extends WidgetBase {
662
+ constructor(
663
+ private readonly options: CommonProps & {
664
+ spinning?: boolean;
665
+ } = {},
666
+ ) {
667
+ super(options);
668
+ }
669
+
670
+ toProtocol(): Record<string, unknown> {
671
+ return {
672
+ type: "spinner",
673
+ data: this.withCommon({ spinning: this.options.spinning ?? true }),
674
+ };
675
+ }
676
+ }
677
+
678
+ export class DetailGridItem {
679
+ constructor(
680
+ public readonly key: string,
681
+ public readonly value: string,
682
+ ) {}
683
+
684
+ toProtocol(): Record<string, unknown> {
685
+ return { key: this.key, value: this.value };
686
+ }
687
+ }
688
+
689
+ export class DetailGrid extends WidgetBase {
690
+ constructor(
691
+ private readonly options: CommonProps & {
692
+ rows?: DetailGridItem[];
693
+ } = {},
694
+ ) {
695
+ super(options);
696
+ }
697
+
698
+ toProtocol(): Record<string, unknown> {
699
+ return {
700
+ type: "detail_grid",
701
+ data: this.withCommon({
702
+ rows: (this.options.rows ?? []).map((row) => row.toProtocol()),
703
+ }),
704
+ };
705
+ }
706
+ }
707
+
708
+ export class EmptyState extends WidgetBase {
709
+ constructor(
710
+ private readonly options: CommonProps & {
711
+ title: string;
712
+ subtitle?: string;
713
+ },
714
+ ) {
715
+ super(options);
716
+ }
717
+
718
+ toProtocol(): Record<string, unknown> {
719
+ return {
720
+ type: "empty_state",
721
+ data: this.withCommon({
722
+ title: this.options.title,
723
+ subtitle: this.options.subtitle ?? "",
724
+ }),
725
+ };
726
+ }
727
+ }
728
+
729
+ export class Badge extends WidgetBase {
730
+ constructor(
731
+ private readonly options: CommonProps & {
732
+ label: string;
733
+ },
734
+ ) {
735
+ super(options);
736
+ }
737
+
738
+ toProtocol(): Record<string, unknown> {
739
+ return {
740
+ type: "badge",
741
+ data: this.withCommon({
742
+ label: this.options.label,
743
+ }),
744
+ };
745
+ }
746
+ }
747
+
748
+ export class StatusDot extends WidgetBase {
749
+ constructor(options: CommonProps = {}) {
750
+ super(options);
751
+ }
752
+
753
+ toProtocol(): Record<string, unknown> {
754
+ return { type: "status", data: this.withCommon({}) };
755
+ }
756
+ }
757
+
758
+ export class Box extends WidgetBase {
759
+ constructor(
760
+ private readonly options: CommonProps & {
761
+ orientation?: Orientation;
762
+ spacing?: number;
763
+ children?: TreeNode[];
764
+ } = {},
765
+ ) {
766
+ super(options);
767
+ }
768
+
769
+ static vertical(children: TreeNode[], spacing = 0, options: CommonProps = {}): Box {
770
+ return new Box({ ...options, orientation: "vertical", spacing, children });
771
+ }
772
+
773
+ static horizontal(children: TreeNode[], spacing = 0, options: CommonProps = {}): Box {
774
+ return new Box({ ...options, orientation: "horizontal", spacing, children });
775
+ }
776
+
777
+ toProtocol(): Record<string, unknown> {
778
+ return {
779
+ type: "box",
780
+ data: this.withCommon({
781
+ orientation: this.options.orientation ?? "vertical",
782
+ spacing: this.options.spacing ?? 0,
783
+ children: (this.options.children ?? []).map((child) => child.toProtocol()),
784
+ }),
785
+ };
786
+ }
787
+ }
788
+
789
+ export type TreeNode =
790
+ | Hero
791
+ | Card
792
+ | Section
793
+ | Collapsible
794
+ | Item
795
+ | CollapsibleItem
796
+ | Meter
797
+ | Copyable
798
+ | Toast
799
+ | ActionRow
800
+ | ActionMenu
801
+ | DetailGrid
802
+ | EmptyState
803
+ | Badge
804
+ | StatusDot
805
+ | Box
806
+ | Row
807
+ | Column
808
+ | Grid
809
+ | Scroll
810
+ | Progress
811
+ | Separator
812
+ | Spinner
813
+ | Label
814
+ | IconWidget
815
+ | Image
816
+ | Button
817
+ | Switch
818
+ | Scale
819
+ | Dropdown
820
+ | Checkbox;