@termuijs/widgets 0.1.3 → 0.1.5
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 +88 -39
- package/dist/index.cjs +2142 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +800 -1
- package/dist/index.d.ts +800 -1
- package/dist/index.js +2132 -47
- package/dist/index.js.map +1 -1
- package/package.json +13 -8
- package/LICENSE +0 -21
package/dist/index.cjs
CHANGED
|
@@ -20,22 +20,49 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
Banner: () => Banner,
|
|
23
24
|
BarChart: () => BarChart,
|
|
25
|
+
BigText: () => BigText,
|
|
24
26
|
Box: () => Box,
|
|
27
|
+
Card: () => Card,
|
|
28
|
+
Center: () => Center,
|
|
29
|
+
ChatMessage: () => ChatMessage,
|
|
30
|
+
Columns: () => Columns,
|
|
31
|
+
CommandPalette: () => CommandPalette,
|
|
32
|
+
Definition: () => Definition,
|
|
33
|
+
DiffView: () => DiffView,
|
|
25
34
|
Gauge: () => Gauge,
|
|
35
|
+
Gradient: () => Gradient,
|
|
36
|
+
Grid: () => Grid,
|
|
37
|
+
HeatMap: () => HeatMap,
|
|
38
|
+
JSONView: () => JSONView,
|
|
39
|
+
KeyValue: () => KeyValue,
|
|
40
|
+
LineChart: () => LineChart,
|
|
26
41
|
List: () => List,
|
|
27
42
|
LogView: () => LogView,
|
|
43
|
+
MultiProgress: () => MultiProgress,
|
|
28
44
|
ProgressBar: () => ProgressBar,
|
|
29
45
|
SPINNER_FRAMES: () => SPINNER_FRAMES,
|
|
46
|
+
ScrollView: () => ScrollView,
|
|
30
47
|
Scrollbar: () => Scrollbar,
|
|
48
|
+
Sidebar: () => Sidebar,
|
|
49
|
+
Skeleton: () => Skeleton,
|
|
31
50
|
Sparkline: () => Sparkline,
|
|
32
51
|
Spinner: () => Spinner,
|
|
33
52
|
StatusIndicator: () => StatusIndicator,
|
|
53
|
+
StatusMessage: () => StatusMessage,
|
|
54
|
+
StreamingText: () => StreamingText,
|
|
34
55
|
Table: () => Table,
|
|
35
56
|
Text: () => Text,
|
|
36
57
|
TextInput: () => TextInput,
|
|
58
|
+
ToolApproval: () => ToolApproval,
|
|
59
|
+
ToolCall: () => ToolCall,
|
|
60
|
+
Tree: () => Tree,
|
|
37
61
|
VirtualList: () => VirtualList,
|
|
38
|
-
Widget: () => Widget
|
|
62
|
+
Widget: () => Widget,
|
|
63
|
+
computeRange: () => computeRange,
|
|
64
|
+
computeVariableRange: () => computeVariableRange,
|
|
65
|
+
jsonToTree: () => jsonToTree
|
|
39
66
|
});
|
|
40
67
|
module.exports = __toCommonJS(index_exports);
|
|
41
68
|
|
|
@@ -261,6 +288,7 @@ var Widget = class {
|
|
|
261
288
|
child.unmount();
|
|
262
289
|
}
|
|
263
290
|
this.events.emit("unmount", void 0);
|
|
291
|
+
this.events.removeAll();
|
|
264
292
|
}
|
|
265
293
|
};
|
|
266
294
|
|
|
@@ -426,8 +454,806 @@ var LogView = class extends Widget {
|
|
|
426
454
|
}
|
|
427
455
|
};
|
|
428
456
|
|
|
429
|
-
// src/
|
|
457
|
+
// src/display/Tree.ts
|
|
430
458
|
var import_core5 = require("@termuijs/core");
|
|
459
|
+
var Tree = class extends Widget {
|
|
460
|
+
_nodes;
|
|
461
|
+
_onSelect;
|
|
462
|
+
_indent;
|
|
463
|
+
_selectedIndex = 0;
|
|
464
|
+
_scrollOffset = 0;
|
|
465
|
+
_visibleNodes = [];
|
|
466
|
+
constructor(options, style = {}) {
|
|
467
|
+
super(style);
|
|
468
|
+
this._nodes = options.nodes;
|
|
469
|
+
this._onSelect = options.onSelect;
|
|
470
|
+
this._indent = options.indent ?? 2;
|
|
471
|
+
this.focusable = true;
|
|
472
|
+
this._buildVisibleNodes();
|
|
473
|
+
}
|
|
474
|
+
// ── Public API ─────────────────────────────────────
|
|
475
|
+
get selectedIndex() {
|
|
476
|
+
return this._selectedIndex;
|
|
477
|
+
}
|
|
478
|
+
get selectedNode() {
|
|
479
|
+
return this._visibleNodes[this._selectedIndex]?.node;
|
|
480
|
+
}
|
|
481
|
+
setNodes(nodes) {
|
|
482
|
+
this._nodes = nodes;
|
|
483
|
+
this._selectedIndex = 0;
|
|
484
|
+
this._scrollOffset = 0;
|
|
485
|
+
this._buildVisibleNodes();
|
|
486
|
+
this.markDirty();
|
|
487
|
+
}
|
|
488
|
+
/** Move cursor up one visible row */
|
|
489
|
+
movePrev() {
|
|
490
|
+
if (this._selectedIndex > 0) {
|
|
491
|
+
this._selectedIndex--;
|
|
492
|
+
this._clampScroll();
|
|
493
|
+
this.markDirty();
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/** Move cursor down one visible row */
|
|
497
|
+
moveNext() {
|
|
498
|
+
if (this._selectedIndex < this._visibleNodes.length - 1) {
|
|
499
|
+
this._selectedIndex++;
|
|
500
|
+
this._clampScroll();
|
|
501
|
+
this.markDirty();
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/** Go to first visible node */
|
|
505
|
+
moveFirst() {
|
|
506
|
+
this._selectedIndex = 0;
|
|
507
|
+
this._clampScroll();
|
|
508
|
+
this.markDirty();
|
|
509
|
+
}
|
|
510
|
+
/** Go to last visible node */
|
|
511
|
+
moveLast() {
|
|
512
|
+
if (this._visibleNodes.length > 0) {
|
|
513
|
+
this._selectedIndex = this._visibleNodes.length - 1;
|
|
514
|
+
this._clampScroll();
|
|
515
|
+
this.markDirty();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
/** Expand the selected node (if it's a collapsed parent) */
|
|
519
|
+
expand() {
|
|
520
|
+
const entry = this._visibleNodes[this._selectedIndex];
|
|
521
|
+
if (!entry) return;
|
|
522
|
+
const node = entry.node;
|
|
523
|
+
if (_isParent(node) && !node.expanded) {
|
|
524
|
+
node.expanded = true;
|
|
525
|
+
this._buildVisibleNodes();
|
|
526
|
+
this.markDirty();
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
/** Collapse the selected node, or move to parent if already collapsed/leaf */
|
|
530
|
+
collapse() {
|
|
531
|
+
const entry = this._visibleNodes[this._selectedIndex];
|
|
532
|
+
if (!entry) return;
|
|
533
|
+
const node = entry.node;
|
|
534
|
+
if (_isParent(node) && node.expanded) {
|
|
535
|
+
node.expanded = false;
|
|
536
|
+
this._buildVisibleNodes();
|
|
537
|
+
this._clampScroll();
|
|
538
|
+
this.markDirty();
|
|
539
|
+
} else if (entry.depth > 0) {
|
|
540
|
+
const parentPath = entry.path.slice(0, -1);
|
|
541
|
+
const parentIdx = this._visibleNodes.findIndex(
|
|
542
|
+
(e) => _pathsEqual(e.path, parentPath)
|
|
543
|
+
);
|
|
544
|
+
if (parentIdx >= 0) {
|
|
545
|
+
this._selectedIndex = parentIdx;
|
|
546
|
+
this._clampScroll();
|
|
547
|
+
this.markDirty();
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
/** Toggle expand/collapse (parent) or call onSelect (leaf) */
|
|
552
|
+
toggle() {
|
|
553
|
+
const entry = this._visibleNodes[this._selectedIndex];
|
|
554
|
+
if (!entry) return;
|
|
555
|
+
const node = entry.node;
|
|
556
|
+
if (_isParent(node)) {
|
|
557
|
+
node.expanded = !node.expanded;
|
|
558
|
+
this._buildVisibleNodes();
|
|
559
|
+
this._clampScroll();
|
|
560
|
+
this.markDirty();
|
|
561
|
+
} else {
|
|
562
|
+
this._onSelect?.(node, entry.path);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Handle a key event. Call this from your app's key-routing logic
|
|
567
|
+
* when this widget is focused.
|
|
568
|
+
*/
|
|
569
|
+
handleKey(key) {
|
|
570
|
+
switch (key) {
|
|
571
|
+
case "ArrowUp":
|
|
572
|
+
case "k":
|
|
573
|
+
this.movePrev();
|
|
574
|
+
break;
|
|
575
|
+
case "ArrowDown":
|
|
576
|
+
case "j":
|
|
577
|
+
this.moveNext();
|
|
578
|
+
break;
|
|
579
|
+
case "Enter":
|
|
580
|
+
case " ":
|
|
581
|
+
this.toggle();
|
|
582
|
+
break;
|
|
583
|
+
case "ArrowLeft":
|
|
584
|
+
case "h":
|
|
585
|
+
this.collapse();
|
|
586
|
+
break;
|
|
587
|
+
case "ArrowRight":
|
|
588
|
+
case "l":
|
|
589
|
+
this.expand();
|
|
590
|
+
break;
|
|
591
|
+
case "Home":
|
|
592
|
+
this.moveFirst();
|
|
593
|
+
break;
|
|
594
|
+
case "End":
|
|
595
|
+
this.moveLast();
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
// ── Rendering ──────────────────────────────────────
|
|
600
|
+
_renderSelf(screen) {
|
|
601
|
+
const rect = this._getContentRect();
|
|
602
|
+
const { x, y, width, height } = rect;
|
|
603
|
+
if (width <= 0 || height <= 0) return;
|
|
604
|
+
const attrs = (0, import_core5.styleToCellAttrs)(this._style);
|
|
605
|
+
const useUnicode = import_core5.caps.unicode;
|
|
606
|
+
const collapsedChevron = useUnicode ? "\u25B6 " : "> ";
|
|
607
|
+
const expandedChevron = useUnicode ? "\u25BC " : "v ";
|
|
608
|
+
const leafPrefix = useUnicode ? "\u2022 " : "* ";
|
|
609
|
+
const visibleCount = Math.min(
|
|
610
|
+
this._visibleNodes.length - this._scrollOffset,
|
|
611
|
+
height
|
|
612
|
+
);
|
|
613
|
+
for (let i = 0; i < visibleCount; i++) {
|
|
614
|
+
const entryIdx = this._scrollOffset + i;
|
|
615
|
+
const entry = this._visibleNodes[entryIdx];
|
|
616
|
+
const { node, depth } = entry;
|
|
617
|
+
const isSelected = entryIdx === this._selectedIndex;
|
|
618
|
+
const indentStr = " ".repeat(this._indent * depth);
|
|
619
|
+
let chevron;
|
|
620
|
+
if (_isParent(node)) {
|
|
621
|
+
chevron = node.expanded ? expandedChevron : collapsedChevron;
|
|
622
|
+
} else {
|
|
623
|
+
chevron = leafPrefix;
|
|
624
|
+
}
|
|
625
|
+
let line = indentStr + chevron + node.label;
|
|
626
|
+
line = (0, import_core5.truncate)(line, width);
|
|
627
|
+
const cellStyle = isSelected && this.isFocused ? {
|
|
628
|
+
...attrs,
|
|
629
|
+
bg: { type: "named", name: "blue" },
|
|
630
|
+
bold: true
|
|
631
|
+
} : isSelected ? { ...attrs, bold: true } : attrs;
|
|
632
|
+
screen.writeString(x, y + i, line, cellStyle);
|
|
633
|
+
if (isSelected && this.isFocused) {
|
|
634
|
+
const lineWidth = (0, import_core5.stringWidth)(line);
|
|
635
|
+
const remaining = width - lineWidth;
|
|
636
|
+
for (let c = 0; c < remaining; c++) {
|
|
637
|
+
screen.setCell(x + lineWidth + c, y + i, {
|
|
638
|
+
char: " ",
|
|
639
|
+
...cellStyle
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
// ── Private helpers ────────────────────────────────
|
|
646
|
+
/** Rebuild the flat visible-node list from the tree */
|
|
647
|
+
_buildVisibleNodes() {
|
|
648
|
+
this._visibleNodes = [];
|
|
649
|
+
_collectVisible(this._nodes, 0, [], this._visibleNodes);
|
|
650
|
+
}
|
|
651
|
+
/** Ensure scroll keeps the selected index in view */
|
|
652
|
+
_clampScroll() {
|
|
653
|
+
const rect = this._getContentRect();
|
|
654
|
+
const visibleHeight = rect.height > 0 ? rect.height : 24;
|
|
655
|
+
if (this._selectedIndex < this._scrollOffset) {
|
|
656
|
+
this._scrollOffset = this._selectedIndex;
|
|
657
|
+
}
|
|
658
|
+
if (this._selectedIndex >= this._scrollOffset + visibleHeight) {
|
|
659
|
+
this._scrollOffset = this._selectedIndex - visibleHeight + 1;
|
|
660
|
+
}
|
|
661
|
+
this._scrollOffset = Math.max(0, this._scrollOffset);
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
function _isParent(node) {
|
|
665
|
+
return Array.isArray(node.children) && node.children.length > 0;
|
|
666
|
+
}
|
|
667
|
+
function _pathsEqual(a, b) {
|
|
668
|
+
if (a.length !== b.length) return false;
|
|
669
|
+
for (let i = 0; i < a.length; i++) {
|
|
670
|
+
if (a[i] !== b[i]) return false;
|
|
671
|
+
}
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
function _collectVisible(nodes, depth, parentPath, out) {
|
|
675
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
676
|
+
const node = nodes[i];
|
|
677
|
+
const path = [...parentPath, i];
|
|
678
|
+
out.push({ node, depth, path });
|
|
679
|
+
if (_isParent(node) && node.expanded) {
|
|
680
|
+
_collectVisible(node.children, depth + 1, path, out);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// src/display/JSONView.ts
|
|
686
|
+
var import_core6 = require("@termuijs/core");
|
|
687
|
+
function jsonToTree(value, key) {
|
|
688
|
+
const prefix = key !== void 0 ? `${key}: ` : "";
|
|
689
|
+
if (value === null) {
|
|
690
|
+
return {
|
|
691
|
+
label: `${prefix}null`,
|
|
692
|
+
data: { type: "null", key }
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (typeof value === "boolean") {
|
|
696
|
+
return {
|
|
697
|
+
label: `${prefix}${value}`,
|
|
698
|
+
data: { type: "boolean", key, value }
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
if (typeof value === "number") {
|
|
702
|
+
return {
|
|
703
|
+
label: `${prefix}${value}`,
|
|
704
|
+
data: { type: "number", key, value }
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
if (typeof value === "string") {
|
|
708
|
+
return {
|
|
709
|
+
label: `${prefix}"${value}"`,
|
|
710
|
+
data: { type: "string", key, value }
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
if (Array.isArray(value)) {
|
|
714
|
+
const children = value.map((v, i) => jsonToTree(v, String(i)));
|
|
715
|
+
return {
|
|
716
|
+
label: `${prefix}[${children.length}]`,
|
|
717
|
+
children,
|
|
718
|
+
expanded: false,
|
|
719
|
+
data: { type: "array", key }
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
if (typeof value === "object") {
|
|
723
|
+
const obj = value;
|
|
724
|
+
const children = Object.keys(obj).map((k) => jsonToTree(obj[k], k));
|
|
725
|
+
return {
|
|
726
|
+
label: `${prefix}{${children.length}}`,
|
|
727
|
+
children,
|
|
728
|
+
expanded: false,
|
|
729
|
+
data: { type: "object", key }
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
return {
|
|
733
|
+
label: `${prefix}${String(value)}`,
|
|
734
|
+
data: { type: "unknown", key }
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
function _valueColor(type) {
|
|
738
|
+
switch (type) {
|
|
739
|
+
case "string":
|
|
740
|
+
return { type: "named", name: "green" };
|
|
741
|
+
case "number":
|
|
742
|
+
return { type: "named", name: "yellow" };
|
|
743
|
+
case "boolean":
|
|
744
|
+
return { type: "named", name: "magenta" };
|
|
745
|
+
case "null":
|
|
746
|
+
return { type: "named", name: "magenta" };
|
|
747
|
+
default:
|
|
748
|
+
return { type: "named", name: "white" };
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
var KEY_COLOR = { type: "named", name: "cyan" };
|
|
752
|
+
function _splitLabel(label, nodeData) {
|
|
753
|
+
if (nodeData.key !== void 0) {
|
|
754
|
+
const sep = `${nodeData.key}: `;
|
|
755
|
+
if (label.startsWith(sep)) {
|
|
756
|
+
return { keyPart: sep, valuePart: label.slice(sep.length) };
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return { keyPart: "", valuePart: label };
|
|
760
|
+
}
|
|
761
|
+
var JSONView = class extends Tree {
|
|
762
|
+
constructor(options, style = {}) {
|
|
763
|
+
const root = jsonToTree(options.data);
|
|
764
|
+
const nodes = root.children && root.children.length > 0 ? root.children : [root];
|
|
765
|
+
super({ nodes, onSelect: options.onSelect, indent: options.indent }, style);
|
|
766
|
+
}
|
|
767
|
+
// ── Override rendering ─────────────────────────────
|
|
768
|
+
/**
|
|
769
|
+
* Replicate Tree's _renderSelf but colorize key/value segments.
|
|
770
|
+
* We access the private state via `(this as any)` since Tree doesn't
|
|
771
|
+
* expose those fields publicly — the tradeoff of extending vs composing.
|
|
772
|
+
*/
|
|
773
|
+
_renderSelf(screen) {
|
|
774
|
+
const rect = this._getContentRect();
|
|
775
|
+
const { x, y, width, height } = rect;
|
|
776
|
+
if (width <= 0 || height <= 0) return;
|
|
777
|
+
const attrs = (0, import_core6.styleToCellAttrs)(this._style);
|
|
778
|
+
const useUnicode = import_core6.caps.unicode;
|
|
779
|
+
const collapsedChevron = useUnicode ? "\u25B6 " : "> ";
|
|
780
|
+
const expandedChevron = useUnicode ? "\u25BC " : "v ";
|
|
781
|
+
const leafPrefix = useUnicode ? "\u2022 " : "* ";
|
|
782
|
+
const visibleNodes = this._visibleNodes;
|
|
783
|
+
const scrollOffset = this._scrollOffset;
|
|
784
|
+
const selectedIndex = this._selectedIndex;
|
|
785
|
+
const indent = this._indent;
|
|
786
|
+
const visibleCount = Math.min(
|
|
787
|
+
visibleNodes.length - scrollOffset,
|
|
788
|
+
height
|
|
789
|
+
);
|
|
790
|
+
for (let i = 0; i < visibleCount; i++) {
|
|
791
|
+
const entryIdx = scrollOffset + i;
|
|
792
|
+
const entry = visibleNodes[entryIdx];
|
|
793
|
+
const { node, depth } = entry;
|
|
794
|
+
const isSelected = entryIdx === selectedIndex;
|
|
795
|
+
const nodeData = node.data ?? { type: "unknown" };
|
|
796
|
+
const indentStr = " ".repeat(indent * depth);
|
|
797
|
+
const isParent = Array.isArray(node.children) && node.children.length > 0;
|
|
798
|
+
let chevron;
|
|
799
|
+
if (isParent) {
|
|
800
|
+
chevron = node.expanded ? expandedChevron : collapsedChevron;
|
|
801
|
+
} else {
|
|
802
|
+
chevron = leafPrefix;
|
|
803
|
+
}
|
|
804
|
+
const linePrefix = indentStr + chevron;
|
|
805
|
+
const { keyPart, valuePart } = _splitLabel(node.label, nodeData);
|
|
806
|
+
const baseCellStyle = isSelected && this.isFocused ? {
|
|
807
|
+
...attrs,
|
|
808
|
+
bg: { type: "named", name: "blue" },
|
|
809
|
+
bold: true
|
|
810
|
+
} : isSelected ? { ...attrs, bold: true } : attrs;
|
|
811
|
+
let cursorX = x;
|
|
812
|
+
const prefixTrunc = (0, import_core6.truncate)(linePrefix, width);
|
|
813
|
+
if (prefixTrunc.length > 0) {
|
|
814
|
+
screen.writeString(cursorX, y + i, prefixTrunc, baseCellStyle);
|
|
815
|
+
cursorX += (0, import_core6.stringWidth)(prefixTrunc);
|
|
816
|
+
}
|
|
817
|
+
const remaining = width - (cursorX - x);
|
|
818
|
+
if (remaining <= 0) {
|
|
819
|
+
_fillSelection(screen, x, y + i, width, cursorX - x, isSelected, this.isFocused, baseCellStyle);
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
if (keyPart.length > 0) {
|
|
823
|
+
const keyTrunc = (0, import_core6.truncate)(keyPart, remaining);
|
|
824
|
+
const keyStyle = { ...baseCellStyle, fg: KEY_COLOR };
|
|
825
|
+
screen.writeString(cursorX, y + i, keyTrunc, keyStyle);
|
|
826
|
+
cursorX += (0, import_core6.stringWidth)(keyTrunc);
|
|
827
|
+
}
|
|
828
|
+
const remaining2 = width - (cursorX - x);
|
|
829
|
+
if (remaining2 <= 0) {
|
|
830
|
+
_fillSelection(screen, x, y + i, width, cursorX - x, isSelected, this.isFocused, baseCellStyle);
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
if (valuePart.length > 0) {
|
|
834
|
+
const valTrunc = (0, import_core6.truncate)(valuePart, remaining2);
|
|
835
|
+
const valColor = _valueColor(nodeData.type);
|
|
836
|
+
const valStyle = { ...baseCellStyle, fg: valColor };
|
|
837
|
+
screen.writeString(cursorX, y + i, valTrunc, valStyle);
|
|
838
|
+
cursorX += (0, import_core6.stringWidth)(valTrunc);
|
|
839
|
+
}
|
|
840
|
+
_fillSelection(screen, x, y + i, width, cursorX - x, isSelected, this.isFocused, baseCellStyle);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
function _fillSelection(screen, rowX, rowY, width, writtenWidth, isSelected, isFocused, cellStyle) {
|
|
845
|
+
if (!isSelected || !isFocused) return;
|
|
846
|
+
const remaining = width - writtenWidth;
|
|
847
|
+
for (let c = 0; c < remaining; c++) {
|
|
848
|
+
screen.setCell(rowX + writtenWidth + c, rowY, {
|
|
849
|
+
char: " ",
|
|
850
|
+
...cellStyle
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/display/DiffView.ts
|
|
856
|
+
var import_core7 = require("@termuijs/core");
|
|
857
|
+
var DiffView = class extends Widget {
|
|
858
|
+
_lines;
|
|
859
|
+
_scrollOffset = 0;
|
|
860
|
+
_showLineNumbers;
|
|
861
|
+
_gutterWidth;
|
|
862
|
+
constructor(options, style = {}) {
|
|
863
|
+
super(style);
|
|
864
|
+
this._lines = options.lines;
|
|
865
|
+
this._showLineNumbers = options.showLineNumbers ?? true;
|
|
866
|
+
this._gutterWidth = options.gutterWidth ?? 5;
|
|
867
|
+
this.focusable = true;
|
|
868
|
+
}
|
|
869
|
+
setLines(lines) {
|
|
870
|
+
this._lines = lines;
|
|
871
|
+
this._scrollOffset = 0;
|
|
872
|
+
this.markDirty();
|
|
873
|
+
}
|
|
874
|
+
_renderSelf(screen) {
|
|
875
|
+
const rect = this._getContentRect();
|
|
876
|
+
const { x, y, width, height } = rect;
|
|
877
|
+
if (width <= 0 || height <= 0) return;
|
|
878
|
+
const baseAttrs = (0, import_core7.styleToCellAttrs)(this._style);
|
|
879
|
+
const visibleLines = this._lines.slice(
|
|
880
|
+
this._scrollOffset,
|
|
881
|
+
this._scrollOffset + height
|
|
882
|
+
);
|
|
883
|
+
for (let i = 0; i < visibleLines.length; i++) {
|
|
884
|
+
const diffLine = visibleLines[i];
|
|
885
|
+
let col = x;
|
|
886
|
+
const row = y + i;
|
|
887
|
+
const isAdd = diffLine.type === "add";
|
|
888
|
+
const isRemove = diffLine.type === "remove";
|
|
889
|
+
const isContext = diffLine.type === "context";
|
|
890
|
+
const fg = isAdd ? { type: "named", name: "green" } : isRemove ? { type: "named", name: "red" } : void 0;
|
|
891
|
+
const lineAttrs = {
|
|
892
|
+
...baseAttrs,
|
|
893
|
+
...fg ? { fg } : {},
|
|
894
|
+
dim: isContext
|
|
895
|
+
};
|
|
896
|
+
if (this._showLineNumbers) {
|
|
897
|
+
const gutterStr = diffLine.lineNo !== void 0 ? String(diffLine.lineNo).padStart(this._gutterWidth - 1, " ") + " " : " ".repeat(this._gutterWidth);
|
|
898
|
+
const gutterAttrs = { ...baseAttrs, dim: true };
|
|
899
|
+
screen.writeString(col, row, gutterStr.slice(0, this._gutterWidth), gutterAttrs);
|
|
900
|
+
col += this._gutterWidth;
|
|
901
|
+
}
|
|
902
|
+
const prefix = isAdd ? "+" : isRemove ? "-" : " ";
|
|
903
|
+
const remainingWidth = width - (col - x);
|
|
904
|
+
if (remainingWidth <= 0) continue;
|
|
905
|
+
screen.writeString(col, row, prefix, lineAttrs);
|
|
906
|
+
col += 1;
|
|
907
|
+
const contentWidth = width - (col - x);
|
|
908
|
+
if (contentWidth <= 0) continue;
|
|
909
|
+
const content = (0, import_core7.truncate)(diffLine.content, contentWidth);
|
|
910
|
+
screen.writeString(col, row, content, lineAttrs);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
handleKey(key) {
|
|
914
|
+
const rect = this._getContentRect();
|
|
915
|
+
const visibleHeight = Math.max(1, rect.height);
|
|
916
|
+
const maxOffset = Math.max(0, this._lines.length - visibleHeight);
|
|
917
|
+
switch (key) {
|
|
918
|
+
case "ArrowUp":
|
|
919
|
+
case "k":
|
|
920
|
+
this._scrollOffset = Math.max(0, this._scrollOffset - 1);
|
|
921
|
+
this.markDirty();
|
|
922
|
+
break;
|
|
923
|
+
case "ArrowDown":
|
|
924
|
+
case "j":
|
|
925
|
+
this._scrollOffset = Math.min(maxOffset, this._scrollOffset + 1);
|
|
926
|
+
this.markDirty();
|
|
927
|
+
break;
|
|
928
|
+
case "PageUp":
|
|
929
|
+
this._scrollOffset = Math.max(0, this._scrollOffset - visibleHeight);
|
|
930
|
+
this.markDirty();
|
|
931
|
+
break;
|
|
932
|
+
case "PageDown":
|
|
933
|
+
this._scrollOffset = Math.min(maxOffset, this._scrollOffset + visibleHeight);
|
|
934
|
+
this.markDirty();
|
|
935
|
+
break;
|
|
936
|
+
case "Home":
|
|
937
|
+
this._scrollOffset = 0;
|
|
938
|
+
this.markDirty();
|
|
939
|
+
break;
|
|
940
|
+
case "End":
|
|
941
|
+
this._scrollOffset = maxOffset;
|
|
942
|
+
this.markDirty();
|
|
943
|
+
break;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
// src/display/StreamingText.ts
|
|
949
|
+
var import_core8 = require("@termuijs/core");
|
|
950
|
+
var import_motion = require("@termuijs/motion");
|
|
951
|
+
var StreamingText = class extends Widget {
|
|
952
|
+
_text;
|
|
953
|
+
_cursor;
|
|
954
|
+
_speed;
|
|
955
|
+
_blinkInterval;
|
|
956
|
+
/** Number of characters currently revealed (used when speed > 0) */
|
|
957
|
+
_revealed;
|
|
958
|
+
_cursorVisible;
|
|
959
|
+
_blinkUnsub;
|
|
960
|
+
constructor(options, style = {}) {
|
|
961
|
+
super(style);
|
|
962
|
+
this._text = options.text;
|
|
963
|
+
this._cursor = options.cursor ?? (import_core8.caps.unicode ? "\u258B" : "_");
|
|
964
|
+
this._speed = options.speed ?? 0;
|
|
965
|
+
this._blinkInterval = options.blinkInterval ?? 530;
|
|
966
|
+
this._revealed = 0;
|
|
967
|
+
this._cursorVisible = true;
|
|
968
|
+
}
|
|
969
|
+
/** Replace text content and reset the revealed counter to 0. */
|
|
970
|
+
setText(text) {
|
|
971
|
+
this._text = text;
|
|
972
|
+
this._revealed = 0;
|
|
973
|
+
this.markDirty();
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Advance `_revealed` by `speed` characters.
|
|
977
|
+
* Call this from an external tick/render loop when `speed > 0`.
|
|
978
|
+
*/
|
|
979
|
+
tick() {
|
|
980
|
+
if (this._speed <= 0 || this.isComplete()) return;
|
|
981
|
+
this._revealed = Math.min(this._revealed + this._speed, this._text.length);
|
|
982
|
+
this.markDirty();
|
|
983
|
+
}
|
|
984
|
+
/** Returns true when all text has been revealed. */
|
|
985
|
+
isComplete() {
|
|
986
|
+
if (this._speed === 0) return true;
|
|
987
|
+
return this._revealed >= this._text.length;
|
|
988
|
+
}
|
|
989
|
+
/** Lifecycle: start the blink timer (only when motion is enabled). */
|
|
990
|
+
mount() {
|
|
991
|
+
super.mount();
|
|
992
|
+
if (!import_core8.caps.motion) {
|
|
993
|
+
this._cursorVisible = false;
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
this._blinkUnsub = (0, import_motion.timerPoolSubscribe)(this._blinkInterval, () => {
|
|
997
|
+
this._cursorVisible = !this._cursorVisible;
|
|
998
|
+
this.markDirty();
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
/** Lifecycle: stop the blink timer. */
|
|
1002
|
+
unmount() {
|
|
1003
|
+
this._blinkUnsub?.();
|
|
1004
|
+
this._blinkUnsub = void 0;
|
|
1005
|
+
super.unmount();
|
|
1006
|
+
}
|
|
1007
|
+
_renderSelf(screen) {
|
|
1008
|
+
const rect = this._getContentRect();
|
|
1009
|
+
const { x, y, width, height } = rect;
|
|
1010
|
+
if (width <= 0 || height <= 0) return;
|
|
1011
|
+
const attrs = (0, import_core8.styleToCellAttrs)(this._style);
|
|
1012
|
+
const displayText = this._speed > 0 ? this._text.slice(0, this._revealed) : this._text;
|
|
1013
|
+
const fullText = this._cursorVisible ? displayText + this._cursor : displayText;
|
|
1014
|
+
const wrapped = (0, import_core8.wordWrap)(fullText, width);
|
|
1015
|
+
const lines = wrapped.split("\n");
|
|
1016
|
+
const limit = Math.min(lines.length, height);
|
|
1017
|
+
for (let i = 0; i < limit; i++) {
|
|
1018
|
+
const line = lines[i];
|
|
1019
|
+
if (line === void 0) continue;
|
|
1020
|
+
screen.writeString(x, y + i, line, attrs);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
|
|
1025
|
+
// src/display/ChatMessage.ts
|
|
1026
|
+
var import_core9 = require("@termuijs/core");
|
|
1027
|
+
var ROLE_CONFIG = {
|
|
1028
|
+
user: { badge: "[User]", colorName: "cyan" },
|
|
1029
|
+
assistant: { badge: "[Assistant]", colorName: "green" },
|
|
1030
|
+
system: { badge: "[System]", colorName: "yellow" },
|
|
1031
|
+
tool: { badge: "[Tool]", colorName: "magenta" }
|
|
1032
|
+
};
|
|
1033
|
+
var ChatMessage = class extends Widget {
|
|
1034
|
+
_role;
|
|
1035
|
+
_content;
|
|
1036
|
+
_timestamp;
|
|
1037
|
+
constructor(options, style = {}) {
|
|
1038
|
+
super(style);
|
|
1039
|
+
this._role = options.role;
|
|
1040
|
+
this._content = options.content;
|
|
1041
|
+
this._timestamp = options.timestamp;
|
|
1042
|
+
this.focusable = false;
|
|
1043
|
+
}
|
|
1044
|
+
/** Update the message content and mark dirty. */
|
|
1045
|
+
setContent(content) {
|
|
1046
|
+
this._content = content;
|
|
1047
|
+
this.markDirty();
|
|
1048
|
+
}
|
|
1049
|
+
/** Update the message role and mark dirty. */
|
|
1050
|
+
setRole(role) {
|
|
1051
|
+
this._role = role;
|
|
1052
|
+
this.markDirty();
|
|
1053
|
+
}
|
|
1054
|
+
_renderSelf(screen) {
|
|
1055
|
+
const rect = this._getContentRect();
|
|
1056
|
+
const { x, y, width, height } = rect;
|
|
1057
|
+
if (width <= 0 || height <= 0) return;
|
|
1058
|
+
const config = ROLE_CONFIG[this._role];
|
|
1059
|
+
const baseAttrs = (0, import_core9.styleToCellAttrs)(this._style);
|
|
1060
|
+
const badgeAttrs = {
|
|
1061
|
+
...baseAttrs,
|
|
1062
|
+
fg: { type: "named", name: config.colorName }
|
|
1063
|
+
};
|
|
1064
|
+
screen.writeString(x, y, config.badge, badgeAttrs);
|
|
1065
|
+
if (this._timestamp) {
|
|
1066
|
+
const ts = this._timestamp.toLocaleTimeString("en-GB", {
|
|
1067
|
+
hour: "2-digit",
|
|
1068
|
+
minute: "2-digit",
|
|
1069
|
+
second: "2-digit",
|
|
1070
|
+
hour12: false
|
|
1071
|
+
});
|
|
1072
|
+
const tsWidth = (0, import_core9.stringWidth)(ts);
|
|
1073
|
+
const tsX = x + width - tsWidth;
|
|
1074
|
+
if (tsX > x + (0, import_core9.stringWidth)(config.badge)) {
|
|
1075
|
+
const dimAttrs = { ...baseAttrs, dim: true };
|
|
1076
|
+
screen.writeString(tsX, y, ts, dimAttrs);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
if (height <= 1) return;
|
|
1080
|
+
const indent = " ";
|
|
1081
|
+
const contentWidth = Math.max(0, width - indent.length);
|
|
1082
|
+
const lines = contentWidth > 0 ? (0, import_core9.wordWrap)(this._content, contentWidth).split("\n") : [];
|
|
1083
|
+
const maxContentRows = height - 1;
|
|
1084
|
+
for (let i = 0; i < Math.min(lines.length, maxContentRows); i++) {
|
|
1085
|
+
const line = lines[i];
|
|
1086
|
+
if (line === void 0) continue;
|
|
1087
|
+
const displayLine = (0, import_core9.truncate)(indent + line, width);
|
|
1088
|
+
screen.writeString(x, y + 1 + i, displayLine, baseAttrs);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
// src/display/ToolCall.ts
|
|
1094
|
+
var import_core10 = require("@termuijs/core");
|
|
1095
|
+
var STATUS_CONFIG = {
|
|
1096
|
+
pending: { unicodeSymbol: "\u25CC", asciiSymbol: "?", colorName: "white", dim: true },
|
|
1097
|
+
running: { unicodeSymbol: "\u25CE", asciiSymbol: "~", colorName: "yellow" },
|
|
1098
|
+
done: { unicodeSymbol: "\u2713", asciiSymbol: "+", colorName: "green" },
|
|
1099
|
+
error: { unicodeSymbol: "\u2717", asciiSymbol: "!", colorName: "red" }
|
|
1100
|
+
};
|
|
1101
|
+
var ToolCall = class extends Widget {
|
|
1102
|
+
_name;
|
|
1103
|
+
_args;
|
|
1104
|
+
_result;
|
|
1105
|
+
_status;
|
|
1106
|
+
_collapsed;
|
|
1107
|
+
constructor(options, style = {}) {
|
|
1108
|
+
super(style);
|
|
1109
|
+
this._name = options.name;
|
|
1110
|
+
this._args = options.args;
|
|
1111
|
+
this._result = options.result;
|
|
1112
|
+
this._status = options.status;
|
|
1113
|
+
this._collapsed = options.collapsed ?? true;
|
|
1114
|
+
this.focusable = true;
|
|
1115
|
+
}
|
|
1116
|
+
// ── Public API ─────────────────────────────────────
|
|
1117
|
+
setStatus(status) {
|
|
1118
|
+
this._status = status;
|
|
1119
|
+
this.markDirty();
|
|
1120
|
+
}
|
|
1121
|
+
setResult(result) {
|
|
1122
|
+
this._result = result;
|
|
1123
|
+
this.markDirty();
|
|
1124
|
+
}
|
|
1125
|
+
collapse() {
|
|
1126
|
+
this._collapsed = true;
|
|
1127
|
+
this.markDirty();
|
|
1128
|
+
}
|
|
1129
|
+
expand() {
|
|
1130
|
+
this._collapsed = false;
|
|
1131
|
+
this.markDirty();
|
|
1132
|
+
}
|
|
1133
|
+
handleKey(key) {
|
|
1134
|
+
if (key === " " || key === "Enter") {
|
|
1135
|
+
this._collapsed = !this._collapsed;
|
|
1136
|
+
this.markDirty();
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
// ── Rendering ──────────────────────────────────────
|
|
1140
|
+
_renderSelf(screen) {
|
|
1141
|
+
const rect = this._getContentRect();
|
|
1142
|
+
const { x, y, width, height } = rect;
|
|
1143
|
+
if (width <= 0 || height <= 0) return;
|
|
1144
|
+
const useUnicode = import_core10.caps.unicode;
|
|
1145
|
+
const baseAttrs = (0, import_core10.styleToCellAttrs)(this._style);
|
|
1146
|
+
const config = STATUS_CONFIG[this._status];
|
|
1147
|
+
const collapsedChevron = useUnicode ? "\u25B6" : ">";
|
|
1148
|
+
const expandedChevron = useUnicode ? "\u25BC" : "v";
|
|
1149
|
+
const chevron = this._collapsed ? collapsedChevron : expandedChevron;
|
|
1150
|
+
const symbol = useUnicode ? config.unicodeSymbol : config.asciiSymbol;
|
|
1151
|
+
const statusAttrs = {
|
|
1152
|
+
...baseAttrs,
|
|
1153
|
+
fg: { type: "named", name: config.colorName },
|
|
1154
|
+
bold: config.bold ?? false,
|
|
1155
|
+
dim: config.dim ?? false
|
|
1156
|
+
};
|
|
1157
|
+
const headerText = `${chevron} ${this._name} ${symbol} [${this._status}]`;
|
|
1158
|
+
screen.writeString(x, y, (0, import_core10.truncate)(headerText, width), baseAttrs);
|
|
1159
|
+
const symbolOffset = chevron.length + 1 + this._name.length + 1;
|
|
1160
|
+
if (symbolOffset < width) {
|
|
1161
|
+
screen.writeString(x + symbolOffset, y, symbol, statusAttrs);
|
|
1162
|
+
}
|
|
1163
|
+
if (this._collapsed) return;
|
|
1164
|
+
let row = 1;
|
|
1165
|
+
const argEntries = Object.entries(this._args);
|
|
1166
|
+
for (const [key, value] of argEntries) {
|
|
1167
|
+
if (row >= height) break;
|
|
1168
|
+
const argLine = ` ${key}: ${JSON.stringify(value)}`;
|
|
1169
|
+
screen.writeString(x, y + row, (0, import_core10.truncate)(argLine, width), baseAttrs);
|
|
1170
|
+
row++;
|
|
1171
|
+
}
|
|
1172
|
+
if (row < height && this._result !== void 0 && (this._status === "done" || this._status === "error")) {
|
|
1173
|
+
const resultStr = typeof this._result === "string" ? this._result : JSON.stringify(this._result);
|
|
1174
|
+
const resultLine = ` result: ${resultStr}`;
|
|
1175
|
+
screen.writeString(x, y + row, (0, import_core10.truncate)(resultLine, width), baseAttrs);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
var ToolApproval = class extends ToolCall {
|
|
1180
|
+
_onApprove;
|
|
1181
|
+
_onDeny;
|
|
1182
|
+
constructor(options, style = {}) {
|
|
1183
|
+
super(options, style);
|
|
1184
|
+
this._onApprove = options.onApprove;
|
|
1185
|
+
this._onDeny = options.onDeny;
|
|
1186
|
+
}
|
|
1187
|
+
_renderSelf(screen) {
|
|
1188
|
+
super._renderSelf(screen);
|
|
1189
|
+
const rect = this._getContentRect();
|
|
1190
|
+
const { x, y, width, height } = rect;
|
|
1191
|
+
if (width <= 0 || height <= 0) return;
|
|
1192
|
+
let rowsUsed = 1;
|
|
1193
|
+
if (!this._collapsed) {
|
|
1194
|
+
rowsUsed += Object.keys(this._args).length;
|
|
1195
|
+
if (this._result !== void 0 && (this._status === "done" || this._status === "error")) {
|
|
1196
|
+
rowsUsed += 1;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
const approvalRow = y + rowsUsed;
|
|
1200
|
+
if (approvalRow >= y + height) return;
|
|
1201
|
+
const baseAttrs = (0, import_core10.styleToCellAttrs)(this._style);
|
|
1202
|
+
const approveAttrs = {
|
|
1203
|
+
...baseAttrs,
|
|
1204
|
+
fg: { type: "named", name: "green" },
|
|
1205
|
+
bold: true
|
|
1206
|
+
};
|
|
1207
|
+
const denyAttrs = {
|
|
1208
|
+
...baseAttrs,
|
|
1209
|
+
fg: { type: "named", name: "red" },
|
|
1210
|
+
bold: true
|
|
1211
|
+
};
|
|
1212
|
+
const approveText = "[y] Approve";
|
|
1213
|
+
const denyText = "[n] Deny";
|
|
1214
|
+
screen.writeString(x, approvalRow, approveText, approveAttrs);
|
|
1215
|
+
const denyX = x + approveText.length + 2;
|
|
1216
|
+
if (denyX + denyText.length <= x + width) {
|
|
1217
|
+
screen.writeString(denyX, approvalRow, denyText, denyAttrs);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
handleKey(key) {
|
|
1221
|
+
if (key === "y" || key === "Enter") {
|
|
1222
|
+
this._onApprove?.();
|
|
1223
|
+
} else if (key === "n" || key === "Escape") {
|
|
1224
|
+
this._onDeny?.();
|
|
1225
|
+
} else {
|
|
1226
|
+
super.handleKey(key);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
|
|
1231
|
+
// src/input/virtual-scroll.ts
|
|
1232
|
+
function computeRange(scrollOffset, viewportItems, itemCount, overscan = 2) {
|
|
1233
|
+
const start = Math.max(0, scrollOffset - overscan);
|
|
1234
|
+
const end = Math.min(itemCount, scrollOffset + viewportItems + overscan);
|
|
1235
|
+
return { start, end, offsetPx: start };
|
|
1236
|
+
}
|
|
1237
|
+
function computeVariableRange(scrollPx, viewportPx, sizes, overscan = 2) {
|
|
1238
|
+
const cumulative = [];
|
|
1239
|
+
let sum = 0;
|
|
1240
|
+
for (const s of sizes) {
|
|
1241
|
+
cumulative.push(sum);
|
|
1242
|
+
sum += s;
|
|
1243
|
+
}
|
|
1244
|
+
cumulative.push(sum);
|
|
1245
|
+
let startIdx = cumulative.findIndex((c, i) => i < sizes.length && c + sizes[i] > scrollPx);
|
|
1246
|
+
if (startIdx < 0) startIdx = sizes.length;
|
|
1247
|
+
startIdx = Math.max(0, startIdx - overscan);
|
|
1248
|
+
const viewportEnd = scrollPx + viewportPx;
|
|
1249
|
+
let endIdx = cumulative.findIndex((c) => c >= viewportEnd);
|
|
1250
|
+
if (endIdx < 0) endIdx = sizes.length;
|
|
1251
|
+
endIdx = Math.min(sizes.length, endIdx + overscan);
|
|
1252
|
+
return { start: startIdx, end: endIdx, offsetPx: cumulative[startIdx] };
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// src/input/List.ts
|
|
1256
|
+
var import_core11 = require("@termuijs/core");
|
|
431
1257
|
var List = class extends Widget {
|
|
432
1258
|
_items;
|
|
433
1259
|
_selectedIndex = 0;
|
|
@@ -482,15 +1308,15 @@ var List = class extends Widget {
|
|
|
482
1308
|
const rect = this._getContentRect();
|
|
483
1309
|
const { x, y, width, height } = rect;
|
|
484
1310
|
if (width <= 0 || height <= 0) return;
|
|
485
|
-
const attrs = (0,
|
|
1311
|
+
const attrs = (0, import_core11.styleToCellAttrs)(this._style);
|
|
486
1312
|
const visibleCount = Math.min(this._items.length - this._scrollOffset, height);
|
|
487
1313
|
for (let i = 0; i < visibleCount; i++) {
|
|
488
1314
|
const itemIdx = this._scrollOffset + i;
|
|
489
1315
|
const item = this._items[itemIdx];
|
|
490
1316
|
const isSelected = itemIdx === this._selectedIndex;
|
|
491
|
-
const prefix = isSelected ? "\u25B8 " : " ";
|
|
1317
|
+
const prefix = isSelected ? import_core11.caps.unicode ? "\u25B8 " : "> " : " ";
|
|
492
1318
|
let line = prefix + item.label;
|
|
493
|
-
line = (0,
|
|
1319
|
+
line = (0, import_core11.truncate)(line, width);
|
|
494
1320
|
const cellStyle = {
|
|
495
1321
|
...attrs,
|
|
496
1322
|
bold: isSelected,
|
|
@@ -499,9 +1325,9 @@ var List = class extends Widget {
|
|
|
499
1325
|
};
|
|
500
1326
|
screen.writeString(x, y + i, line, cellStyle);
|
|
501
1327
|
if (isSelected && this.isFocused) {
|
|
502
|
-
const remaining = width - (0,
|
|
1328
|
+
const remaining = width - (0, import_core11.stringWidth)(line);
|
|
503
1329
|
for (let c = 0; c < remaining; c++) {
|
|
504
|
-
screen.setCell(x + (0,
|
|
1330
|
+
screen.setCell(x + (0, import_core11.stringWidth)(line) + c, y + i, { char: " ", ...cellStyle });
|
|
505
1331
|
}
|
|
506
1332
|
}
|
|
507
1333
|
}
|
|
@@ -509,7 +1335,7 @@ var List = class extends Widget {
|
|
|
509
1335
|
const scrollRatio = this._scrollOffset / (this._items.length - height);
|
|
510
1336
|
const scrollPos = Math.floor(scrollRatio * (height - 1));
|
|
511
1337
|
for (let r = 0; r < height; r++) {
|
|
512
|
-
const scrollChar = r === scrollPos ? "\u2588" : "\u2591";
|
|
1338
|
+
const scrollChar = r === scrollPos ? import_core11.caps.unicode ? "\u2588" : "#" : import_core11.caps.unicode ? "\u2591" : "-";
|
|
513
1339
|
screen.setCell(x + width - 1, y + r, { char: scrollChar, ...attrs, dim: true });
|
|
514
1340
|
}
|
|
515
1341
|
}
|
|
@@ -531,7 +1357,7 @@ var List = class extends Widget {
|
|
|
531
1357
|
};
|
|
532
1358
|
|
|
533
1359
|
// src/input/TextInput.ts
|
|
534
|
-
var
|
|
1360
|
+
var import_core12 = require("@termuijs/core");
|
|
535
1361
|
var TextInput = class extends Widget {
|
|
536
1362
|
_value = "";
|
|
537
1363
|
_cursorPos = 0;
|
|
@@ -608,9 +1434,9 @@ var TextInput = class extends Widget {
|
|
|
608
1434
|
const rect = this._getContentRect();
|
|
609
1435
|
const { x, y, width, height } = rect;
|
|
610
1436
|
if (width <= 0 || height <= 0) return;
|
|
611
|
-
const attrs = (0,
|
|
1437
|
+
const attrs = (0, import_core12.styleToCellAttrs)(this._style);
|
|
612
1438
|
if (this._value.length === 0 && !this.isFocused) {
|
|
613
|
-
screen.writeString(x, y, (0,
|
|
1439
|
+
screen.writeString(x, y, (0, import_core12.truncate)(this._placeholder, width), { ...attrs, dim: true });
|
|
614
1440
|
return;
|
|
615
1441
|
}
|
|
616
1442
|
const displayValue = this._mask ? this._mask.repeat(this._value.length) : this._value;
|
|
@@ -636,7 +1462,7 @@ var TextInput = class extends Widget {
|
|
|
636
1462
|
};
|
|
637
1463
|
|
|
638
1464
|
// src/input/VirtualList.ts
|
|
639
|
-
var
|
|
1465
|
+
var import_core13 = require("@termuijs/core");
|
|
640
1466
|
var VirtualList = class extends Widget {
|
|
641
1467
|
_totalItems;
|
|
642
1468
|
_itemHeight;
|
|
@@ -740,10 +1566,14 @@ var VirtualList = class extends Widget {
|
|
|
740
1566
|
const rect = this._getContentRect();
|
|
741
1567
|
const { x, y, width, height } = rect;
|
|
742
1568
|
if (width <= 0 || height <= 0 || this._totalItems === 0) return;
|
|
743
|
-
const attrs = (0,
|
|
1569
|
+
const attrs = (0, import_core13.styleToCellAttrs)(this._style);
|
|
744
1570
|
const visibleItemCount = Math.floor(height / this._itemHeight);
|
|
745
|
-
const
|
|
746
|
-
|
|
1571
|
+
const { start: startIdx, end: endIdx } = computeRange(
|
|
1572
|
+
this._scrollOffset,
|
|
1573
|
+
visibleItemCount,
|
|
1574
|
+
this._totalItems,
|
|
1575
|
+
this._overscan
|
|
1576
|
+
);
|
|
747
1577
|
const contentWidth = this._showScrollbar && this._totalItems > visibleItemCount ? width - 1 : width;
|
|
748
1578
|
for (let idx = startIdx; idx < endIdx; idx++) {
|
|
749
1579
|
const rowY = y + (idx - this._scrollOffset) * this._itemHeight;
|
|
@@ -755,9 +1585,9 @@ var VirtualList = class extends Widget {
|
|
|
755
1585
|
} catch {
|
|
756
1586
|
content = `[Error: item ${idx}]`;
|
|
757
1587
|
}
|
|
758
|
-
const prefix = isSelected ? "\u25B8 " : " ";
|
|
1588
|
+
const prefix = isSelected ? import_core13.caps.unicode ? "\u25B8 " : "> " : " ";
|
|
759
1589
|
let line = prefix + content;
|
|
760
|
-
line = (0,
|
|
1590
|
+
line = (0, import_core13.truncate)(line, contentWidth);
|
|
761
1591
|
const cellStyle = {
|
|
762
1592
|
...attrs,
|
|
763
1593
|
bold: isSelected,
|
|
@@ -765,9 +1595,9 @@ var VirtualList = class extends Widget {
|
|
|
765
1595
|
};
|
|
766
1596
|
screen.writeString(x, rowY, line, cellStyle);
|
|
767
1597
|
if (isSelected && this.isFocused) {
|
|
768
|
-
const remaining = contentWidth - (0,
|
|
1598
|
+
const remaining = contentWidth - (0, import_core13.stringWidth)(line);
|
|
769
1599
|
for (let c = 0; c < remaining; c++) {
|
|
770
|
-
screen.setCell(x + (0,
|
|
1600
|
+
screen.setCell(x + (0, import_core13.stringWidth)(line) + c, rowY, { char: " ", ...cellStyle });
|
|
771
1601
|
}
|
|
772
1602
|
}
|
|
773
1603
|
}
|
|
@@ -776,8 +1606,10 @@ var VirtualList = class extends Widget {
|
|
|
776
1606
|
const totalPages = this._totalItems - visibleItemCount;
|
|
777
1607
|
const scrollRatio = totalPages > 0 ? this._scrollOffset / totalPages : 0;
|
|
778
1608
|
const thumbPos = Math.floor(scrollRatio * (height - 1));
|
|
1609
|
+
const thumbChar = import_core13.caps.unicode ? "\u2588" : "#";
|
|
1610
|
+
const trackChar = import_core13.caps.unicode ? "\u2591" : "|";
|
|
779
1611
|
for (let r = 0; r < height; r++) {
|
|
780
|
-
const scrollChar = r === thumbPos ?
|
|
1612
|
+
const scrollChar = r === thumbPos ? thumbChar : trackChar;
|
|
781
1613
|
screen.setCell(scrollbarX, y + r, { char: scrollChar, ...attrs, dim: r !== thumbPos });
|
|
782
1614
|
}
|
|
783
1615
|
}
|
|
@@ -800,8 +1632,173 @@ var VirtualList = class extends Widget {
|
|
|
800
1632
|
}
|
|
801
1633
|
};
|
|
802
1634
|
|
|
1635
|
+
// src/input/CommandPalette.ts
|
|
1636
|
+
var import_core14 = require("@termuijs/core");
|
|
1637
|
+
var CommandPalette = class extends Widget {
|
|
1638
|
+
_commands;
|
|
1639
|
+
_filtered;
|
|
1640
|
+
_query = "";
|
|
1641
|
+
_selectedIndex = 0;
|
|
1642
|
+
_options;
|
|
1643
|
+
constructor(options, style = {}) {
|
|
1644
|
+
super({ border: "single", ...style });
|
|
1645
|
+
this._options = {
|
|
1646
|
+
placeholder: "Type to search...",
|
|
1647
|
+
maxVisible: 8,
|
|
1648
|
+
...options
|
|
1649
|
+
};
|
|
1650
|
+
this._commands = options.commands;
|
|
1651
|
+
this._filtered = [...this._commands];
|
|
1652
|
+
this.focusable = true;
|
|
1653
|
+
}
|
|
1654
|
+
/** Update the full command list and re-filter. */
|
|
1655
|
+
setCommands(commands) {
|
|
1656
|
+
this._commands = commands;
|
|
1657
|
+
this._filter();
|
|
1658
|
+
this.markDirty();
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Reset query, re-filter all commands, reset selection.
|
|
1662
|
+
* Call this when opening the palette.
|
|
1663
|
+
*/
|
|
1664
|
+
open() {
|
|
1665
|
+
this._query = "";
|
|
1666
|
+
this._selectedIndex = 0;
|
|
1667
|
+
this._filtered = [...this._commands];
|
|
1668
|
+
this.markDirty();
|
|
1669
|
+
}
|
|
1670
|
+
/** Current query string. */
|
|
1671
|
+
getQuery() {
|
|
1672
|
+
return this._query;
|
|
1673
|
+
}
|
|
1674
|
+
// ─── Private helpers ────────────────────────────────
|
|
1675
|
+
/** Filter commands based on current query (case-insensitive substring). */
|
|
1676
|
+
_filter() {
|
|
1677
|
+
const q = this._query.toLowerCase();
|
|
1678
|
+
if (q === "") {
|
|
1679
|
+
this._filtered = [...this._commands];
|
|
1680
|
+
} else {
|
|
1681
|
+
this._filtered = this._commands.filter(
|
|
1682
|
+
(cmd) => cmd.label.toLowerCase().includes(q) || cmd.id.toLowerCase().includes(q)
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
const max = Math.max(0, this._filtered.length - 1);
|
|
1686
|
+
this._selectedIndex = Math.min(this._selectedIndex, max);
|
|
1687
|
+
}
|
|
1688
|
+
_executeSelected() {
|
|
1689
|
+
const cmd = this._filtered[this._selectedIndex];
|
|
1690
|
+
if (cmd) {
|
|
1691
|
+
cmd.action();
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
_moveUp() {
|
|
1695
|
+
if (this._selectedIndex > 0) {
|
|
1696
|
+
this._selectedIndex--;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
_moveDown() {
|
|
1700
|
+
const maxVisible = this._options.maxVisible ?? 8;
|
|
1701
|
+
const visibleCount = Math.min(this._filtered.length, maxVisible);
|
|
1702
|
+
if (this._selectedIndex < visibleCount - 1) {
|
|
1703
|
+
this._selectedIndex++;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
// ─── Key handling ────────────────────────────────────
|
|
1707
|
+
handleKey(key) {
|
|
1708
|
+
switch (key) {
|
|
1709
|
+
case "Escape":
|
|
1710
|
+
this._options.onClose?.();
|
|
1711
|
+
break;
|
|
1712
|
+
case "Enter":
|
|
1713
|
+
this._executeSelected();
|
|
1714
|
+
break;
|
|
1715
|
+
case "ArrowUp":
|
|
1716
|
+
case "k":
|
|
1717
|
+
this._moveUp();
|
|
1718
|
+
break;
|
|
1719
|
+
case "ArrowDown":
|
|
1720
|
+
case "j":
|
|
1721
|
+
this._moveDown();
|
|
1722
|
+
break;
|
|
1723
|
+
case "Backspace":
|
|
1724
|
+
this._query = this._query.slice(0, -1);
|
|
1725
|
+
this._filter();
|
|
1726
|
+
break;
|
|
1727
|
+
default:
|
|
1728
|
+
if (key.length === 1) {
|
|
1729
|
+
this._query += key;
|
|
1730
|
+
this._filter();
|
|
1731
|
+
}
|
|
1732
|
+
break;
|
|
1733
|
+
}
|
|
1734
|
+
this.markDirty();
|
|
1735
|
+
}
|
|
1736
|
+
// ─── Rendering ───────────────────────────────────────
|
|
1737
|
+
_renderSelf(screen) {
|
|
1738
|
+
const rect = this._getContentRect();
|
|
1739
|
+
const { x, y, width, height } = rect;
|
|
1740
|
+
if (width <= 0 || height <= 0) return;
|
|
1741
|
+
const attrs = (0, import_core14.styleToCellAttrs)(this._style);
|
|
1742
|
+
const maxVisible = this._options.maxVisible ?? 8;
|
|
1743
|
+
const placeholder = this._options.placeholder ?? "Type to search...";
|
|
1744
|
+
const prefix = "> ";
|
|
1745
|
+
const queryDisplay = this._query.length > 0 ? this._query : placeholder;
|
|
1746
|
+
const queryDim = this._query.length === 0;
|
|
1747
|
+
const queryLine = (0, import_core14.truncate)(prefix + queryDisplay, width);
|
|
1748
|
+
screen.writeString(x, y, queryLine, { ...attrs, dim: queryDim });
|
|
1749
|
+
const queryLineWidth = (0, import_core14.stringWidth)(queryLine);
|
|
1750
|
+
for (let c = queryLineWidth; c < width; c++) {
|
|
1751
|
+
screen.setCell(x + c, y, { char: " ", ...attrs });
|
|
1752
|
+
}
|
|
1753
|
+
const listStartRow = 1;
|
|
1754
|
+
const listHeight = height - listStartRow;
|
|
1755
|
+
const visibleCount = Math.min(this._filtered.length, maxVisible, listHeight);
|
|
1756
|
+
for (let i = 0; i < visibleCount; i++) {
|
|
1757
|
+
const cmd = this._filtered[i];
|
|
1758
|
+
const isSelected = i === this._selectedIndex;
|
|
1759
|
+
const rowY = y + listStartRow + i;
|
|
1760
|
+
const rowPrefix = isSelected ? "\u25B8 " : " ";
|
|
1761
|
+
const labelPart = rowPrefix + cmd.label;
|
|
1762
|
+
const desc = cmd.description ?? "";
|
|
1763
|
+
const descWidth = (0, import_core14.stringWidth)(desc);
|
|
1764
|
+
const gap = 1;
|
|
1765
|
+
const labelMaxWidth = desc ? Math.max(0, width - descWidth - gap) : width;
|
|
1766
|
+
const labelTruncated = (0, import_core14.truncate)(labelPart, labelMaxWidth);
|
|
1767
|
+
const labelWidth = (0, import_core14.stringWidth)(labelTruncated);
|
|
1768
|
+
const cellStyle = {
|
|
1769
|
+
...attrs,
|
|
1770
|
+
bold: isSelected,
|
|
1771
|
+
inverse: isSelected
|
|
1772
|
+
};
|
|
1773
|
+
const dimStyle = {
|
|
1774
|
+
...attrs,
|
|
1775
|
+
dim: true,
|
|
1776
|
+
inverse: isSelected
|
|
1777
|
+
};
|
|
1778
|
+
screen.writeString(x, rowY, labelTruncated, cellStyle);
|
|
1779
|
+
if (desc) {
|
|
1780
|
+
const descX = x + width - descWidth;
|
|
1781
|
+
for (let c = x + labelWidth; c < descX; c++) {
|
|
1782
|
+
screen.setCell(c, rowY, { char: " ", ...cellStyle });
|
|
1783
|
+
}
|
|
1784
|
+
screen.writeString(descX, rowY, desc, dimStyle);
|
|
1785
|
+
} else {
|
|
1786
|
+
for (let c = x + labelWidth; c < x + width; c++) {
|
|
1787
|
+
screen.setCell(c, rowY, { char: " ", ...cellStyle });
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
for (let i = visibleCount; i < listHeight; i++) {
|
|
1792
|
+
const rowY = y + listStartRow + i;
|
|
1793
|
+
for (let c = 0; c < width; c++) {
|
|
1794
|
+
screen.setCell(x + c, rowY, { char: " ", ...attrs });
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1799
|
+
|
|
803
1800
|
// src/data/Table.ts
|
|
804
|
-
var
|
|
1801
|
+
var import_core15 = require("@termuijs/core");
|
|
805
1802
|
var Table = class extends Widget {
|
|
806
1803
|
_columns;
|
|
807
1804
|
_rows;
|
|
@@ -828,8 +1825,8 @@ var Table = class extends Widget {
|
|
|
828
1825
|
const rect = this._getContentRect();
|
|
829
1826
|
const { x, y, width, height } = rect;
|
|
830
1827
|
if (width <= 0 || height <= 0) return;
|
|
831
|
-
const attrs = (0,
|
|
832
|
-
const sepWidth = (0,
|
|
1828
|
+
const attrs = (0, import_core15.styleToCellAttrs)(this._style);
|
|
1829
|
+
const sepWidth = (0, import_core15.stringWidth)(this._separator);
|
|
833
1830
|
const colWidths = this._computeColumnWidths(
|
|
834
1831
|
width - (this._columns.length - 1) * sepWidth
|
|
835
1832
|
);
|
|
@@ -896,8 +1893,8 @@ var Table = class extends Widget {
|
|
|
896
1893
|
return this._columns.map((c) => c.width ?? flexWidth);
|
|
897
1894
|
}
|
|
898
1895
|
_alignText(text, width, align) {
|
|
899
|
-
const truncated = (0,
|
|
900
|
-
const textWidth = (0,
|
|
1896
|
+
const truncated = (0, import_core15.truncate)(text, width);
|
|
1897
|
+
const textWidth = (0, import_core15.stringWidth)(truncated);
|
|
901
1898
|
const pad = Math.max(0, width - textWidth);
|
|
902
1899
|
switch (align) {
|
|
903
1900
|
case "right":
|
|
@@ -915,7 +1912,7 @@ var Table = class extends Widget {
|
|
|
915
1912
|
};
|
|
916
1913
|
|
|
917
1914
|
// src/data/Gauge.ts
|
|
918
|
-
var
|
|
1915
|
+
var import_core16 = require("@termuijs/core");
|
|
919
1916
|
var Gauge = class extends Widget {
|
|
920
1917
|
_label;
|
|
921
1918
|
_value = 0;
|
|
@@ -942,17 +1939,17 @@ var Gauge = class extends Widget {
|
|
|
942
1939
|
const rect = this._getContentRect();
|
|
943
1940
|
const { x, y, width, height } = rect;
|
|
944
1941
|
if (width <= 0 || height <= 0) return;
|
|
945
|
-
const attrs = (0,
|
|
1942
|
+
const attrs = (0, import_core16.styleToCellAttrs)(this._style);
|
|
946
1943
|
const labelStr = this._label + " ";
|
|
947
1944
|
const percentStr = this._showLabel ? ` ${Math.round(this._value * 100)}%` : "";
|
|
948
|
-
const labelWidth = (0,
|
|
949
|
-
const percentWidth = (0,
|
|
1945
|
+
const labelWidth = (0, import_core16.stringWidth)(labelStr);
|
|
1946
|
+
const percentWidth = (0, import_core16.stringWidth)(percentStr);
|
|
950
1947
|
const barWidth = Math.max(0, width - labelWidth - percentWidth);
|
|
951
1948
|
screen.writeString(x, y, labelStr, { ...attrs, bold: true });
|
|
952
1949
|
const filled = Math.round(barWidth * this._value);
|
|
953
1950
|
const barX = x + labelWidth;
|
|
954
1951
|
for (let i = 0; i < barWidth; i++) {
|
|
955
|
-
const char = i < filled ? "\u2588" : "\u2591";
|
|
1952
|
+
const char = i < filled ? import_core16.caps.unicode ? "\u2588" : "#" : import_core16.caps.unicode ? "\u2591" : "-";
|
|
956
1953
|
screen.setCell(barX + i, y, {
|
|
957
1954
|
char,
|
|
958
1955
|
fg: i < filled ? this._color : { type: "named", name: "brightBlack" }
|
|
@@ -968,8 +1965,9 @@ var Gauge = class extends Widget {
|
|
|
968
1965
|
};
|
|
969
1966
|
|
|
970
1967
|
// src/data/Sparkline.ts
|
|
971
|
-
var
|
|
972
|
-
var
|
|
1968
|
+
var import_core17 = require("@termuijs/core");
|
|
1969
|
+
var SPARK_CHARS_UNICODE = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
|
|
1970
|
+
var SPARK_CHARS_ASCII = ["1", "2", "3", "4", "5", "6", "7", "8"];
|
|
973
1971
|
var Sparkline = class extends Widget {
|
|
974
1972
|
_label;
|
|
975
1973
|
_data = [];
|
|
@@ -993,7 +1991,7 @@ var Sparkline = class extends Widget {
|
|
|
993
1991
|
const rect = this._getContentRect();
|
|
994
1992
|
const { x, y, width, height } = rect;
|
|
995
1993
|
if (width <= 0 || height <= 0) return;
|
|
996
|
-
const attrs = (0,
|
|
1994
|
+
const attrs = (0, import_core17.styleToCellAttrs)(this._style);
|
|
997
1995
|
const labelStr = this._label + " ";
|
|
998
1996
|
const labelWidth = labelStr.length;
|
|
999
1997
|
screen.writeString(x, y, labelStr, { ...attrs, bold: true });
|
|
@@ -1003,11 +2001,12 @@ var Sparkline = class extends Widget {
|
|
|
1003
2001
|
const min = Math.min(...data);
|
|
1004
2002
|
const max = Math.max(...data);
|
|
1005
2003
|
const range = max - min || 1;
|
|
2004
|
+
const sparkChars = import_core17.caps.unicode ? SPARK_CHARS_UNICODE : SPARK_CHARS_ASCII;
|
|
1006
2005
|
for (let i = 0; i < data.length; i++) {
|
|
1007
2006
|
const normalized = (data[i] - min) / range;
|
|
1008
2007
|
const charIdx = Math.min(7, Math.floor(normalized * 8));
|
|
1009
2008
|
screen.setCell(x + labelWidth + i, y, {
|
|
1010
|
-
char:
|
|
2009
|
+
char: sparkChars[charIdx],
|
|
1011
2010
|
fg: this._color
|
|
1012
2011
|
});
|
|
1013
2012
|
}
|
|
@@ -1022,7 +2021,7 @@ var Sparkline = class extends Widget {
|
|
|
1022
2021
|
};
|
|
1023
2022
|
|
|
1024
2023
|
// src/data/StatusIndicator.ts
|
|
1025
|
-
var
|
|
2024
|
+
var import_core18 = require("@termuijs/core");
|
|
1026
2025
|
var StatusIndicator = class extends Widget {
|
|
1027
2026
|
_label;
|
|
1028
2027
|
_isUp;
|
|
@@ -1048,7 +2047,7 @@ var StatusIndicator = class extends Widget {
|
|
|
1048
2047
|
const rect = this._getContentRect();
|
|
1049
2048
|
const { x, y, width, height } = rect;
|
|
1050
2049
|
if (width <= 0 || height <= 0) return;
|
|
1051
|
-
const attrs = (0,
|
|
2050
|
+
const attrs = (0, import_core18.styleToCellAttrs)(this._style);
|
|
1052
2051
|
const dot = this._isUp ? "\u25CF" : "\u25CB";
|
|
1053
2052
|
const statusText = this._isUp ? "Online" : "Offline";
|
|
1054
2053
|
const color = this._isUp ? this._upColor : this._downColor;
|
|
@@ -1061,7 +2060,7 @@ var StatusIndicator = class extends Widget {
|
|
|
1061
2060
|
};
|
|
1062
2061
|
|
|
1063
2062
|
// src/data/BarChart.ts
|
|
1064
|
-
var
|
|
2063
|
+
var import_core19 = require("@termuijs/core");
|
|
1065
2064
|
var BarChart = class extends Widget {
|
|
1066
2065
|
_data = [];
|
|
1067
2066
|
_direction;
|
|
@@ -1141,7 +2140,7 @@ var BarChart = class extends Widget {
|
|
|
1141
2140
|
for (let row = barAreaHeight - 1; row >= 0; row--) {
|
|
1142
2141
|
if (remaining <= 0) break;
|
|
1143
2142
|
const level = Math.min(remaining, 8);
|
|
1144
|
-
const symbol =
|
|
2143
|
+
const symbol = import_core19.VERTICAL_BAR_SYMBOLS[level] ?? " ";
|
|
1145
2144
|
const cellY = oy + row;
|
|
1146
2145
|
for (let col = 0; col < this._barWidth; col++) {
|
|
1147
2146
|
const cellX = cx + col;
|
|
@@ -1152,7 +2151,7 @@ var BarChart = class extends Widget {
|
|
|
1152
2151
|
remaining -= 8;
|
|
1153
2152
|
}
|
|
1154
2153
|
const valStr = Math.round(bar.value).toString();
|
|
1155
|
-
const valX = cx + Math.floor((this._barWidth - (0,
|
|
2154
|
+
const valX = cx + Math.floor((this._barWidth - (0, import_core19.stringWidth)(valStr)) / 2);
|
|
1156
2155
|
screen.writeString(
|
|
1157
2156
|
Math.max(cx, valX),
|
|
1158
2157
|
oy + barAreaHeight,
|
|
@@ -1161,7 +2160,7 @@ var BarChart = class extends Widget {
|
|
|
1161
2160
|
);
|
|
1162
2161
|
if (hasLabels && bar.label) {
|
|
1163
2162
|
const label = bar.label.slice(0, this._barWidth);
|
|
1164
|
-
const labelX = cx + Math.floor((this._barWidth - (0,
|
|
2163
|
+
const labelX = cx + Math.floor((this._barWidth - (0, import_core19.stringWidth)(label)) / 2);
|
|
1165
2164
|
screen.writeString(
|
|
1166
2165
|
Math.max(cx, labelX),
|
|
1167
2166
|
oy + barAreaHeight + valueRows,
|
|
@@ -1175,7 +2174,7 @@ var BarChart = class extends Widget {
|
|
|
1175
2174
|
if (hasGroupLabels && group.label) {
|
|
1176
2175
|
const groupWidth = cx - groupStartX;
|
|
1177
2176
|
const label = group.label.slice(0, groupWidth);
|
|
1178
|
-
const labelX = groupStartX + Math.floor((groupWidth - (0,
|
|
2177
|
+
const labelX = groupStartX + Math.floor((groupWidth - (0, import_core19.stringWidth)(label)) / 2);
|
|
1179
2178
|
screen.writeString(
|
|
1180
2179
|
Math.max(groupStartX, labelX),
|
|
1181
2180
|
oy + height - 1,
|
|
@@ -1193,7 +2192,7 @@ var BarChart = class extends Widget {
|
|
|
1193
2192
|
for (const group of this._data) {
|
|
1194
2193
|
for (const bar of group.bars) {
|
|
1195
2194
|
if (bar.label) {
|
|
1196
|
-
const w = (0,
|
|
2195
|
+
const w = (0, import_core19.stringWidth)(bar.label);
|
|
1197
2196
|
if (w > maxLabelWidth) maxLabelWidth = w;
|
|
1198
2197
|
}
|
|
1199
2198
|
const vw = Math.round(bar.value).toString().length;
|
|
@@ -1226,7 +2225,7 @@ var BarChart = class extends Widget {
|
|
|
1226
2225
|
for (let col = 0; col < barAreaWidth; col++) {
|
|
1227
2226
|
if (remaining <= 0) break;
|
|
1228
2227
|
const level = Math.min(remaining, 8);
|
|
1229
|
-
const symbol =
|
|
2228
|
+
const symbol = import_core19.HORIZONTAL_BAR_SYMBOLS[level] ?? " ";
|
|
1230
2229
|
screen.setCell(barStartX + col, cellY, { char: symbol, fg: color });
|
|
1231
2230
|
remaining -= 8;
|
|
1232
2231
|
}
|
|
@@ -1248,8 +2247,270 @@ var BarChart = class extends Widget {
|
|
|
1248
2247
|
}
|
|
1249
2248
|
};
|
|
1250
2249
|
|
|
2250
|
+
// src/layout/Grid.ts
|
|
2251
|
+
var Grid = class extends Widget {
|
|
2252
|
+
_columns;
|
|
2253
|
+
_colGap;
|
|
2254
|
+
_rowGap;
|
|
2255
|
+
_rows = [];
|
|
2256
|
+
_itemCount = 0;
|
|
2257
|
+
constructor(style, options) {
|
|
2258
|
+
super({ flexDirection: "column", ...style });
|
|
2259
|
+
this._columns = Math.max(1, options.columns);
|
|
2260
|
+
const gap = options.gap ?? 1;
|
|
2261
|
+
this._colGap = options.colGap ?? gap;
|
|
2262
|
+
this._rowGap = options.rowGap ?? gap;
|
|
2263
|
+
}
|
|
2264
|
+
_renderSelf(_screen) {
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Add a widget to the grid. Items fill left-to-right,
|
|
2268
|
+
* wrapping to a new row automatically every `columns` items.
|
|
2269
|
+
* Overrides Widget.addChild so the reconciler generic loop works unchanged.
|
|
2270
|
+
*/
|
|
2271
|
+
addChild(widget) {
|
|
2272
|
+
const rowIndex = Math.floor(this._itemCount / this._columns);
|
|
2273
|
+
if (rowIndex >= this._rows.length) {
|
|
2274
|
+
const rowStyle = { flexDirection: "row" };
|
|
2275
|
+
if (this._colGap > 0) rowStyle.gap = this._colGap;
|
|
2276
|
+
if (this._rows.length > 0 && this._rowGap > 0) {
|
|
2277
|
+
rowStyle.margin = this._rowGap;
|
|
2278
|
+
}
|
|
2279
|
+
const row = new Box(rowStyle);
|
|
2280
|
+
this._rows.push(row);
|
|
2281
|
+
super.addChild(row);
|
|
2282
|
+
}
|
|
2283
|
+
const currentRow = this._rows[rowIndex];
|
|
2284
|
+
widget.setStyle({ flexGrow: 1 });
|
|
2285
|
+
currentRow.addChild(widget);
|
|
2286
|
+
this._itemCount++;
|
|
2287
|
+
}
|
|
2288
|
+
/** Add an item explicitly (alias for addChild) */
|
|
2289
|
+
addItem(widget) {
|
|
2290
|
+
this.addChild(widget);
|
|
2291
|
+
}
|
|
2292
|
+
/** Remove all items and reset the grid */
|
|
2293
|
+
clearItems() {
|
|
2294
|
+
for (const row of this._rows) {
|
|
2295
|
+
row.unmount();
|
|
2296
|
+
row.parent = null;
|
|
2297
|
+
}
|
|
2298
|
+
this._children = [];
|
|
2299
|
+
this._rows = [];
|
|
2300
|
+
this._itemCount = 0;
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2303
|
+
|
|
2304
|
+
// src/layout/ScrollView.ts
|
|
2305
|
+
var import_core20 = require("@termuijs/core");
|
|
2306
|
+
var ScrollView = class extends Widget {
|
|
2307
|
+
_scrollOffset = 0;
|
|
2308
|
+
_contentHeight;
|
|
2309
|
+
_showScrollbar;
|
|
2310
|
+
constructor(style = {}, opts = {}) {
|
|
2311
|
+
super({ overflow: "hidden", ...style });
|
|
2312
|
+
this._contentHeight = opts.contentHeight ?? 0;
|
|
2313
|
+
this._showScrollbar = opts.showScrollbar ?? true;
|
|
2314
|
+
this.focusable = true;
|
|
2315
|
+
}
|
|
2316
|
+
/** Set the total content height (in rows) */
|
|
2317
|
+
setContentHeight(h) {
|
|
2318
|
+
this._contentHeight = h;
|
|
2319
|
+
this._clampOffset();
|
|
2320
|
+
this.markDirty();
|
|
2321
|
+
}
|
|
2322
|
+
/** Get current scroll offset */
|
|
2323
|
+
get scrollOffset() {
|
|
2324
|
+
return this._scrollOffset;
|
|
2325
|
+
}
|
|
2326
|
+
/** Scroll by delta rows */
|
|
2327
|
+
scrollBy(delta) {
|
|
2328
|
+
this._scrollOffset += delta;
|
|
2329
|
+
this._clampOffset();
|
|
2330
|
+
this.markDirty();
|
|
2331
|
+
}
|
|
2332
|
+
/** Scroll to absolute offset */
|
|
2333
|
+
scrollTo(offset) {
|
|
2334
|
+
this._scrollOffset = offset;
|
|
2335
|
+
this._clampOffset();
|
|
2336
|
+
this.markDirty();
|
|
2337
|
+
}
|
|
2338
|
+
_clampOffset() {
|
|
2339
|
+
const viewHeight = this._rect.height;
|
|
2340
|
+
const maxOffset = Math.max(0, this._contentHeight - viewHeight);
|
|
2341
|
+
this._scrollOffset = Math.max(0, Math.min(this._scrollOffset, maxOffset));
|
|
2342
|
+
}
|
|
2343
|
+
/** Handle keyboard navigation */
|
|
2344
|
+
onKey(event) {
|
|
2345
|
+
switch (event.key) {
|
|
2346
|
+
case "ArrowUp":
|
|
2347
|
+
this.scrollBy(-1);
|
|
2348
|
+
break;
|
|
2349
|
+
case "ArrowDown":
|
|
2350
|
+
this.scrollBy(1);
|
|
2351
|
+
break;
|
|
2352
|
+
case "PageUp":
|
|
2353
|
+
this.scrollBy(-Math.max(1, this._rect.height - 1));
|
|
2354
|
+
break;
|
|
2355
|
+
case "PageDown":
|
|
2356
|
+
this.scrollBy(Math.max(1, this._rect.height - 1));
|
|
2357
|
+
break;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
render(screen) {
|
|
2361
|
+
if (this._style.visible === false) return;
|
|
2362
|
+
const shouldClip = true;
|
|
2363
|
+
if (shouldClip) screen.pushClip(this._rect);
|
|
2364
|
+
this._renderSelf(screen);
|
|
2365
|
+
this._renderBorder(screen);
|
|
2366
|
+
const rect = this._getContentRect();
|
|
2367
|
+
for (const child of this._children) {
|
|
2368
|
+
const origRect = { ...child.rect };
|
|
2369
|
+
child._rect = {
|
|
2370
|
+
x: origRect.x,
|
|
2371
|
+
y: origRect.y - this._scrollOffset,
|
|
2372
|
+
width: origRect.width,
|
|
2373
|
+
height: origRect.height
|
|
2374
|
+
};
|
|
2375
|
+
try {
|
|
2376
|
+
child.render(screen);
|
|
2377
|
+
} finally {
|
|
2378
|
+
child._rect = origRect;
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
if (shouldClip) screen.popClip();
|
|
2382
|
+
if (this._showScrollbar && this._contentHeight > this._rect.height) {
|
|
2383
|
+
this._renderScrollbar(screen, rect);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
_renderScrollbar(screen, contentRect) {
|
|
2387
|
+
const { y, width, height } = contentRect;
|
|
2388
|
+
const scrollX = contentRect.x + width;
|
|
2389
|
+
if (scrollX >= this._rect.x + this._rect.width) return;
|
|
2390
|
+
const trackHeight = height;
|
|
2391
|
+
const thumbSize = Math.max(1, Math.round(height / this._contentHeight * trackHeight));
|
|
2392
|
+
const maxOffset = Math.max(1, this._contentHeight - height);
|
|
2393
|
+
const thumbPos = Math.round(this._scrollOffset / maxOffset * (trackHeight - thumbSize));
|
|
2394
|
+
const attrs = (0, import_core20.styleToCellAttrs)(this._style);
|
|
2395
|
+
const thumbChar = "\u2588";
|
|
2396
|
+
const trackChar = "\u2591";
|
|
2397
|
+
for (let i = 0; i < trackHeight; i++) {
|
|
2398
|
+
const isThumb = i >= thumbPos && i < thumbPos + thumbSize;
|
|
2399
|
+
screen.setCell(scrollX, y + i, {
|
|
2400
|
+
char: isThumb ? thumbChar : trackChar,
|
|
2401
|
+
...attrs,
|
|
2402
|
+
dim: !isThumb
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
_renderSelf(_screen) {
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
|
|
2410
|
+
// src/layout/Center.ts
|
|
2411
|
+
var Center = class extends Widget {
|
|
2412
|
+
_horizontal;
|
|
2413
|
+
_vertical;
|
|
2414
|
+
constructor(style = {}, opts = {}) {
|
|
2415
|
+
super(style);
|
|
2416
|
+
this._horizontal = opts.horizontal ?? true;
|
|
2417
|
+
this._vertical = opts.vertical ?? true;
|
|
2418
|
+
}
|
|
2419
|
+
_renderSelf(_screen) {
|
|
2420
|
+
}
|
|
2421
|
+
render(screen) {
|
|
2422
|
+
if (this._style.visible === false) return;
|
|
2423
|
+
const shouldClip = this._style.overflow !== "visible";
|
|
2424
|
+
if (shouldClip) screen.pushClip(this._rect);
|
|
2425
|
+
this._renderSelf(screen);
|
|
2426
|
+
this._renderBorder(screen);
|
|
2427
|
+
const content = this._getContentRect();
|
|
2428
|
+
for (const child of this._children) {
|
|
2429
|
+
const childRect = child.rect;
|
|
2430
|
+
const origRect = { ...childRect };
|
|
2431
|
+
let offsetX = content.x;
|
|
2432
|
+
let offsetY = content.y;
|
|
2433
|
+
if (this._horizontal) {
|
|
2434
|
+
offsetX = content.x + Math.max(0, Math.floor((content.width - childRect.width) / 2));
|
|
2435
|
+
}
|
|
2436
|
+
if (this._vertical) {
|
|
2437
|
+
offsetY = content.y + Math.max(0, Math.floor((content.height - childRect.height) / 2));
|
|
2438
|
+
}
|
|
2439
|
+
child._rect = {
|
|
2440
|
+
x: offsetX,
|
|
2441
|
+
y: offsetY,
|
|
2442
|
+
width: childRect.width,
|
|
2443
|
+
height: childRect.height
|
|
2444
|
+
};
|
|
2445
|
+
child.render(screen);
|
|
2446
|
+
child._rect = origRect;
|
|
2447
|
+
}
|
|
2448
|
+
if (shouldClip) screen.popClip();
|
|
2449
|
+
}
|
|
2450
|
+
};
|
|
2451
|
+
|
|
2452
|
+
// src/layout/Card.ts
|
|
2453
|
+
var import_core21 = require("@termuijs/core");
|
|
2454
|
+
var Card = class extends Widget {
|
|
2455
|
+
_title;
|
|
2456
|
+
_borderColor;
|
|
2457
|
+
constructor(style = {}, opts = {}) {
|
|
2458
|
+
super({
|
|
2459
|
+
border: "single",
|
|
2460
|
+
padding: 1,
|
|
2461
|
+
...style
|
|
2462
|
+
});
|
|
2463
|
+
this._title = opts.title ?? "";
|
|
2464
|
+
this._borderColor = opts.borderColor;
|
|
2465
|
+
}
|
|
2466
|
+
setTitle(title) {
|
|
2467
|
+
this._title = title;
|
|
2468
|
+
this.markDirty();
|
|
2469
|
+
}
|
|
2470
|
+
_renderSelf(screen) {
|
|
2471
|
+
if (!this._title) return;
|
|
2472
|
+
const { x, y, width } = this._rect;
|
|
2473
|
+
if (width < 4) return;
|
|
2474
|
+
const attrs = (0, import_core21.styleToCellAttrs)(this._style);
|
|
2475
|
+
const fg = this._borderColor ?? attrs.fg;
|
|
2476
|
+
const titleText = ` ${this._title} `;
|
|
2477
|
+
const titleWidth = (0, import_core21.stringWidth)(titleText);
|
|
2478
|
+
const innerWidth = width - 2;
|
|
2479
|
+
if (titleWidth > innerWidth) return;
|
|
2480
|
+
const titleX = x + 1 + Math.floor((innerWidth - titleWidth) / 2);
|
|
2481
|
+
screen.writeString(titleX, y, titleText, { fg, bold: true });
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
|
|
2485
|
+
// src/layout/Columns.ts
|
|
2486
|
+
var Columns = class extends Widget {
|
|
2487
|
+
_inner;
|
|
2488
|
+
constructor(style = {}, opts = {}) {
|
|
2489
|
+
super(style);
|
|
2490
|
+
this._inner = new Box({
|
|
2491
|
+
flexDirection: "row",
|
|
2492
|
+
gap: opts.gap ?? 1,
|
|
2493
|
+
width: "100%",
|
|
2494
|
+
height: "100%"
|
|
2495
|
+
});
|
|
2496
|
+
super.addChild(this._inner);
|
|
2497
|
+
}
|
|
2498
|
+
addChild(widget) {
|
|
2499
|
+
widget.setStyle({ flexGrow: 1 });
|
|
2500
|
+
this._inner.addChild(widget);
|
|
2501
|
+
}
|
|
2502
|
+
removeChild(widget) {
|
|
2503
|
+
this._inner.removeChild(widget);
|
|
2504
|
+
}
|
|
2505
|
+
clearChildren() {
|
|
2506
|
+
this._inner.clearChildren();
|
|
2507
|
+
}
|
|
2508
|
+
_renderSelf(_screen) {
|
|
2509
|
+
}
|
|
2510
|
+
};
|
|
2511
|
+
|
|
1251
2512
|
// src/feedback/ProgressBar.ts
|
|
1252
|
-
var
|
|
2513
|
+
var import_core22 = require("@termuijs/core");
|
|
1253
2514
|
var ProgressBar = class extends Widget {
|
|
1254
2515
|
_value;
|
|
1255
2516
|
_fillChar;
|
|
@@ -1261,8 +2522,8 @@ var ProgressBar = class extends Widget {
|
|
|
1261
2522
|
constructor(style = {}, options = {}) {
|
|
1262
2523
|
super({ height: 1, ...style });
|
|
1263
2524
|
this._value = Math.max(0, Math.min(1, options.value ?? 0));
|
|
1264
|
-
this._fillChar = options.fillChar ?? "\u2588";
|
|
1265
|
-
this._emptyChar = options.emptyChar ?? "\u2591";
|
|
2525
|
+
this._fillChar = options.fillChar ?? (import_core22.caps.unicode ? "\u2588" : "#");
|
|
2526
|
+
this._emptyChar = options.emptyChar ?? (import_core22.caps.unicode ? "\u2591" : "-");
|
|
1266
2527
|
this._fillColor = options.fillColor ?? { type: "named", name: "green" };
|
|
1267
2528
|
this._showLabel = options.showLabel ?? true;
|
|
1268
2529
|
this._labelFormat = options.labelFormat ?? "percent";
|
|
@@ -1280,7 +2541,7 @@ var ProgressBar = class extends Widget {
|
|
|
1280
2541
|
const rect = this._getContentRect();
|
|
1281
2542
|
const { x, y, width } = rect;
|
|
1282
2543
|
if (width <= 0) return;
|
|
1283
|
-
const attrs = (0,
|
|
2544
|
+
const attrs = (0, import_core22.styleToCellAttrs)(this._style);
|
|
1284
2545
|
let label = "";
|
|
1285
2546
|
if (this._showLabel) {
|
|
1286
2547
|
if (this._labelFormat === "percent") {
|
|
@@ -1304,8 +2565,84 @@ var ProgressBar = class extends Widget {
|
|
|
1304
2565
|
}
|
|
1305
2566
|
};
|
|
1306
2567
|
|
|
2568
|
+
// src/feedback/MultiProgress.ts
|
|
2569
|
+
var import_core23 = require("@termuijs/core");
|
|
2570
|
+
var MultiProgress = class extends Widget {
|
|
2571
|
+
_items;
|
|
2572
|
+
_labelWidth;
|
|
2573
|
+
_showValues;
|
|
2574
|
+
constructor(options, style = {}) {
|
|
2575
|
+
const height = options.items.length;
|
|
2576
|
+
super({ height, ...style });
|
|
2577
|
+
this._items = options.items.map((item) => ({
|
|
2578
|
+
...item,
|
|
2579
|
+
value: Math.max(0, Math.min(1, item.value))
|
|
2580
|
+
}));
|
|
2581
|
+
this._labelWidth = options.labelWidth ?? 12;
|
|
2582
|
+
this._showValues = options.showValues ?? true;
|
|
2583
|
+
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Replace all items and mark dirty
|
|
2586
|
+
*/
|
|
2587
|
+
setItems(items) {
|
|
2588
|
+
this._items = items.map((item) => ({
|
|
2589
|
+
...item,
|
|
2590
|
+
value: Math.max(0, Math.min(1, item.value))
|
|
2591
|
+
}));
|
|
2592
|
+
this.markDirty();
|
|
2593
|
+
}
|
|
2594
|
+
/**
|
|
2595
|
+
* Update a single item's value
|
|
2596
|
+
*/
|
|
2597
|
+
updateItem(index, value) {
|
|
2598
|
+
if (index >= 0 && index < this._items.length) {
|
|
2599
|
+
this._items[index].value = Math.max(0, Math.min(1, value));
|
|
2600
|
+
this.markDirty();
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
_renderSelf(screen) {
|
|
2604
|
+
const rect = this._getContentRect();
|
|
2605
|
+
const { x, y, width } = rect;
|
|
2606
|
+
if (width <= 0) return;
|
|
2607
|
+
const attrs = (0, import_core23.styleToCellAttrs)(this._style);
|
|
2608
|
+
const fillChar = import_core23.caps.unicode ? "\u2588" : import_core23.BLOCK.full;
|
|
2609
|
+
const emptyChar = import_core23.caps.unicode ? "\u2591" : import_core23.BLOCK.empty;
|
|
2610
|
+
for (let i = 0; i < this._items.length; i++) {
|
|
2611
|
+
const item = this._items[i];
|
|
2612
|
+
const rowY = y + i;
|
|
2613
|
+
let colX = x;
|
|
2614
|
+
const label = item.label.length > this._labelWidth ? item.label.substring(0, this._labelWidth) : item.label.padEnd(this._labelWidth);
|
|
2615
|
+
screen.writeString(colX, rowY, label, attrs);
|
|
2616
|
+
colX += this._labelWidth;
|
|
2617
|
+
if (colX < x + width) {
|
|
2618
|
+
screen.setCell(colX, rowY, { char: " ", ...attrs });
|
|
2619
|
+
colX++;
|
|
2620
|
+
}
|
|
2621
|
+
let percentLabel = "";
|
|
2622
|
+
if (this._showValues) {
|
|
2623
|
+
percentLabel = ` ${Math.round(item.value * 100)}%`;
|
|
2624
|
+
}
|
|
2625
|
+
const barWidth = Math.max(0, x + width - colX - percentLabel.length);
|
|
2626
|
+
const filled = Math.round(barWidth * item.value);
|
|
2627
|
+
const empty = barWidth - filled;
|
|
2628
|
+
const fillColor = item.color ?? { type: "named", name: "green" };
|
|
2629
|
+
for (let j = 0; j < filled; j++) {
|
|
2630
|
+
screen.setCell(colX + j, rowY, { char: fillChar, ...attrs, fg: fillColor });
|
|
2631
|
+
}
|
|
2632
|
+
for (let j = 0; j < empty; j++) {
|
|
2633
|
+
screen.setCell(colX + filled + j, rowY, { char: emptyChar, ...attrs, dim: true });
|
|
2634
|
+
}
|
|
2635
|
+
if (percentLabel) {
|
|
2636
|
+
const labelX = colX + barWidth;
|
|
2637
|
+
screen.writeString(labelX, rowY, percentLabel, { ...attrs, bold: true });
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
};
|
|
2642
|
+
|
|
1307
2643
|
// src/feedback/Spinner.ts
|
|
1308
|
-
var
|
|
2644
|
+
var import_core24 = require("@termuijs/core");
|
|
2645
|
+
var import_motion2 = require("@termuijs/motion");
|
|
1309
2646
|
var SPINNER_FRAMES = {
|
|
1310
2647
|
dots: {
|
|
1311
2648
|
frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
|
|
@@ -1348,6 +2685,7 @@ var Spinner = class extends Widget {
|
|
|
1348
2685
|
_color;
|
|
1349
2686
|
_lastTick = 0;
|
|
1350
2687
|
_elapsed = 0;
|
|
2688
|
+
_timerUnsub;
|
|
1351
2689
|
constructor(style = {}, options = {}) {
|
|
1352
2690
|
super({ height: 1, ...style });
|
|
1353
2691
|
const spinnerDef = typeof options.spinner === "string" ? SPINNER_FRAMES[options.spinner] ?? SPINNER_FRAMES.dots : options.spinner ?? SPINNER_FRAMES.dots;
|
|
@@ -1355,6 +2693,10 @@ var Spinner = class extends Widget {
|
|
|
1355
2693
|
this._interval = spinnerDef.interval;
|
|
1356
2694
|
this._label = options.label ?? "";
|
|
1357
2695
|
this._color = options.color ?? { type: "named", name: "cyan" };
|
|
2696
|
+
if (!import_core24.caps.unicode && this._frames.some((f) => f.codePointAt(0) > 127)) {
|
|
2697
|
+
this._frames = Array.from(import_core24.BRAILLE_SPIN);
|
|
2698
|
+
this._interval = 130;
|
|
2699
|
+
}
|
|
1358
2700
|
}
|
|
1359
2701
|
/** Update the spinner label */
|
|
1360
2702
|
setLabel(label) {
|
|
@@ -1365,17 +2707,33 @@ var Spinner = class extends Widget {
|
|
|
1365
2707
|
* Call this with a delta (ms) from the render loop.
|
|
1366
2708
|
*/
|
|
1367
2709
|
tick(deltaMs) {
|
|
2710
|
+
if (!import_core24.caps.motion) return;
|
|
1368
2711
|
this._elapsed += deltaMs;
|
|
1369
2712
|
if (this._elapsed >= this._interval) {
|
|
1370
2713
|
this._frameIndex = (this._frameIndex + 1) % this._frames.length;
|
|
1371
2714
|
this._elapsed = 0;
|
|
1372
2715
|
}
|
|
1373
2716
|
}
|
|
2717
|
+
/** Lifecycle: start the frame-advance timer (only when motion is enabled). */
|
|
2718
|
+
mount() {
|
|
2719
|
+
super.mount();
|
|
2720
|
+
if (!import_core24.caps.motion) return;
|
|
2721
|
+
this._timerUnsub = (0, import_motion2.timerPoolSubscribe)(this._interval, () => {
|
|
2722
|
+
this._frameIndex = (this._frameIndex + 1) % this._frames.length;
|
|
2723
|
+
this.markDirty();
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
/** Lifecycle: stop the frame-advance timer. */
|
|
2727
|
+
unmount() {
|
|
2728
|
+
this._timerUnsub?.();
|
|
2729
|
+
this._timerUnsub = void 0;
|
|
2730
|
+
super.unmount();
|
|
2731
|
+
}
|
|
1374
2732
|
_renderSelf(screen) {
|
|
1375
2733
|
const rect = this._getContentRect();
|
|
1376
2734
|
const { x, y, width } = rect;
|
|
1377
2735
|
if (width <= 0) return;
|
|
1378
|
-
const attrs = (0,
|
|
2736
|
+
const attrs = (0, import_core24.styleToCellAttrs)(this._style);
|
|
1379
2737
|
const frame = this._frames[this._frameIndex];
|
|
1380
2738
|
screen.writeString(x, y, frame, { ...attrs, fg: this._color });
|
|
1381
2739
|
if (this._label) {
|
|
@@ -1385,7 +2743,7 @@ var Spinner = class extends Widget {
|
|
|
1385
2743
|
};
|
|
1386
2744
|
|
|
1387
2745
|
// src/feedback/Scrollbar.ts
|
|
1388
|
-
var
|
|
2746
|
+
var import_core25 = require("@termuijs/core");
|
|
1389
2747
|
var Scrollbar = class extends Widget {
|
|
1390
2748
|
_contentLength;
|
|
1391
2749
|
_viewportLength;
|
|
@@ -1422,7 +2780,7 @@ var Scrollbar = class extends Widget {
|
|
|
1422
2780
|
if (width <= 0 || height <= 0 || this._contentLength <= 0) return;
|
|
1423
2781
|
if (this._contentLength <= this._viewportLength) return;
|
|
1424
2782
|
const vertical = this._orientation === "verticalRight" || this._orientation === "verticalLeft";
|
|
1425
|
-
const symbols = vertical ?
|
|
2783
|
+
const symbols = vertical ? import_core25.ScrollbarSets.VERTICAL : import_core25.ScrollbarSets.HORIZONTAL;
|
|
1426
2784
|
const trackX = this._orientation === "verticalLeft" ? x : this._orientation === "verticalRight" ? x + width - 1 : x;
|
|
1427
2785
|
const trackY = this._orientation === "horizontalTop" ? y : this._orientation === "horizontalBottom" ? y + height - 1 : y;
|
|
1428
2786
|
const totalLength = vertical ? height : width;
|
|
@@ -1466,23 +2824,755 @@ var Scrollbar = class extends Widget {
|
|
|
1466
2824
|
}
|
|
1467
2825
|
}
|
|
1468
2826
|
};
|
|
2827
|
+
|
|
2828
|
+
// src/feedback/Skeleton.ts
|
|
2829
|
+
var import_core26 = require("@termuijs/core");
|
|
2830
|
+
var import_motion3 = require("@termuijs/motion");
|
|
2831
|
+
var Skeleton = class extends Widget {
|
|
2832
|
+
_frame = 0;
|
|
2833
|
+
_shimmerPos = 0;
|
|
2834
|
+
_unsub;
|
|
2835
|
+
_chars;
|
|
2836
|
+
_variant;
|
|
2837
|
+
_intervalMs;
|
|
2838
|
+
constructor(style = {}, options = {}) {
|
|
2839
|
+
super(style);
|
|
2840
|
+
this._variant = options.variant ?? "pulse";
|
|
2841
|
+
this._intervalMs = options.intervalMs ?? 600;
|
|
2842
|
+
const defaultChars = import_core26.caps.unicode ? ["\u2591", "\u2592"] : ["-", "#"];
|
|
2843
|
+
this._chars = options.chars ?? defaultChars;
|
|
2844
|
+
if (import_core26.caps.motion) {
|
|
2845
|
+
this._unsub = (0, import_motion3.timerPoolSubscribe)(this._intervalMs, () => {
|
|
2846
|
+
this._frame = 1 - this._frame;
|
|
2847
|
+
if (this._variant === "shimmer") {
|
|
2848
|
+
this._shimmerPos++;
|
|
2849
|
+
}
|
|
2850
|
+
this.markDirty();
|
|
2851
|
+
});
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
unmount() {
|
|
2855
|
+
this._unsub?.();
|
|
2856
|
+
this._unsub = void 0;
|
|
2857
|
+
super.unmount();
|
|
2858
|
+
}
|
|
2859
|
+
_renderSelf(screen) {
|
|
2860
|
+
const rect = this._getContentRect();
|
|
2861
|
+
const { x, y, width, height } = rect;
|
|
2862
|
+
if (width <= 0 || height <= 0) return;
|
|
2863
|
+
if (this._variant === "pulse") {
|
|
2864
|
+
const char = this._chars[this._frame];
|
|
2865
|
+
const dim = this._frame === 0;
|
|
2866
|
+
for (let row = y; row < y + height; row++) {
|
|
2867
|
+
for (let col = x; col < x + width; col++) {
|
|
2868
|
+
screen.setCell(col, row, { char, dim, bold: false });
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
} else {
|
|
2872
|
+
const bandWidth = Math.max(1, Math.floor(width * 0.2));
|
|
2873
|
+
const totalPositions = width + bandWidth;
|
|
2874
|
+
const bandStart = this._shimmerPos % totalPositions;
|
|
2875
|
+
for (let row = y; row < y + height; row++) {
|
|
2876
|
+
for (let colOffset = 0; colOffset < width; colOffset++) {
|
|
2877
|
+
const col = x + colOffset;
|
|
2878
|
+
const inBand = colOffset >= bandStart && colOffset < bandStart + bandWidth;
|
|
2879
|
+
const char = inBand ? this._chars[1] : this._chars[0];
|
|
2880
|
+
screen.setCell(col, row, { char, dim: !inBand, bold: false });
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
};
|
|
2886
|
+
|
|
2887
|
+
// src/feedback/StatusMessage.ts
|
|
2888
|
+
var import_core27 = require("@termuijs/core");
|
|
2889
|
+
var ICONS_UNICODE = {
|
|
2890
|
+
success: "\u2713",
|
|
2891
|
+
error: "\u2717",
|
|
2892
|
+
warning: "\u26A0",
|
|
2893
|
+
info: "\u2139"
|
|
2894
|
+
};
|
|
2895
|
+
var ICONS_ASCII = {
|
|
2896
|
+
success: "+",
|
|
2897
|
+
error: "x",
|
|
2898
|
+
warning: "!",
|
|
2899
|
+
info: "i"
|
|
2900
|
+
};
|
|
2901
|
+
var COLORS = {
|
|
2902
|
+
success: { type: "named", name: "green" },
|
|
2903
|
+
error: { type: "named", name: "red" },
|
|
2904
|
+
warning: { type: "named", name: "yellow" },
|
|
2905
|
+
info: { type: "named", name: "cyan" }
|
|
2906
|
+
};
|
|
2907
|
+
var StatusMessage = class extends Widget {
|
|
2908
|
+
_message;
|
|
2909
|
+
_variant;
|
|
2910
|
+
_icon;
|
|
2911
|
+
constructor(message, style = {}, opts = {}) {
|
|
2912
|
+
super({ height: 1, ...style });
|
|
2913
|
+
this._message = message;
|
|
2914
|
+
this._variant = opts.variant ?? "info";
|
|
2915
|
+
this._icon = opts.icon;
|
|
2916
|
+
}
|
|
2917
|
+
setMessage(message) {
|
|
2918
|
+
this._message = message;
|
|
2919
|
+
this.markDirty();
|
|
2920
|
+
}
|
|
2921
|
+
setVariant(variant) {
|
|
2922
|
+
this._variant = variant;
|
|
2923
|
+
this.markDirty();
|
|
2924
|
+
}
|
|
2925
|
+
_renderSelf(screen) {
|
|
2926
|
+
const rect = this._getContentRect();
|
|
2927
|
+
const { x, y, width } = rect;
|
|
2928
|
+
if (width <= 0) return;
|
|
2929
|
+
const attrs = (0, import_core27.styleToCellAttrs)(this._style);
|
|
2930
|
+
const color = COLORS[this._variant];
|
|
2931
|
+
const iconMap = import_core27.caps.unicode ? ICONS_UNICODE : ICONS_ASCII;
|
|
2932
|
+
const icon = this._icon ?? iconMap[this._variant];
|
|
2933
|
+
screen.writeString(x, y, icon, { ...attrs, fg: color, bold: true });
|
|
2934
|
+
const msgX = x + icon.length + 1;
|
|
2935
|
+
const remaining = width - icon.length - 1;
|
|
2936
|
+
if (remaining > 0) {
|
|
2937
|
+
screen.writeString(msgX, y, this._message.slice(0, remaining), { ...attrs, fg: color });
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
};
|
|
2941
|
+
|
|
2942
|
+
// src/feedback/Banner.ts
|
|
2943
|
+
var import_core28 = require("@termuijs/core");
|
|
2944
|
+
var VARIANT_COLORS = {
|
|
2945
|
+
success: { type: "named", name: "green" },
|
|
2946
|
+
error: { type: "named", name: "red" },
|
|
2947
|
+
warning: { type: "named", name: "yellow" },
|
|
2948
|
+
info: { type: "named", name: "cyan" }
|
|
2949
|
+
};
|
|
2950
|
+
var Banner = class extends Widget {
|
|
2951
|
+
_variant;
|
|
2952
|
+
_title;
|
|
2953
|
+
_body;
|
|
2954
|
+
constructor(style = {}, opts = {}) {
|
|
2955
|
+
super({
|
|
2956
|
+
width: "100%",
|
|
2957
|
+
padding: 1,
|
|
2958
|
+
...style
|
|
2959
|
+
});
|
|
2960
|
+
this._variant = opts.variant ?? "info";
|
|
2961
|
+
this._title = opts.title ?? "";
|
|
2962
|
+
this._body = opts.body ?? "";
|
|
2963
|
+
}
|
|
2964
|
+
setTitle(title) {
|
|
2965
|
+
this._title = title;
|
|
2966
|
+
this.markDirty();
|
|
2967
|
+
}
|
|
2968
|
+
setBody(body) {
|
|
2969
|
+
this._body = body;
|
|
2970
|
+
this.markDirty();
|
|
2971
|
+
}
|
|
2972
|
+
setVariant(variant) {
|
|
2973
|
+
this._variant = variant;
|
|
2974
|
+
this.markDirty();
|
|
2975
|
+
}
|
|
2976
|
+
_renderSelf(screen) {
|
|
2977
|
+
const { x, y, width, height } = this._rect;
|
|
2978
|
+
if (width < 2 || height < 2) return;
|
|
2979
|
+
const attrs = (0, import_core28.styleToCellAttrs)(this._style);
|
|
2980
|
+
const color = VARIANT_COLORS[this._variant];
|
|
2981
|
+
const fg = color;
|
|
2982
|
+
const borderChars = (0, import_core28.getBorderChars)("single");
|
|
2983
|
+
if (borderChars) {
|
|
2984
|
+
screen.setCell(x, y, { char: borderChars.topLeft, fg });
|
|
2985
|
+
for (let c = 1; c < width - 1; c++) {
|
|
2986
|
+
screen.setCell(x + c, y, { char: borderChars.top, fg });
|
|
2987
|
+
}
|
|
2988
|
+
screen.setCell(x + width - 1, y, { char: borderChars.topRight, fg });
|
|
2989
|
+
screen.setCell(x, y + height - 1, { char: borderChars.bottomLeft, fg });
|
|
2990
|
+
for (let c = 1; c < width - 1; c++) {
|
|
2991
|
+
screen.setCell(x + c, y + height - 1, { char: borderChars.bottom, fg });
|
|
2992
|
+
}
|
|
2993
|
+
screen.setCell(x + width - 1, y + height - 1, { char: borderChars.bottomRight, fg });
|
|
2994
|
+
for (let r = 1; r < height - 1; r++) {
|
|
2995
|
+
screen.setCell(x, y + r, { char: borderChars.left, fg });
|
|
2996
|
+
screen.setCell(x + width - 1, y + r, { char: borderChars.right, fg });
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
const cx = x + 2;
|
|
3000
|
+
const cy = y + 2;
|
|
3001
|
+
const contentWidth = Math.max(0, width - 4);
|
|
3002
|
+
const contentHeight = Math.max(0, height - 4);
|
|
3003
|
+
let row = 0;
|
|
3004
|
+
if (this._title && row < contentHeight) {
|
|
3005
|
+
screen.writeString(cx, cy + row, this._title.slice(0, contentWidth), {
|
|
3006
|
+
...attrs,
|
|
3007
|
+
fg: color,
|
|
3008
|
+
bold: true
|
|
3009
|
+
});
|
|
3010
|
+
row++;
|
|
3011
|
+
}
|
|
3012
|
+
if (this._body) {
|
|
3013
|
+
const lines = this._body.split("\n");
|
|
3014
|
+
for (const line of lines) {
|
|
3015
|
+
if (row >= contentHeight) break;
|
|
3016
|
+
screen.writeString(cx, cy + row, line.slice(0, contentWidth), {
|
|
3017
|
+
...attrs,
|
|
3018
|
+
fg: color
|
|
3019
|
+
});
|
|
3020
|
+
row++;
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
};
|
|
3025
|
+
|
|
3026
|
+
// src/data/KeyValue.ts
|
|
3027
|
+
var import_core29 = require("@termuijs/core");
|
|
3028
|
+
var KeyValue = class extends Widget {
|
|
3029
|
+
_pairs;
|
|
3030
|
+
_separator;
|
|
3031
|
+
_keyColor;
|
|
3032
|
+
_valueColor;
|
|
3033
|
+
constructor(pairs, style = {}, opts = {}) {
|
|
3034
|
+
super(style);
|
|
3035
|
+
this._pairs = Array.isArray(pairs) ? pairs : Object.entries(pairs).map(([key, value]) => ({ key, value }));
|
|
3036
|
+
this._separator = opts.separator ?? ": ";
|
|
3037
|
+
this._keyColor = opts.keyColor;
|
|
3038
|
+
this._valueColor = opts.valueColor;
|
|
3039
|
+
}
|
|
3040
|
+
setPairs(pairs) {
|
|
3041
|
+
this._pairs = Array.isArray(pairs) ? pairs : Object.entries(pairs).map(([key, value]) => ({ key, value }));
|
|
3042
|
+
this.markDirty();
|
|
3043
|
+
}
|
|
3044
|
+
_renderSelf(screen) {
|
|
3045
|
+
const rect = this._getContentRect();
|
|
3046
|
+
const { x, y, width, height } = rect;
|
|
3047
|
+
if (width <= 0 || height <= 0 || this._pairs.length === 0) return;
|
|
3048
|
+
const attrs = (0, import_core29.styleToCellAttrs)(this._style);
|
|
3049
|
+
let maxKeyWidth = 0;
|
|
3050
|
+
for (const pair of this._pairs) {
|
|
3051
|
+
const w = (0, import_core29.stringWidth)(pair.key);
|
|
3052
|
+
if (w > maxKeyWidth) maxKeyWidth = w;
|
|
3053
|
+
}
|
|
3054
|
+
const sepWidth = (0, import_core29.stringWidth)(this._separator);
|
|
3055
|
+
for (let i = 0; i < this._pairs.length && i < height; i++) {
|
|
3056
|
+
const pair = this._pairs[i];
|
|
3057
|
+
if (!pair) continue;
|
|
3058
|
+
const keyWidth = (0, import_core29.stringWidth)(pair.key);
|
|
3059
|
+
const keyX = x + (maxKeyWidth - keyWidth);
|
|
3060
|
+
const sepX = x + maxKeyWidth;
|
|
3061
|
+
const valX = sepX + sepWidth;
|
|
3062
|
+
const valWidth = Math.max(0, width - maxKeyWidth - sepWidth);
|
|
3063
|
+
screen.writeString(keyX, y + i, pair.key, {
|
|
3064
|
+
...attrs,
|
|
3065
|
+
fg: this._keyColor ?? attrs.fg,
|
|
3066
|
+
bold: true
|
|
3067
|
+
});
|
|
3068
|
+
screen.writeString(sepX, y + i, this._separator, { ...attrs, dim: true });
|
|
3069
|
+
if (valWidth > 0) {
|
|
3070
|
+
screen.writeString(valX, y + i, pair.value.slice(0, valWidth), {
|
|
3071
|
+
...attrs,
|
|
3072
|
+
fg: this._valueColor ?? attrs.fg
|
|
3073
|
+
});
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
};
|
|
3078
|
+
|
|
3079
|
+
// src/data/Sidebar.ts
|
|
3080
|
+
var import_core30 = require("@termuijs/core");
|
|
3081
|
+
var Sidebar = class extends Widget {
|
|
3082
|
+
_items;
|
|
3083
|
+
_collapsed;
|
|
3084
|
+
_collapsedWidth;
|
|
3085
|
+
_activeColor;
|
|
3086
|
+
_badgeColor;
|
|
3087
|
+
constructor(items, style = {}, opts = {}) {
|
|
3088
|
+
super(style);
|
|
3089
|
+
this._items = items;
|
|
3090
|
+
this._collapsed = opts.collapsed ?? false;
|
|
3091
|
+
this._collapsedWidth = opts.collapsedWidth ?? 3;
|
|
3092
|
+
this._activeColor = opts.activeColor ?? { type: "named", name: "cyan" };
|
|
3093
|
+
this._badgeColor = opts.badgeColor ?? { type: "named", name: "yellow" };
|
|
3094
|
+
}
|
|
3095
|
+
setItems(items) {
|
|
3096
|
+
this._items = items;
|
|
3097
|
+
this.markDirty();
|
|
3098
|
+
}
|
|
3099
|
+
setCollapsed(collapsed) {
|
|
3100
|
+
this._collapsed = collapsed;
|
|
3101
|
+
this.markDirty();
|
|
3102
|
+
}
|
|
3103
|
+
toggle() {
|
|
3104
|
+
this._collapsed = !this._collapsed;
|
|
3105
|
+
this.markDirty();
|
|
3106
|
+
}
|
|
3107
|
+
get isCollapsed() {
|
|
3108
|
+
return this._collapsed;
|
|
3109
|
+
}
|
|
3110
|
+
_renderSelf(screen) {
|
|
3111
|
+
const rect = this._getContentRect();
|
|
3112
|
+
const { x, y, width, height } = rect;
|
|
3113
|
+
if (width <= 0 || height <= 0) return;
|
|
3114
|
+
const attrs = (0, import_core30.styleToCellAttrs)(this._style);
|
|
3115
|
+
for (let i = 0; i < this._items.length && i < height; i++) {
|
|
3116
|
+
const item = this._items[i];
|
|
3117
|
+
if (!item) continue;
|
|
3118
|
+
const isActive = item.active ?? false;
|
|
3119
|
+
const fg = isActive ? this._activeColor : attrs.fg;
|
|
3120
|
+
if (this._collapsed) {
|
|
3121
|
+
const char = item.label.charAt(0) || " ";
|
|
3122
|
+
screen.writeString(x, y + i, char, { ...attrs, fg, bold: isActive });
|
|
3123
|
+
} else {
|
|
3124
|
+
const prefix = isActive ? "\u25B6 " : " ";
|
|
3125
|
+
const prefixWidth = (0, import_core30.stringWidth)(prefix);
|
|
3126
|
+
screen.writeString(x, y + i, prefix, { ...attrs, fg });
|
|
3127
|
+
const badgeText = item.badge ? ` [${item.badge}]` : "";
|
|
3128
|
+
const badgeWidth = (0, import_core30.stringWidth)(badgeText);
|
|
3129
|
+
const labelWidth = Math.max(0, width - prefixWidth - badgeWidth);
|
|
3130
|
+
const label = item.label.slice(0, labelWidth);
|
|
3131
|
+
screen.writeString(x + prefixWidth, y + i, label, {
|
|
3132
|
+
...attrs,
|
|
3133
|
+
fg,
|
|
3134
|
+
bold: isActive
|
|
3135
|
+
});
|
|
3136
|
+
if (item.badge && badgeWidth > 0) {
|
|
3137
|
+
const badgeX = x + width - badgeWidth;
|
|
3138
|
+
screen.writeString(badgeX, y + i, badgeText, {
|
|
3139
|
+
...attrs,
|
|
3140
|
+
fg: this._badgeColor
|
|
3141
|
+
});
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
};
|
|
3147
|
+
|
|
3148
|
+
// src/data/LineChart.ts
|
|
3149
|
+
var import_core31 = require("@termuijs/core");
|
|
3150
|
+
var POINT_CHAR_UNICODE = "\u25CF";
|
|
3151
|
+
var POINT_CHAR_ASCII = "*";
|
|
3152
|
+
var LineChart = class extends Widget {
|
|
3153
|
+
_data;
|
|
3154
|
+
_color;
|
|
3155
|
+
_showYAxis;
|
|
3156
|
+
_showXAxis;
|
|
3157
|
+
_yLabel;
|
|
3158
|
+
_max;
|
|
3159
|
+
_min;
|
|
3160
|
+
constructor(data, style = {}, opts = {}) {
|
|
3161
|
+
super(style);
|
|
3162
|
+
this._data = data;
|
|
3163
|
+
this._color = opts.color ?? { type: "named", name: "cyan" };
|
|
3164
|
+
this._showYAxis = opts.showYAxis ?? false;
|
|
3165
|
+
this._showXAxis = opts.showXAxis ?? false;
|
|
3166
|
+
this._yLabel = opts.yLabel ?? "";
|
|
3167
|
+
this._max = opts.max;
|
|
3168
|
+
this._min = opts.min;
|
|
3169
|
+
}
|
|
3170
|
+
setData(data) {
|
|
3171
|
+
this._data = data;
|
|
3172
|
+
this.markDirty();
|
|
3173
|
+
}
|
|
3174
|
+
pushValue(value) {
|
|
3175
|
+
this._data.push(value);
|
|
3176
|
+
this.markDirty();
|
|
3177
|
+
}
|
|
3178
|
+
_renderSelf(screen) {
|
|
3179
|
+
const rect = this._getContentRect();
|
|
3180
|
+
let { x, y, width, height } = rect;
|
|
3181
|
+
if (width <= 0 || height <= 0 || this._data.length === 0) return;
|
|
3182
|
+
const attrs = (0, import_core31.styleToCellAttrs)(this._style);
|
|
3183
|
+
const plotHeight = this._showXAxis ? Math.max(1, height - 1) : height;
|
|
3184
|
+
const yAxisWidth = this._showYAxis ? 5 : 0;
|
|
3185
|
+
const plotWidth = Math.max(1, width - yAxisWidth);
|
|
3186
|
+
const plotX = x + yAxisWidth;
|
|
3187
|
+
const min = this._min ?? Math.min(...this._data);
|
|
3188
|
+
const max = this._max ?? Math.max(...this._data);
|
|
3189
|
+
const range = max - min || 1;
|
|
3190
|
+
const samples = [];
|
|
3191
|
+
for (let col = 0; col < plotWidth; col++) {
|
|
3192
|
+
const idx = Math.floor(col / plotWidth * this._data.length);
|
|
3193
|
+
const val = this._data[Math.min(idx, this._data.length - 1)];
|
|
3194
|
+
samples.push(val ?? min);
|
|
3195
|
+
}
|
|
3196
|
+
const toRow = (v) => {
|
|
3197
|
+
const norm = (v - min) / range;
|
|
3198
|
+
return Math.max(0, Math.min(plotHeight - 1, Math.round((1 - norm) * (plotHeight - 1))));
|
|
3199
|
+
};
|
|
3200
|
+
if (this._showYAxis && yAxisWidth > 0) {
|
|
3201
|
+
for (let row = 0; row < plotHeight; row++) {
|
|
3202
|
+
const v = plotHeight > 1 ? max - row / (plotHeight - 1) * range : max;
|
|
3203
|
+
if (row === 0 || row === plotHeight - 1) {
|
|
3204
|
+
const label = v.toFixed(0).padStart(yAxisWidth - 1, " ");
|
|
3205
|
+
screen.writeString(x, y + row, label + "\u2524", { ...attrs, dim: true });
|
|
3206
|
+
} else {
|
|
3207
|
+
screen.writeString(x + yAxisWidth - 1, y + row, "\u2502", { ...attrs, dim: true });
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
const pointChar = import_core31.caps.unicode ? POINT_CHAR_UNICODE : POINT_CHAR_ASCII;
|
|
3212
|
+
let prevRow = null;
|
|
3213
|
+
for (let col = 0; col < samples.length; col++) {
|
|
3214
|
+
const val = samples[col];
|
|
3215
|
+
if (val === void 0) continue;
|
|
3216
|
+
const row = toRow(val);
|
|
3217
|
+
if (prevRow !== null && Math.abs(row - prevRow) > 1) {
|
|
3218
|
+
const top = Math.min(prevRow, row) + 1;
|
|
3219
|
+
const bottom = Math.max(prevRow, row);
|
|
3220
|
+
for (let r = top; r < bottom; r++) {
|
|
3221
|
+
screen.setCell(plotX + col, y + r, { char: "\u2502", fg: this._color, dim: true });
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
screen.setCell(plotX + col, y + row, { char: pointChar, fg: this._color });
|
|
3225
|
+
prevRow = row;
|
|
3226
|
+
}
|
|
3227
|
+
if (this._showXAxis) {
|
|
3228
|
+
const axisY = y + height - 1;
|
|
3229
|
+
for (let col = 0; col < plotWidth; col++) {
|
|
3230
|
+
screen.setCell(plotX + col, axisY, { char: "\u2500", ...attrs, dim: true });
|
|
3231
|
+
}
|
|
3232
|
+
if (yAxisWidth > 0) {
|
|
3233
|
+
screen.setCell(plotX - 1, axisY, { char: "\u2514", ...attrs, dim: true });
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
};
|
|
3238
|
+
|
|
3239
|
+
// src/data/HeatMap.ts
|
|
3240
|
+
var import_core32 = require("@termuijs/core");
|
|
3241
|
+
var SHADE_CHARS_UNICODE = ["\u2591", "\u2592", "\u2593", "\u2588"];
|
|
3242
|
+
var SHADE_CHARS_ASCII = [".", ":", "+", "#"];
|
|
3243
|
+
var HeatMap = class extends Widget {
|
|
3244
|
+
_matrix;
|
|
3245
|
+
_highColor;
|
|
3246
|
+
_lowColor;
|
|
3247
|
+
_rowLabels;
|
|
3248
|
+
_colLabels;
|
|
3249
|
+
constructor(matrix, style = {}, opts = {}) {
|
|
3250
|
+
super(style);
|
|
3251
|
+
this._matrix = matrix;
|
|
3252
|
+
this._highColor = opts.highColor ?? { type: "named", name: "red" };
|
|
3253
|
+
this._lowColor = opts.lowColor ?? { type: "named", name: "brightBlack" };
|
|
3254
|
+
this._rowLabels = opts.rowLabels ?? [];
|
|
3255
|
+
this._colLabels = opts.colLabels ?? [];
|
|
3256
|
+
}
|
|
3257
|
+
setMatrix(matrix) {
|
|
3258
|
+
this._matrix = matrix;
|
|
3259
|
+
this.markDirty();
|
|
3260
|
+
}
|
|
3261
|
+
_renderSelf(screen) {
|
|
3262
|
+
const rect = this._getContentRect();
|
|
3263
|
+
const { x, y, width, height } = rect;
|
|
3264
|
+
if (width <= 0 || height <= 0 || this._matrix.length === 0) return;
|
|
3265
|
+
const attrs = (0, import_core32.styleToCellAttrs)(this._style);
|
|
3266
|
+
const shadeChars = import_core32.caps.unicode ? SHADE_CHARS_UNICODE : SHADE_CHARS_ASCII;
|
|
3267
|
+
const labelWidth = this._rowLabels.length > 0 ? Math.max(...this._rowLabels.map((l) => l.length)) + 1 : 0;
|
|
3268
|
+
let globalMin = Infinity;
|
|
3269
|
+
let globalMax = -Infinity;
|
|
3270
|
+
for (const row of this._matrix) {
|
|
3271
|
+
for (const val of row) {
|
|
3272
|
+
if (val < globalMin) globalMin = val;
|
|
3273
|
+
if (val > globalMax) globalMax = val;
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
const range = globalMax - globalMin || 1;
|
|
3277
|
+
let startRow = 0;
|
|
3278
|
+
if (this._colLabels.length > 0) {
|
|
3279
|
+
for (let col = 0; col < this._colLabels.length; col++) {
|
|
3280
|
+
const cx = x + labelWidth + col;
|
|
3281
|
+
if (cx >= x + width) break;
|
|
3282
|
+
const label = (this._colLabels[col] ?? "").charAt(0);
|
|
3283
|
+
screen.setCell(cx, y, { char: label, ...attrs, dim: true });
|
|
3284
|
+
}
|
|
3285
|
+
startRow = 1;
|
|
3286
|
+
}
|
|
3287
|
+
for (let r = 0; r < this._matrix.length; r++) {
|
|
3288
|
+
const rowY = y + startRow + r;
|
|
3289
|
+
if (rowY >= y + height) break;
|
|
3290
|
+
if (this._rowLabels[r]) {
|
|
3291
|
+
const label = this._rowLabels[r].slice(0, labelWidth - 1).padEnd(labelWidth - 1, " ");
|
|
3292
|
+
screen.writeString(x, rowY, label + " ", { ...attrs, dim: true });
|
|
3293
|
+
}
|
|
3294
|
+
const row = this._matrix[r];
|
|
3295
|
+
if (!row) continue;
|
|
3296
|
+
for (let col = 0; col < row.length; col++) {
|
|
3297
|
+
const cx = x + labelWidth + col;
|
|
3298
|
+
if (cx >= x + width) break;
|
|
3299
|
+
const val = row[col] ?? 0;
|
|
3300
|
+
const norm = (val - globalMin) / range;
|
|
3301
|
+
const level = Math.min(3, Math.floor(norm * 4));
|
|
3302
|
+
const char = shadeChars[level] ?? shadeChars[0];
|
|
3303
|
+
const fg = norm >= 0.75 ? this._highColor : this._lowColor;
|
|
3304
|
+
screen.setCell(cx, rowY, { char, fg });
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
};
|
|
3309
|
+
|
|
3310
|
+
// src/data/Definition.ts
|
|
3311
|
+
var import_core33 = require("@termuijs/core");
|
|
3312
|
+
var Definition = class extends Widget {
|
|
3313
|
+
_pairs;
|
|
3314
|
+
_indent;
|
|
3315
|
+
_spacing;
|
|
3316
|
+
_termColor;
|
|
3317
|
+
_definitionColor;
|
|
3318
|
+
constructor(pairs, style = {}, opts = {}) {
|
|
3319
|
+
super(style);
|
|
3320
|
+
this._pairs = Array.isArray(pairs) ? pairs : Object.entries(pairs).map(([term, definition]) => ({ term, definition }));
|
|
3321
|
+
this._indent = opts.indent ?? 2;
|
|
3322
|
+
this._spacing = opts.spacing ?? true;
|
|
3323
|
+
this._termColor = opts.termColor;
|
|
3324
|
+
this._definitionColor = opts.definitionColor;
|
|
3325
|
+
}
|
|
3326
|
+
setPairs(pairs) {
|
|
3327
|
+
this._pairs = Array.isArray(pairs) ? pairs : Object.entries(pairs).map(([term, definition]) => ({ term, definition }));
|
|
3328
|
+
this.markDirty();
|
|
3329
|
+
}
|
|
3330
|
+
_renderSelf(screen) {
|
|
3331
|
+
const rect = this._getContentRect();
|
|
3332
|
+
const { x, y, width, height } = rect;
|
|
3333
|
+
if (width <= 0 || height <= 0 || this._pairs.length === 0) return;
|
|
3334
|
+
const attrs = (0, import_core33.styleToCellAttrs)(this._style);
|
|
3335
|
+
const indent = Math.min(this._indent, width - 1);
|
|
3336
|
+
let row = 0;
|
|
3337
|
+
for (const pair of this._pairs) {
|
|
3338
|
+
if (row >= height) break;
|
|
3339
|
+
screen.writeString(x, y + row, pair.term.slice(0, width), {
|
|
3340
|
+
...attrs,
|
|
3341
|
+
fg: this._termColor ?? attrs.fg,
|
|
3342
|
+
bold: true
|
|
3343
|
+
});
|
|
3344
|
+
row++;
|
|
3345
|
+
if (row >= height) break;
|
|
3346
|
+
const defWidth = Math.max(1, width - indent);
|
|
3347
|
+
const words = pair.definition.split(" ");
|
|
3348
|
+
let line = "";
|
|
3349
|
+
for (const word of words) {
|
|
3350
|
+
if (line.length === 0) {
|
|
3351
|
+
line = word;
|
|
3352
|
+
} else if (line.length + 1 + word.length <= defWidth) {
|
|
3353
|
+
line += " " + word;
|
|
3354
|
+
} else {
|
|
3355
|
+
if (row >= height) break;
|
|
3356
|
+
screen.writeString(x + indent, y + row, line, {
|
|
3357
|
+
...attrs,
|
|
3358
|
+
fg: this._definitionColor ?? attrs.fg
|
|
3359
|
+
});
|
|
3360
|
+
row++;
|
|
3361
|
+
line = word;
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
if (line && row < height) {
|
|
3365
|
+
screen.writeString(x + indent, y + row, line, {
|
|
3366
|
+
...attrs,
|
|
3367
|
+
fg: this._definitionColor ?? attrs.fg
|
|
3368
|
+
});
|
|
3369
|
+
row++;
|
|
3370
|
+
}
|
|
3371
|
+
if (this._spacing && row < height) {
|
|
3372
|
+
row++;
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
};
|
|
3377
|
+
|
|
3378
|
+
// src/display/BigText.ts
|
|
3379
|
+
var import_core34 = require("@termuijs/core");
|
|
3380
|
+
var CHAR_MAP = {
|
|
3381
|
+
"A": [" # ", "# #", "###", "# #", "# #"],
|
|
3382
|
+
"B": ["## ", "# #", "## ", "# #", "## "],
|
|
3383
|
+
"C": [" ##", "# ", "# ", "# ", " ##"],
|
|
3384
|
+
"D": ["## ", "# #", "# #", "# #", "## "],
|
|
3385
|
+
"E": ["###", "# ", "## ", "# ", "###"],
|
|
3386
|
+
"F": ["###", "# ", "## ", "# ", "# "],
|
|
3387
|
+
"G": [" ##", "# ", "# #", "# #", " ##"],
|
|
3388
|
+
"H": ["# #", "# #", "###", "# #", "# #"],
|
|
3389
|
+
"I": ["###", " # ", " # ", " # ", "###"],
|
|
3390
|
+
"J": ["###", " #", " #", "# #", " # "],
|
|
3391
|
+
"K": ["# #", "## ", "# ", "## ", "# #"],
|
|
3392
|
+
"L": ["# ", "# ", "# ", "# ", "###"],
|
|
3393
|
+
"M": ["# #", "###", "# #", "# #", "# #"],
|
|
3394
|
+
"N": ["# #", "## ", "# #", "# #", "# #"],
|
|
3395
|
+
"O": [" # ", "# #", "# #", "# #", " # "],
|
|
3396
|
+
"P": ["## ", "# #", "## ", "# ", "# "],
|
|
3397
|
+
"Q": [" # ", "# #", "# #", "##:", " ##"],
|
|
3398
|
+
"R": ["## ", "# #", "## ", "## ", "# #"],
|
|
3399
|
+
"S": [" ##", "# ", " # ", " #", "## "],
|
|
3400
|
+
"T": ["###", " # ", " # ", " # ", " # "],
|
|
3401
|
+
"U": ["# #", "# #", "# #", "# #", "###"],
|
|
3402
|
+
"V": ["# #", "# #", "# #", "# #", " # "],
|
|
3403
|
+
"W": ["# #", "# #", "# #", "###", "# #"],
|
|
3404
|
+
"X": ["# #", "# #", " # ", "# #", "# #"],
|
|
3405
|
+
"Y": ["# #", "# #", " # ", " # ", " # "],
|
|
3406
|
+
"Z": ["###", " #", " # ", "# ", "###"],
|
|
3407
|
+
"0": [" # ", "# #", "# #", "# #", " # "],
|
|
3408
|
+
"1": [" # ", "## ", " # ", " # ", "###"],
|
|
3409
|
+
"2": [" # ", "# #", " # ", "# ", "###"],
|
|
3410
|
+
"3": ["## ", " #", " ##", " #", "## "],
|
|
3411
|
+
"4": ["# #", "# #", "###", " #", " #"],
|
|
3412
|
+
"5": ["###", "# ", "## ", " #", "## "],
|
|
3413
|
+
"6": [" # ", "# ", "## ", "# #", " # "],
|
|
3414
|
+
"7": ["###", " #", " # ", "# ", "# "],
|
|
3415
|
+
"8": [" # ", "# #", " # ", "# #", " # "],
|
|
3416
|
+
"9": [" # ", "# #", " ##", " #", " # "],
|
|
3417
|
+
" ": [" ", " ", " ", " ", " "],
|
|
3418
|
+
"!": [" # ", " # ", " # ", " ", " # "],
|
|
3419
|
+
".": [" ", " ", " ", " ", " # "],
|
|
3420
|
+
"-": [" ", " ", "###", " ", " "],
|
|
3421
|
+
":": [" ", " # ", " ", " # ", " "]
|
|
3422
|
+
};
|
|
3423
|
+
var CHAR_HEIGHT = 5;
|
|
3424
|
+
var CHAR_WIDTH = 3;
|
|
3425
|
+
var BigText = class extends Widget {
|
|
3426
|
+
_text;
|
|
3427
|
+
_color;
|
|
3428
|
+
constructor(text, style = {}, opts = {}) {
|
|
3429
|
+
super(style);
|
|
3430
|
+
this._text = text.toUpperCase();
|
|
3431
|
+
this._color = opts.color ?? { type: "named", name: "white" };
|
|
3432
|
+
}
|
|
3433
|
+
setText(text) {
|
|
3434
|
+
this._text = text.toUpperCase();
|
|
3435
|
+
this.markDirty();
|
|
3436
|
+
}
|
|
3437
|
+
_renderSelf(screen) {
|
|
3438
|
+
const rect = this._getContentRect();
|
|
3439
|
+
const { x, y, width, height } = rect;
|
|
3440
|
+
if (width <= 0 || height <= 0) return;
|
|
3441
|
+
const attrs = (0, import_core34.styleToCellAttrs)(this._style);
|
|
3442
|
+
const fg = this._color;
|
|
3443
|
+
let curX = x;
|
|
3444
|
+
for (const ch of this._text) {
|
|
3445
|
+
const glyph = CHAR_MAP[ch] ?? ["# #", "# #", "# #", "# #", "# #"];
|
|
3446
|
+
const glyphWidth = glyph[0]?.length ?? CHAR_WIDTH;
|
|
3447
|
+
if (curX + glyphWidth > x + width) break;
|
|
3448
|
+
for (let row = 0; row < CHAR_HEIGHT && row < height; row++) {
|
|
3449
|
+
const rowStr = glyph[row] ?? "";
|
|
3450
|
+
for (let col = 0; col < rowStr.length; col++) {
|
|
3451
|
+
if (rowStr[col] !== " ") {
|
|
3452
|
+
screen.setCell(curX + col, y + row, { char: "\u2588", ...attrs, fg });
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
curX += glyphWidth + 1;
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3459
|
+
};
|
|
3460
|
+
|
|
3461
|
+
// src/display/Gradient.ts
|
|
3462
|
+
var import_core35 = require("@termuijs/core");
|
|
3463
|
+
function hexToRgb(hex) {
|
|
3464
|
+
const clean = hex.replace("#", "");
|
|
3465
|
+
if (clean.length !== 6) return null;
|
|
3466
|
+
const r = parseInt(clean.slice(0, 2), 16);
|
|
3467
|
+
const g = parseInt(clean.slice(2, 4), 16);
|
|
3468
|
+
const b = parseInt(clean.slice(4, 6), 16);
|
|
3469
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) return null;
|
|
3470
|
+
return [r, g, b];
|
|
3471
|
+
}
|
|
3472
|
+
function lerpRgb(a, b, t) {
|
|
3473
|
+
return [
|
|
3474
|
+
Math.round(a[0] + (b[0] - a[0]) * t),
|
|
3475
|
+
Math.round(a[1] + (b[1] - a[1]) * t),
|
|
3476
|
+
Math.round(a[2] + (b[2] - a[2]) * t)
|
|
3477
|
+
];
|
|
3478
|
+
}
|
|
3479
|
+
var Gradient = class extends Widget {
|
|
3480
|
+
_text;
|
|
3481
|
+
_startColor;
|
|
3482
|
+
_endColor;
|
|
3483
|
+
_align;
|
|
3484
|
+
constructor(text, style = {}, opts = {}) {
|
|
3485
|
+
super({ height: 1, ...style });
|
|
3486
|
+
this._text = text;
|
|
3487
|
+
this._startColor = opts.startColor ?? "#ff0000";
|
|
3488
|
+
this._endColor = opts.endColor ?? "#0000ff";
|
|
3489
|
+
this._align = opts.align ?? "left";
|
|
3490
|
+
}
|
|
3491
|
+
setText(text) {
|
|
3492
|
+
this._text = text;
|
|
3493
|
+
this.markDirty();
|
|
3494
|
+
}
|
|
3495
|
+
setColors(start, end) {
|
|
3496
|
+
this._startColor = start;
|
|
3497
|
+
this._endColor = end;
|
|
3498
|
+
this.markDirty();
|
|
3499
|
+
}
|
|
3500
|
+
_renderSelf(screen) {
|
|
3501
|
+
const rect = this._getContentRect();
|
|
3502
|
+
const { x, y, width } = rect;
|
|
3503
|
+
if (width <= 0 || !this._text) return;
|
|
3504
|
+
const attrs = (0, import_core35.styleToCellAttrs)(this._style);
|
|
3505
|
+
if (!import_core35.caps.color) {
|
|
3506
|
+
screen.writeString(x, y, this._text.slice(0, width), attrs);
|
|
3507
|
+
return;
|
|
3508
|
+
}
|
|
3509
|
+
const startRgb = hexToRgb(this._startColor);
|
|
3510
|
+
const endRgb = hexToRgb(this._endColor);
|
|
3511
|
+
const chars = Array.from(this._text).slice(0, width);
|
|
3512
|
+
const len = chars.length;
|
|
3513
|
+
let offsetX = 0;
|
|
3514
|
+
if (this._align === "center") offsetX = Math.floor((width - len) / 2);
|
|
3515
|
+
else if (this._align === "right") offsetX = width - len;
|
|
3516
|
+
offsetX = Math.max(0, offsetX);
|
|
3517
|
+
for (let i = 0; i < chars.length; i++) {
|
|
3518
|
+
const t = len > 1 ? i / (len - 1) : 0;
|
|
3519
|
+
let fg;
|
|
3520
|
+
if (startRgb && endRgb) {
|
|
3521
|
+
const [r, g, b] = lerpRgb(startRgb, endRgb, t);
|
|
3522
|
+
fg = { type: "rgb", r, g, b };
|
|
3523
|
+
} else if (startRgb) {
|
|
3524
|
+
fg = (0, import_core35.parseColor)(this._startColor) ?? attrs.fg;
|
|
3525
|
+
} else {
|
|
3526
|
+
fg = attrs.fg;
|
|
3527
|
+
}
|
|
3528
|
+
screen.setCell(x + offsetX + i, y, { char: chars[i] ?? " ", ...attrs, fg });
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
};
|
|
1469
3532
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1470
3533
|
0 && (module.exports = {
|
|
3534
|
+
Banner,
|
|
1471
3535
|
BarChart,
|
|
3536
|
+
BigText,
|
|
1472
3537
|
Box,
|
|
3538
|
+
Card,
|
|
3539
|
+
Center,
|
|
3540
|
+
ChatMessage,
|
|
3541
|
+
Columns,
|
|
3542
|
+
CommandPalette,
|
|
3543
|
+
Definition,
|
|
3544
|
+
DiffView,
|
|
1473
3545
|
Gauge,
|
|
3546
|
+
Gradient,
|
|
3547
|
+
Grid,
|
|
3548
|
+
HeatMap,
|
|
3549
|
+
JSONView,
|
|
3550
|
+
KeyValue,
|
|
3551
|
+
LineChart,
|
|
1474
3552
|
List,
|
|
1475
3553
|
LogView,
|
|
3554
|
+
MultiProgress,
|
|
1476
3555
|
ProgressBar,
|
|
1477
3556
|
SPINNER_FRAMES,
|
|
3557
|
+
ScrollView,
|
|
1478
3558
|
Scrollbar,
|
|
3559
|
+
Sidebar,
|
|
3560
|
+
Skeleton,
|
|
1479
3561
|
Sparkline,
|
|
1480
3562
|
Spinner,
|
|
1481
3563
|
StatusIndicator,
|
|
3564
|
+
StatusMessage,
|
|
3565
|
+
StreamingText,
|
|
1482
3566
|
Table,
|
|
1483
3567
|
Text,
|
|
1484
3568
|
TextInput,
|
|
3569
|
+
ToolApproval,
|
|
3570
|
+
ToolCall,
|
|
3571
|
+
Tree,
|
|
1485
3572
|
VirtualList,
|
|
1486
|
-
Widget
|
|
3573
|
+
Widget,
|
|
3574
|
+
computeRange,
|
|
3575
|
+
computeVariableRange,
|
|
3576
|
+
jsonToTree
|
|
1487
3577
|
});
|
|
1488
3578
|
//# sourceMappingURL=index.cjs.map
|