@asm-agent/tui 0.8.2
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 +795 -0
- package/dist/autocomplete.d.ts +61 -0
- package/dist/autocomplete.d.ts.map +1 -0
- package/dist/autocomplete.js +601 -0
- package/dist/autocomplete.js.map +1 -0
- package/dist/components/box.d.ts +24 -0
- package/dist/components/box.d.ts.map +1 -0
- package/dist/components/box.js +114 -0
- package/dist/components/box.js.map +1 -0
- package/dist/components/cancellable-loader.d.ts +22 -0
- package/dist/components/cancellable-loader.d.ts.map +1 -0
- package/dist/components/cancellable-loader.js +35 -0
- package/dist/components/cancellable-loader.js.map +1 -0
- package/dist/components/editor.d.ts +275 -0
- package/dist/components/editor.d.ts.map +1 -0
- package/dist/components/editor.js +1968 -0
- package/dist/components/editor.js.map +1 -0
- package/dist/components/image.d.ts +34 -0
- package/dist/components/image.d.ts.map +1 -0
- package/dist/components/image.js +96 -0
- package/dist/components/image.js.map +1 -0
- package/dist/components/input.d.ts +37 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +385 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/loader.d.ts +29 -0
- package/dist/components/loader.d.ts.map +1 -0
- package/dist/components/loader.js +69 -0
- package/dist/components/loader.js.map +1 -0
- package/dist/components/markdown.d.ts +100 -0
- package/dist/components/markdown.d.ts.map +1 -0
- package/dist/components/markdown.js +773 -0
- package/dist/components/markdown.js.map +1 -0
- package/dist/components/select-list.d.ts +61 -0
- package/dist/components/select-list.d.ts.map +1 -0
- package/dist/components/select-list.js +206 -0
- package/dist/components/select-list.js.map +1 -0
- package/dist/components/settings-list.d.ts +49 -0
- package/dist/components/settings-list.d.ts.map +1 -0
- package/dist/components/settings-list.js +170 -0
- package/dist/components/settings-list.js.map +1 -0
- package/dist/components/spacer.d.ts +12 -0
- package/dist/components/spacer.d.ts.map +1 -0
- package/dist/components/spacer.js +21 -0
- package/dist/components/spacer.js.map +1 -0
- package/dist/components/text.d.ts +19 -0
- package/dist/components/text.d.ts.map +1 -0
- package/dist/components/text.js +77 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/truncated-text.d.ts +14 -0
- package/dist/components/truncated-text.d.ts.map +1 -0
- package/dist/components/truncated-text.js +44 -0
- package/dist/components/truncated-text.js.map +1 -0
- package/dist/editor-component.d.ts +51 -0
- package/dist/editor-component.d.ts.map +1 -0
- package/dist/editor-component.js +2 -0
- package/dist/editor-component.js.map +1 -0
- package/dist/fullscreen.d.ts +105 -0
- package/dist/fullscreen.d.ts.map +1 -0
- package/dist/fullscreen.js +597 -0
- package/dist/fullscreen.js.map +1 -0
- package/dist/fuzzy.d.ts +26 -0
- package/dist/fuzzy.d.ts.map +1 -0
- package/dist/fuzzy.js +114 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/keybindings.d.ts +239 -0
- package/dist/keybindings.d.ts.map +1 -0
- package/dist/keybindings.js +222 -0
- package/dist/keybindings.js.map +1 -0
- package/dist/keys.d.ts +184 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +1163 -0
- package/dist/keys.js.map +1 -0
- package/dist/kill-ring.d.ts +26 -0
- package/dist/kill-ring.d.ts.map +1 -0
- package/dist/kill-ring.js +42 -0
- package/dist/kill-ring.js.map +1 -0
- package/dist/latex.d.ts +21 -0
- package/dist/latex.d.ts.map +1 -0
- package/dist/latex.js +797 -0
- package/dist/latex.js.map +1 -0
- package/dist/mouse.d.ts +24 -0
- package/dist/mouse.d.ts.map +1 -0
- package/dist/mouse.js +34 -0
- package/dist/mouse.js.map +1 -0
- package/dist/render-cache.d.ts +9 -0
- package/dist/render-cache.d.ts.map +1 -0
- package/dist/render-cache.js +23 -0
- package/dist/render-cache.js.map +1 -0
- package/dist/selection-metadata.d.ts +22 -0
- package/dist/selection-metadata.d.ts.map +1 -0
- package/dist/selection-metadata.js +141 -0
- package/dist/selection-metadata.js.map +1 -0
- package/dist/slash-command-context.d.ts +12 -0
- package/dist/slash-command-context.d.ts.map +1 -0
- package/dist/slash-command-context.js +32 -0
- package/dist/slash-command-context.js.map +1 -0
- package/dist/stdin-buffer.d.ts +50 -0
- package/dist/stdin-buffer.d.ts.map +1 -0
- package/dist/stdin-buffer.js +313 -0
- package/dist/stdin-buffer.js.map +1 -0
- package/dist/terminal-colors.d.ts +31 -0
- package/dist/terminal-colors.d.ts.map +1 -0
- package/dist/terminal-colors.js +161 -0
- package/dist/terminal-colors.js.map +1 -0
- package/dist/terminal-image.d.ts +85 -0
- package/dist/terminal-image.d.ts.map +1 -0
- package/dist/terminal-image.js +324 -0
- package/dist/terminal-image.js.map +1 -0
- package/dist/terminal.d.ts +113 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +486 -0
- package/dist/terminal.js.map +1 -0
- package/dist/tui.d.ts +310 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +1673 -0
- package/dist/tui.js.map +1 -0
- package/dist/undo-stack.d.ts +16 -0
- package/dist/undo-stack.d.ts.map +1 -0
- package/dist/undo-stack.js +26 -0
- package/dist/undo-stack.js.map +1 -0
- package/dist/utils.d.ts +98 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +1233 -0
- package/dist/utils.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { fuzzyFilter } from "../fuzzy.js";
|
|
2
|
+
import { getKeybindings } from "../keybindings.js";
|
|
3
|
+
import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils.js";
|
|
4
|
+
import { Input } from "./input.js";
|
|
5
|
+
export class SettingsList {
|
|
6
|
+
items;
|
|
7
|
+
filteredItems;
|
|
8
|
+
theme;
|
|
9
|
+
selectedIndex = 0;
|
|
10
|
+
maxVisible;
|
|
11
|
+
onChange;
|
|
12
|
+
onCancel;
|
|
13
|
+
searchInput;
|
|
14
|
+
searchEnabled;
|
|
15
|
+
submenuComponent = null;
|
|
16
|
+
submenuItemIndex = null;
|
|
17
|
+
constructor(items, maxVisible, theme, onChange, onCancel, options = {}) {
|
|
18
|
+
this.items = items;
|
|
19
|
+
this.filteredItems = items;
|
|
20
|
+
this.maxVisible = maxVisible;
|
|
21
|
+
this.theme = theme;
|
|
22
|
+
this.onChange = onChange;
|
|
23
|
+
this.onCancel = onCancel;
|
|
24
|
+
this.searchEnabled = options.enableSearch ?? false;
|
|
25
|
+
if (this.searchEnabled) {
|
|
26
|
+
this.searchInput = new Input();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
updateValue(id, newValue) {
|
|
30
|
+
const item = this.items.find((i) => i.id === id);
|
|
31
|
+
if (item) {
|
|
32
|
+
item.currentValue = newValue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
invalidate() {
|
|
36
|
+
this.submenuComponent?.invalidate?.();
|
|
37
|
+
}
|
|
38
|
+
render(width) {
|
|
39
|
+
if (this.submenuComponent) {
|
|
40
|
+
return this.submenuComponent.render(width);
|
|
41
|
+
}
|
|
42
|
+
return this.renderMainList(width);
|
|
43
|
+
}
|
|
44
|
+
renderMainList(width) {
|
|
45
|
+
const lines = [];
|
|
46
|
+
if (this.searchEnabled && this.searchInput) {
|
|
47
|
+
lines.push(...this.searchInput.render(width));
|
|
48
|
+
lines.push("");
|
|
49
|
+
}
|
|
50
|
+
if (this.items.length === 0) {
|
|
51
|
+
lines.push(this.theme.hint(" No settings available"));
|
|
52
|
+
if (this.searchEnabled) {
|
|
53
|
+
this.addHintLine(lines, width);
|
|
54
|
+
}
|
|
55
|
+
return lines;
|
|
56
|
+
}
|
|
57
|
+
const displayItems = this.searchEnabled ? this.filteredItems : this.items;
|
|
58
|
+
if (displayItems.length === 0) {
|
|
59
|
+
lines.push(truncateToWidth(this.theme.hint(" No matching settings"), width));
|
|
60
|
+
this.addHintLine(lines, width);
|
|
61
|
+
return lines;
|
|
62
|
+
}
|
|
63
|
+
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), displayItems.length - this.maxVisible));
|
|
64
|
+
const endIndex = Math.min(startIndex + this.maxVisible, displayItems.length);
|
|
65
|
+
const maxLabelWidth = Math.min(30, Math.max(...this.items.map((item) => visibleWidth(item.label))));
|
|
66
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
67
|
+
const item = displayItems[i];
|
|
68
|
+
if (!item)
|
|
69
|
+
continue;
|
|
70
|
+
const isSelected = i === this.selectedIndex;
|
|
71
|
+
const prefix = isSelected ? this.theme.cursor : " ";
|
|
72
|
+
const prefixWidth = visibleWidth(prefix);
|
|
73
|
+
const labelPadded = item.label + " ".repeat(Math.max(0, maxLabelWidth - visibleWidth(item.label)));
|
|
74
|
+
const labelText = this.theme.label(labelPadded, isSelected);
|
|
75
|
+
const separator = " ";
|
|
76
|
+
const usedWidth = prefixWidth + maxLabelWidth + visibleWidth(separator);
|
|
77
|
+
const valueMaxWidth = width - usedWidth - 2;
|
|
78
|
+
const valueText = this.theme.value(truncateToWidth(item.currentValue, valueMaxWidth, ""), isSelected);
|
|
79
|
+
lines.push(truncateToWidth(prefix + labelText + separator + valueText, width));
|
|
80
|
+
}
|
|
81
|
+
if (startIndex > 0 || endIndex < displayItems.length) {
|
|
82
|
+
const scrollText = ` (${this.selectedIndex + 1}/${displayItems.length})`;
|
|
83
|
+
lines.push(this.theme.hint(truncateToWidth(scrollText, width - 2, "")));
|
|
84
|
+
}
|
|
85
|
+
const selectedItem = displayItems[this.selectedIndex];
|
|
86
|
+
if (selectedItem?.description) {
|
|
87
|
+
lines.push("");
|
|
88
|
+
const wrappedDesc = wrapTextWithAnsi(selectedItem.description, width - 4);
|
|
89
|
+
for (const line of wrappedDesc) {
|
|
90
|
+
lines.push(this.theme.description(` ${line}`));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
this.addHintLine(lines, width);
|
|
94
|
+
return lines;
|
|
95
|
+
}
|
|
96
|
+
handleInput(data) {
|
|
97
|
+
// If submenu is active, delegate all input to it
|
|
98
|
+
// The submenu's onCancel (triggered by escape) will call done() which closes it
|
|
99
|
+
if (this.submenuComponent) {
|
|
100
|
+
this.submenuComponent.handleInput?.(data);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const kb = getKeybindings();
|
|
104
|
+
const displayItems = this.searchEnabled ? this.filteredItems : this.items;
|
|
105
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
106
|
+
if (displayItems.length === 0)
|
|
107
|
+
return;
|
|
108
|
+
this.selectedIndex = this.selectedIndex === 0 ? displayItems.length - 1 : this.selectedIndex - 1;
|
|
109
|
+
}
|
|
110
|
+
else if (kb.matches(data, "tui.select.down")) {
|
|
111
|
+
if (displayItems.length === 0)
|
|
112
|
+
return;
|
|
113
|
+
this.selectedIndex = this.selectedIndex === displayItems.length - 1 ? 0 : this.selectedIndex + 1;
|
|
114
|
+
}
|
|
115
|
+
else if (kb.matches(data, "tui.select.confirm") || data === " ") {
|
|
116
|
+
this.activateItem();
|
|
117
|
+
}
|
|
118
|
+
else if (kb.matches(data, "tui.select.cancel")) {
|
|
119
|
+
this.onCancel();
|
|
120
|
+
}
|
|
121
|
+
else if (this.searchEnabled && this.searchInput) {
|
|
122
|
+
const sanitized = data.replace(/ /g, "");
|
|
123
|
+
if (!sanitized) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.searchInput.handleInput(sanitized);
|
|
127
|
+
this.applyFilter(this.searchInput.getValue());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
activateItem() {
|
|
131
|
+
const item = this.searchEnabled ? this.filteredItems[this.selectedIndex] : this.items[this.selectedIndex];
|
|
132
|
+
if (!item)
|
|
133
|
+
return;
|
|
134
|
+
if (item.submenu) {
|
|
135
|
+
this.submenuItemIndex = this.selectedIndex;
|
|
136
|
+
this.submenuComponent = item.submenu(item.currentValue, (selectedValue) => {
|
|
137
|
+
if (selectedValue !== undefined) {
|
|
138
|
+
item.currentValue = selectedValue;
|
|
139
|
+
this.onChange(item.id, selectedValue);
|
|
140
|
+
}
|
|
141
|
+
this.closeSubmenu();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else if (item.values && item.values.length > 0) {
|
|
145
|
+
const currentIndex = item.values.indexOf(item.currentValue);
|
|
146
|
+
const nextIndex = (currentIndex + 1) % item.values.length;
|
|
147
|
+
const newValue = item.values[nextIndex];
|
|
148
|
+
item.currentValue = newValue;
|
|
149
|
+
this.onChange(item.id, newValue);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
closeSubmenu() {
|
|
153
|
+
this.submenuComponent = null;
|
|
154
|
+
if (this.submenuItemIndex !== null) {
|
|
155
|
+
this.selectedIndex = this.submenuItemIndex;
|
|
156
|
+
this.submenuItemIndex = null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
applyFilter(query) {
|
|
160
|
+
this.filteredItems = fuzzyFilter(this.items, query, (item) => item.label);
|
|
161
|
+
this.selectedIndex = 0;
|
|
162
|
+
}
|
|
163
|
+
addHintLine(lines, width) {
|
|
164
|
+
lines.push("");
|
|
165
|
+
lines.push(truncateToWidth(this.theme.hint(this.searchEnabled
|
|
166
|
+
? " Type to search · Enter/Space to change · Esc to cancel"
|
|
167
|
+
: " Enter/Space to change · Esc to cancel"), width));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=settings-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-list.js","sourceRoot":"","sources":["../../src/components/settings-list.ts"],"names":[],"mappings":"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","sourcesContent":["import { fuzzyFilter } from \"../fuzzy.js\";\nimport { getKeybindings } from \"../keybindings.js\";\nimport type { Component } from \"../tui.js\";\nimport { truncateToWidth, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\nimport { Input } from \"./input.js\";\n\nexport interface SettingItem {\n\t/** Unique identifier for this setting */\n\tid: string;\n\t/** Display label (left side) */\n\tlabel: string;\n\t/** Optional description shown when selected */\n\tdescription?: string;\n\t/** Current value to display (right side) */\n\tcurrentValue: string;\n\t/** If provided, Enter/Space cycles through these values */\n\tvalues?: string[];\n\t/** If provided, Enter opens this submenu. Receives current value and done callback. */\n\tsubmenu?: (currentValue: string, done: (selectedValue?: string) => void) => Component;\n}\n\nexport interface SettingsListTheme {\n\tlabel: (text: string, selected: boolean) => string;\n\tvalue: (text: string, selected: boolean) => string;\n\tdescription: (text: string) => string;\n\tcursor: string;\n\thint: (text: string) => string;\n}\n\nexport interface SettingsListOptions {\n\tenableSearch?: boolean;\n}\n\nexport class SettingsList implements Component {\n\tprivate items: SettingItem[];\n\tprivate filteredItems: SettingItem[];\n\tprivate theme: SettingsListTheme;\n\tprivate selectedIndex = 0;\n\tprivate maxVisible: number;\n\tprivate onChange: (id: string, newValue: string) => void;\n\tprivate onCancel: () => void;\n\tprivate searchInput?: Input;\n\tprivate searchEnabled: boolean;\n\n\tprivate submenuComponent: Component | null = null;\n\tprivate submenuItemIndex: number | null = null;\n\n\tconstructor(\n\t\titems: SettingItem[],\n\t\tmaxVisible: number,\n\t\ttheme: SettingsListTheme,\n\t\tonChange: (id: string, newValue: string) => void,\n\t\tonCancel: () => void,\n\t\toptions: SettingsListOptions = {},\n\t) {\n\t\tthis.items = items;\n\t\tthis.filteredItems = items;\n\t\tthis.maxVisible = maxVisible;\n\t\tthis.theme = theme;\n\t\tthis.onChange = onChange;\n\t\tthis.onCancel = onCancel;\n\t\tthis.searchEnabled = options.enableSearch ?? false;\n\t\tif (this.searchEnabled) {\n\t\t\tthis.searchInput = new Input();\n\t\t}\n\t}\n\n\tupdateValue(id: string, newValue: string): void {\n\t\tconst item = this.items.find((i) => i.id === id);\n\t\tif (item) {\n\t\t\titem.currentValue = newValue;\n\t\t}\n\t}\n\n\tinvalidate(): void {\n\t\tthis.submenuComponent?.invalidate?.();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.submenuComponent) {\n\t\t\treturn this.submenuComponent.render(width);\n\t\t}\n\n\t\treturn this.renderMainList(width);\n\t}\n\n\tprivate renderMainList(width: number): string[] {\n\t\tconst lines: string[] = [];\n\n\t\tif (this.searchEnabled && this.searchInput) {\n\t\t\tlines.push(...this.searchInput.render(width));\n\t\t\tlines.push(\"\");\n\t\t}\n\n\t\tif (this.items.length === 0) {\n\t\t\tlines.push(this.theme.hint(\" No settings available\"));\n\t\t\tif (this.searchEnabled) {\n\t\t\t\tthis.addHintLine(lines, width);\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tif (displayItems.length === 0) {\n\t\t\tlines.push(truncateToWidth(this.theme.hint(\" No matching settings\"), width));\n\t\t\tthis.addHintLine(lines, width);\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), displayItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, displayItems.length);\n\n\t\tconst maxLabelWidth = Math.min(30, Math.max(...this.items.map((item) => visibleWidth(item.label))));\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = displayItems[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst prefix = isSelected ? this.theme.cursor : \" \";\n\t\t\tconst prefixWidth = visibleWidth(prefix);\n\n\t\t\tconst labelPadded = item.label + \" \".repeat(Math.max(0, maxLabelWidth - visibleWidth(item.label)));\n\t\t\tconst labelText = this.theme.label(labelPadded, isSelected);\n\n\t\t\tconst separator = \" \";\n\t\t\tconst usedWidth = prefixWidth + maxLabelWidth + visibleWidth(separator);\n\t\t\tconst valueMaxWidth = width - usedWidth - 2;\n\n\t\t\tconst valueText = this.theme.value(truncateToWidth(item.currentValue, valueMaxWidth, \"\"), isSelected);\n\n\t\t\tlines.push(truncateToWidth(prefix + labelText + separator + valueText, width));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < displayItems.length) {\n\t\t\tconst scrollText = ` (${this.selectedIndex + 1}/${displayItems.length})`;\n\t\t\tlines.push(this.theme.hint(truncateToWidth(scrollText, width - 2, \"\")));\n\t\t}\n\n\t\tconst selectedItem = displayItems[this.selectedIndex];\n\t\tif (selectedItem?.description) {\n\t\t\tlines.push(\"\");\n\t\t\tconst wrappedDesc = wrapTextWithAnsi(selectedItem.description, width - 4);\n\t\t\tfor (const line of wrappedDesc) {\n\t\t\t\tlines.push(this.theme.description(` ${line}`));\n\t\t\t}\n\t\t}\n\n\t\tthis.addHintLine(lines, width);\n\n\t\treturn lines;\n\t}\n\n\thandleInput(data: string): void {\n\t\t// If submenu is active, delegate all input to it\n\t\t// The submenu's onCancel (triggered by escape) will call done() which closes it\n\t\tif (this.submenuComponent) {\n\t\t\tthis.submenuComponent.handleInput?.(data);\n\t\t\treturn;\n\t\t}\n\n\t\tconst kb = getKeybindings();\n\t\tconst displayItems = this.searchEnabled ? this.filteredItems : this.items;\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tif (displayItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? displayItems.length - 1 : this.selectedIndex - 1;\n\t\t} else if (kb.matches(data, \"tui.select.down\")) {\n\t\t\tif (displayItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === displayItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t} else if (kb.matches(data, \"tui.select.confirm\") || data === \" \") {\n\t\t\tthis.activateItem();\n\t\t} else if (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onCancel();\n\t\t} else if (this.searchEnabled && this.searchInput) {\n\t\t\tconst sanitized = data.replace(/ /g, \"\");\n\t\t\tif (!sanitized) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.searchInput.handleInput(sanitized);\n\t\t\tthis.applyFilter(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate activateItem(): void {\n\t\tconst item = this.searchEnabled ? this.filteredItems[this.selectedIndex] : this.items[this.selectedIndex];\n\t\tif (!item) return;\n\n\t\tif (item.submenu) {\n\t\t\tthis.submenuItemIndex = this.selectedIndex;\n\t\t\tthis.submenuComponent = item.submenu(item.currentValue, (selectedValue?: string) => {\n\t\t\t\tif (selectedValue !== undefined) {\n\t\t\t\t\titem.currentValue = selectedValue;\n\t\t\t\t\tthis.onChange(item.id, selectedValue);\n\t\t\t\t}\n\t\t\t\tthis.closeSubmenu();\n\t\t\t});\n\t\t} else if (item.values && item.values.length > 0) {\n\t\t\tconst currentIndex = item.values.indexOf(item.currentValue);\n\t\t\tconst nextIndex = (currentIndex + 1) % item.values.length;\n\t\t\tconst newValue = item.values[nextIndex];\n\t\t\titem.currentValue = newValue;\n\t\t\tthis.onChange(item.id, newValue);\n\t\t}\n\t}\n\n\tprivate closeSubmenu(): void {\n\t\tthis.submenuComponent = null;\n\t\tif (this.submenuItemIndex !== null) {\n\t\t\tthis.selectedIndex = this.submenuItemIndex;\n\t\t\tthis.submenuItemIndex = null;\n\t\t}\n\t}\n\n\tprivate applyFilter(query: string): void {\n\t\tthis.filteredItems = fuzzyFilter(this.items, query, (item) => item.label);\n\t\tthis.selectedIndex = 0;\n\t}\n\n\tprivate addHintLine(lines: string[], width: number): void {\n\t\tlines.push(\"\");\n\t\tlines.push(\n\t\t\ttruncateToWidth(\n\t\t\t\tthis.theme.hint(\n\t\t\t\t\tthis.searchEnabled\n\t\t\t\t\t\t? \" Type to search · Enter/Space to change · Esc to cancel\"\n\t\t\t\t\t\t: \" Enter/Space to change · Esc to cancel\",\n\t\t\t\t),\n\t\t\t\twidth,\n\t\t\t),\n\t\t);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Component } from "../tui.js";
|
|
2
|
+
/**
|
|
3
|
+
* Spacer component that renders empty lines
|
|
4
|
+
*/
|
|
5
|
+
export declare class Spacer implements Component {
|
|
6
|
+
private lines;
|
|
7
|
+
constructor(lines?: number);
|
|
8
|
+
setLines(lines: number): void;
|
|
9
|
+
invalidate(): void;
|
|
10
|
+
render(_width: number): string[];
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=spacer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spacer.d.ts","sourceRoot":"","sources":["../../src/components/spacer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C;;GAEG;AACH,qBAAa,MAAO,YAAW,SAAS;IACvC,OAAO,CAAC,KAAK,CAAS;IAEtB,YAAY,KAAK,GAAE,MAAU,EAE5B;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE5B;IAED,UAAU,IAAI,IAAI,CAAG;IAErB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAM/B;CACD","sourcesContent":["import type { Component } from \"../tui.js\";\n\n/**\n * Spacer component that renders empty lines\n */\nexport class Spacer implements Component {\n\tprivate lines: number;\n\n\tconstructor(lines: number = 1) {\n\t\tthis.lines = lines;\n\t}\n\n\tsetLines(lines: number): void {\n\t\tthis.lines = lines;\n\t}\n\n\tinvalidate(): void {}\n\n\trender(_width: number): string[] {\n\t\tconst result: string[] = [];\n\t\tfor (let i = 0; i < this.lines; i++) {\n\t\t\tresult.push(\"\");\n\t\t}\n\t\treturn result;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacer component that renders empty lines
|
|
3
|
+
*/
|
|
4
|
+
export class Spacer {
|
|
5
|
+
lines;
|
|
6
|
+
constructor(lines = 1) {
|
|
7
|
+
this.lines = lines;
|
|
8
|
+
}
|
|
9
|
+
setLines(lines) {
|
|
10
|
+
this.lines = lines;
|
|
11
|
+
}
|
|
12
|
+
invalidate() { }
|
|
13
|
+
render(_width) {
|
|
14
|
+
const result = [];
|
|
15
|
+
for (let i = 0; i < this.lines; i++) {
|
|
16
|
+
result.push("");
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=spacer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spacer.js","sourceRoot":"","sources":["../../src/components/spacer.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,MAAM;IACV,KAAK,CAAS;IAEtB,YAAY,KAAK,GAAW,CAAC,EAAE;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IAAA,CACnB;IAED,QAAQ,CAAC,KAAa,EAAQ;QAC7B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IAAA,CACnB;IAED,UAAU,GAAS,EAAC,CAAC;IAErB,MAAM,CAAC,MAAc,EAAY;QAChC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QACD,OAAO,MAAM,CAAC;IAAA,CACd;CACD","sourcesContent":["import type { Component } from \"../tui.js\";\n\n/**\n * Spacer component that renders empty lines\n */\nexport class Spacer implements Component {\n\tprivate lines: number;\n\n\tconstructor(lines: number = 1) {\n\t\tthis.lines = lines;\n\t}\n\n\tsetLines(lines: number): void {\n\t\tthis.lines = lines;\n\t}\n\n\tinvalidate(): void {}\n\n\trender(_width: number): string[] {\n\t\tconst result: string[] = [];\n\t\tfor (let i = 0; i < this.lines; i++) {\n\t\t\tresult.push(\"\");\n\t\t}\n\t\treturn result;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Component } from "../tui.js";
|
|
2
|
+
/**
|
|
3
|
+
* Text component - displays multi-line text with word wrapping
|
|
4
|
+
*/
|
|
5
|
+
export declare class Text implements Component {
|
|
6
|
+
private text;
|
|
7
|
+
private paddingX;
|
|
8
|
+
private paddingY;
|
|
9
|
+
private customBgFn?;
|
|
10
|
+
private cachedText?;
|
|
11
|
+
private cachedWidth?;
|
|
12
|
+
private cachedLines?;
|
|
13
|
+
constructor(text?: string, paddingX?: number, paddingY?: number, customBgFn?: (text: string) => string);
|
|
14
|
+
setText(text: string): void;
|
|
15
|
+
setCustomBgFn(customBgFn?: (text: string) => string): void;
|
|
16
|
+
invalidate(): void;
|
|
17
|
+
render(width: number): string[];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/components/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,IAAK,YAAW,SAAS;IACrC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAC,CAA2B;IAE9C,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;IAE/B,YAAY,IAAI,GAAE,MAAW,EAAE,QAAQ,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAK/G;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAK1B;IAED,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAKzD;IAED,UAAU,IAAI,IAAI,CAIjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAiD9B;CACD","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\n\n/**\n * Text component - displays multi-line text with word wrapping\n */\nexport class Text implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate customBgFn?: (text: string) => string;\n\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(text: string = \"\", paddingX: number = 1, paddingY: number = 1, customBgFn?: (text: string) => string) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.customBgFn = customBgFn;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetCustomBgFn(customBgFn?: (text: string) => string): void {\n\t\tthis.customBgFn = customBgFn;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\tconst wrappedLines = wrapTextWithAnsi(normalizedText, contentWidth);\n\n\t\tconst leftMargin = \" \".repeat(this.paddingX);\n\t\tconst rightMargin = \" \".repeat(this.paddingX);\n\t\tconst contentLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\tconst lineWithMargins = leftMargin + line + rightMargin;\n\n\t\t\tif (this.customBgFn) {\n\t\t\t\tcontentLines.push(applyBackgroundToLine(lineWithMargins, width, this.customBgFn));\n\t\t\t} else {\n\t\t\t\tconst visibleLen = visibleWidth(lineWithMargins);\n\t\t\t\tconst paddingNeeded = Math.max(0, width - visibleLen);\n\t\t\t\tcontentLines.push(lineWithMargins + \" \".repeat(paddingNeeded));\n\t\t\t}\n\t\t}\n\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst emptyLines: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst line = this.customBgFn ? applyBackgroundToLine(emptyLine, width, this.customBgFn) : emptyLine;\n\t\t\temptyLines.push(line);\n\t\t}\n\n\t\tconst result = [...emptyLines, ...contentLines, ...emptyLines];\n\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n}\n"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from "../utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* Text component - displays multi-line text with word wrapping
|
|
4
|
+
*/
|
|
5
|
+
export class Text {
|
|
6
|
+
text;
|
|
7
|
+
paddingX; // Left/right padding
|
|
8
|
+
paddingY; // Top/bottom padding
|
|
9
|
+
customBgFn;
|
|
10
|
+
cachedText;
|
|
11
|
+
cachedWidth;
|
|
12
|
+
cachedLines;
|
|
13
|
+
constructor(text = "", paddingX = 1, paddingY = 1, customBgFn) {
|
|
14
|
+
this.text = text;
|
|
15
|
+
this.paddingX = paddingX;
|
|
16
|
+
this.paddingY = paddingY;
|
|
17
|
+
this.customBgFn = customBgFn;
|
|
18
|
+
}
|
|
19
|
+
setText(text) {
|
|
20
|
+
this.text = text;
|
|
21
|
+
this.cachedText = undefined;
|
|
22
|
+
this.cachedWidth = undefined;
|
|
23
|
+
this.cachedLines = undefined;
|
|
24
|
+
}
|
|
25
|
+
setCustomBgFn(customBgFn) {
|
|
26
|
+
this.customBgFn = customBgFn;
|
|
27
|
+
this.cachedText = undefined;
|
|
28
|
+
this.cachedWidth = undefined;
|
|
29
|
+
this.cachedLines = undefined;
|
|
30
|
+
}
|
|
31
|
+
invalidate() {
|
|
32
|
+
this.cachedText = undefined;
|
|
33
|
+
this.cachedWidth = undefined;
|
|
34
|
+
this.cachedLines = undefined;
|
|
35
|
+
}
|
|
36
|
+
render(width) {
|
|
37
|
+
if (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {
|
|
38
|
+
return this.cachedLines;
|
|
39
|
+
}
|
|
40
|
+
if (!this.text || this.text.trim() === "") {
|
|
41
|
+
const result = [];
|
|
42
|
+
this.cachedText = this.text;
|
|
43
|
+
this.cachedWidth = width;
|
|
44
|
+
this.cachedLines = result;
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
const normalizedText = this.text.replace(/\t/g, " ");
|
|
48
|
+
const contentWidth = Math.max(1, width - this.paddingX * 2);
|
|
49
|
+
const wrappedLines = wrapTextWithAnsi(normalizedText, contentWidth);
|
|
50
|
+
const leftMargin = " ".repeat(this.paddingX);
|
|
51
|
+
const rightMargin = " ".repeat(this.paddingX);
|
|
52
|
+
const contentLines = [];
|
|
53
|
+
for (const line of wrappedLines) {
|
|
54
|
+
const lineWithMargins = leftMargin + line + rightMargin;
|
|
55
|
+
if (this.customBgFn) {
|
|
56
|
+
contentLines.push(applyBackgroundToLine(lineWithMargins, width, this.customBgFn));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const visibleLen = visibleWidth(lineWithMargins);
|
|
60
|
+
const paddingNeeded = Math.max(0, width - visibleLen);
|
|
61
|
+
contentLines.push(lineWithMargins + " ".repeat(paddingNeeded));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const emptyLine = " ".repeat(width);
|
|
65
|
+
const emptyLines = [];
|
|
66
|
+
for (let i = 0; i < this.paddingY; i++) {
|
|
67
|
+
const line = this.customBgFn ? applyBackgroundToLine(emptyLine, width, this.customBgFn) : emptyLine;
|
|
68
|
+
emptyLines.push(line);
|
|
69
|
+
}
|
|
70
|
+
const result = [...emptyLines, ...contentLines, ...emptyLines];
|
|
71
|
+
this.cachedText = this.text;
|
|
72
|
+
this.cachedWidth = width;
|
|
73
|
+
this.cachedLines = result;
|
|
74
|
+
return result.length > 0 ? result : [""];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/components/text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\n\n/**\n * Text component - displays multi-line text with word wrapping\n */\nexport class Text implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate customBgFn?: (text: string) => string;\n\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(text: string = \"\", paddingX: number = 1, paddingY: number = 1, customBgFn?: (text: string) => string) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.customBgFn = customBgFn;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetCustomBgFn(customBgFn?: (text: string) => string): void {\n\t\tthis.customBgFn = customBgFn;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\tconst wrappedLines = wrapTextWithAnsi(normalizedText, contentWidth);\n\n\t\tconst leftMargin = \" \".repeat(this.paddingX);\n\t\tconst rightMargin = \" \".repeat(this.paddingX);\n\t\tconst contentLines: string[] = [];\n\n\t\tfor (const line of wrappedLines) {\n\t\t\tconst lineWithMargins = leftMargin + line + rightMargin;\n\n\t\t\tif (this.customBgFn) {\n\t\t\t\tcontentLines.push(applyBackgroundToLine(lineWithMargins, width, this.customBgFn));\n\t\t\t} else {\n\t\t\t\tconst visibleLen = visibleWidth(lineWithMargins);\n\t\t\t\tconst paddingNeeded = Math.max(0, width - visibleLen);\n\t\t\t\tcontentLines.push(lineWithMargins + \" \".repeat(paddingNeeded));\n\t\t\t}\n\t\t}\n\n\t\tconst emptyLine = \" \".repeat(width);\n\t\tconst emptyLines: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst line = this.customBgFn ? applyBackgroundToLine(emptyLine, width, this.customBgFn) : emptyLine;\n\t\t\temptyLines.push(line);\n\t\t}\n\n\t\tconst result = [...emptyLines, ...contentLines, ...emptyLines];\n\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Component } from "../tui.js";
|
|
2
|
+
/**
|
|
3
|
+
* Text component that truncates to fit viewport width
|
|
4
|
+
*/
|
|
5
|
+
export declare class TruncatedText implements Component {
|
|
6
|
+
private text;
|
|
7
|
+
private paddingX;
|
|
8
|
+
private paddingY;
|
|
9
|
+
constructor(text: string, paddingX?: number, paddingY?: number);
|
|
10
|
+
setText(text: string): void;
|
|
11
|
+
invalidate(): void;
|
|
12
|
+
render(width: number): string[];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=truncated-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncated-text.d.ts","sourceRoot":"","sources":["../../src/components/truncated-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC9C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU,EAInE;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1B;IAED,UAAU,IAAI,IAAI,CAAG;IAErB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAkC9B;CACD","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { truncateToWidth, visibleWidth } from \"../utils.js\";\n\n/**\n * Text component that truncates to fit viewport width\n */\nexport class TruncatedText implements Component {\n\tprivate text: string;\n\tprivate paddingX: number;\n\tprivate paddingY: number;\n\n\tconstructor(text: string, paddingX: number = 0, paddingY: number = 0) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst result: string[] = [];\n\n\t\tconst emptyLine = \" \".repeat(width);\n\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(emptyLine);\n\t\t}\n\n\t\tconst availableWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\tlet singleLineText = this.text;\n\t\tconst newlineIndex = this.text.indexOf(\"\\n\");\n\t\tif (newlineIndex !== -1) {\n\t\t\tsingleLineText = this.text.substring(0, newlineIndex);\n\t\t}\n\n\t\tconst displayText = truncateToWidth(singleLineText, availableWidth);\n\n\t\tconst leftPadding = \" \".repeat(this.paddingX);\n\t\tconst rightPadding = \" \".repeat(this.paddingX);\n\t\tconst lineWithPadding = leftPadding + displayText + rightPadding;\n\n\t\tconst lineVisibleWidth = visibleWidth(lineWithPadding);\n\t\tconst paddingNeeded = Math.max(0, width - lineVisibleWidth);\n\t\tconst finalLine = lineWithPadding + \" \".repeat(paddingNeeded);\n\n\t\tresult.push(finalLine);\n\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(emptyLine);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth } from "../utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* Text component that truncates to fit viewport width
|
|
4
|
+
*/
|
|
5
|
+
export class TruncatedText {
|
|
6
|
+
text;
|
|
7
|
+
paddingX;
|
|
8
|
+
paddingY;
|
|
9
|
+
constructor(text, paddingX = 0, paddingY = 0) {
|
|
10
|
+
this.text = text;
|
|
11
|
+
this.paddingX = paddingX;
|
|
12
|
+
this.paddingY = paddingY;
|
|
13
|
+
}
|
|
14
|
+
setText(text) {
|
|
15
|
+
this.text = text;
|
|
16
|
+
}
|
|
17
|
+
invalidate() { }
|
|
18
|
+
render(width) {
|
|
19
|
+
const result = [];
|
|
20
|
+
const emptyLine = " ".repeat(width);
|
|
21
|
+
for (let i = 0; i < this.paddingY; i++) {
|
|
22
|
+
result.push(emptyLine);
|
|
23
|
+
}
|
|
24
|
+
const availableWidth = Math.max(1, width - this.paddingX * 2);
|
|
25
|
+
let singleLineText = this.text;
|
|
26
|
+
const newlineIndex = this.text.indexOf("\n");
|
|
27
|
+
if (newlineIndex !== -1) {
|
|
28
|
+
singleLineText = this.text.substring(0, newlineIndex);
|
|
29
|
+
}
|
|
30
|
+
const displayText = truncateToWidth(singleLineText, availableWidth);
|
|
31
|
+
const leftPadding = " ".repeat(this.paddingX);
|
|
32
|
+
const rightPadding = " ".repeat(this.paddingX);
|
|
33
|
+
const lineWithPadding = leftPadding + displayText + rightPadding;
|
|
34
|
+
const lineVisibleWidth = visibleWidth(lineWithPadding);
|
|
35
|
+
const paddingNeeded = Math.max(0, width - lineVisibleWidth);
|
|
36
|
+
const finalLine = lineWithPadding + " ".repeat(paddingNeeded);
|
|
37
|
+
result.push(finalLine);
|
|
38
|
+
for (let i = 0; i < this.paddingY; i++) {
|
|
39
|
+
result.push(emptyLine);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=truncated-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncated-text.js","sourceRoot":"","sources":["../../src/components/truncated-text.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5D;;GAEG;AACH,MAAM,OAAO,aAAa;IACjB,IAAI,CAAS;IACb,QAAQ,CAAS;IACjB,QAAQ,CAAS;IAEzB,YAAY,IAAY,EAAE,QAAQ,GAAW,CAAC,EAAE,QAAQ,GAAW,CAAC,EAAE;QACrE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAAA,CACzB;IAED,OAAO,CAAC,IAAY,EAAQ;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAAA,CACjB;IAED,UAAU,GAAS,EAAC,CAAC;IAErB,MAAM,CAAC,KAAa,EAAY;QAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAE9D,IAAI,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;YACzB,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,WAAW,GAAG,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QAEpE,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CAAC;QAEjE,MAAM,gBAAgB,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAE9D,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,MAAM,CAAC;IAAA,CACd;CACD","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { truncateToWidth, visibleWidth } from \"../utils.js\";\n\n/**\n * Text component that truncates to fit viewport width\n */\nexport class TruncatedText implements Component {\n\tprivate text: string;\n\tprivate paddingX: number;\n\tprivate paddingY: number;\n\n\tconstructor(text: string, paddingX: number = 0, paddingY: number = 0) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t}\n\n\tinvalidate(): void {}\n\n\trender(width: number): string[] {\n\t\tconst result: string[] = [];\n\n\t\tconst emptyLine = \" \".repeat(width);\n\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(emptyLine);\n\t\t}\n\n\t\tconst availableWidth = Math.max(1, width - this.paddingX * 2);\n\n\t\tlet singleLineText = this.text;\n\t\tconst newlineIndex = this.text.indexOf(\"\\n\");\n\t\tif (newlineIndex !== -1) {\n\t\t\tsingleLineText = this.text.substring(0, newlineIndex);\n\t\t}\n\n\t\tconst displayText = truncateToWidth(singleLineText, availableWidth);\n\n\t\tconst leftPadding = \" \".repeat(this.paddingX);\n\t\tconst rightPadding = \" \".repeat(this.paddingX);\n\t\tconst lineWithPadding = leftPadding + displayText + rightPadding;\n\n\t\tconst lineVisibleWidth = visibleWidth(lineWithPadding);\n\t\tconst paddingNeeded = Math.max(0, width - lineVisibleWidth);\n\t\tconst finalLine = lineWithPadding + \" \".repeat(paddingNeeded);\n\n\t\tresult.push(finalLine);\n\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(emptyLine);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AutocompleteProvider } from "./autocomplete.js";
|
|
2
|
+
import type { Component } from "./tui.js";
|
|
3
|
+
export interface EditorPasteSnapshot {
|
|
4
|
+
pastes: readonly (readonly [number, string])[];
|
|
5
|
+
pasteCounter: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Interface for custom editor components.
|
|
9
|
+
*
|
|
10
|
+
* This allows extensions to provide their own editor implementation
|
|
11
|
+
* (e.g., vim mode, emacs mode, custom keybindings) while maintaining
|
|
12
|
+
* compatibility with the core application.
|
|
13
|
+
*/
|
|
14
|
+
export interface EditorComponent extends Component {
|
|
15
|
+
/** Get the current text content */
|
|
16
|
+
getText(): string;
|
|
17
|
+
/** Set the text content */
|
|
18
|
+
setText(text: string): void;
|
|
19
|
+
/** Handle raw terminal input (key presses, paste sequences, etc.) */
|
|
20
|
+
handleInput(data: string): void;
|
|
21
|
+
/** Called when user submits (e.g., Enter key) */
|
|
22
|
+
onSubmit?: (text: string) => void;
|
|
23
|
+
/** Called when text changes */
|
|
24
|
+
onChange?: (text: string) => void;
|
|
25
|
+
/** Add text to history for up/down navigation */
|
|
26
|
+
addToHistory?(text: string): void;
|
|
27
|
+
/** Prompt history entries available for up/down navigation (most recent first). */
|
|
28
|
+
getHistory?(): readonly string[];
|
|
29
|
+
/** Clear prompt history (e.g. when switching to a different session). */
|
|
30
|
+
clearHistory?(): void;
|
|
31
|
+
/** Insert text at current cursor position */
|
|
32
|
+
insertTextAtCursor?(text: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get text with any markers expanded (e.g., paste markers).
|
|
35
|
+
* Falls back to getText() if not implemented.
|
|
36
|
+
*/
|
|
37
|
+
getExpandedText?(): string;
|
|
38
|
+
getPasteSnapshot?(): EditorPasteSnapshot;
|
|
39
|
+
restorePasteSnapshot?(snapshot: EditorPasteSnapshot): void;
|
|
40
|
+
/** Set the autocomplete provider */
|
|
41
|
+
setAutocompleteProvider?(provider: AutocompleteProvider): void;
|
|
42
|
+
/** Border color function */
|
|
43
|
+
borderColor?: (str: string) => string;
|
|
44
|
+
/** Background color function */
|
|
45
|
+
backgroundColor?: (str: string) => string;
|
|
46
|
+
/** Set horizontal padding */
|
|
47
|
+
setPaddingX?(padding: number): void;
|
|
48
|
+
/** Set max visible items in autocomplete dropdown */
|
|
49
|
+
setAutocompleteMaxVisible?(maxVisible: number): void;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=editor-component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-component.d.ts","sourceRoot":"","sources":["../src/editor-component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAC/C,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,SAAS;IACjD,mCAAmC;IACnC,OAAO,IAAI,MAAM,CAAC;IAElB,2BAA2B;IAC3B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,qEAAqE;IACrE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAElC,iDAAiD;IACjD,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC,mFAAmF;IACnF,UAAU,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC;IAEjC,yEAAyE;IACzE,YAAY,CAAC,IAAI,IAAI,CAAC;IAEtB,6CAA6C;IAC7C,kBAAkB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC;;;OAGG;IACH,eAAe,CAAC,IAAI,MAAM,CAAC;IAE3B,gBAAgB,CAAC,IAAI,mBAAmB,CAAC;IAEzC,oBAAoB,CAAC,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAE3D,oCAAoC;IACpC,uBAAuB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAE/D,4BAA4B;IAC5B,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAEtC,gCAAgC;IAChC,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAE1C,6BAA6B;IAC7B,WAAW,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,qDAAqD;IACrD,yBAAyB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACrD","sourcesContent":["import type { AutocompleteProvider } from \"./autocomplete.js\";\nimport type { Component } from \"./tui.js\";\n\nexport interface EditorPasteSnapshot {\n\tpastes: readonly (readonly [number, string])[];\n\tpasteCounter: number;\n}\n\n/**\n * Interface for custom editor components.\n *\n * This allows extensions to provide their own editor implementation\n * (e.g., vim mode, emacs mode, custom keybindings) while maintaining\n * compatibility with the core application.\n */\nexport interface EditorComponent extends Component {\n\t/** Get the current text content */\n\tgetText(): string;\n\n\t/** Set the text content */\n\tsetText(text: string): void;\n\n\t/** Handle raw terminal input (key presses, paste sequences, etc.) */\n\thandleInput(data: string): void;\n\n\t/** Called when user submits (e.g., Enter key) */\n\tonSubmit?: (text: string) => void;\n\n\t/** Called when text changes */\n\tonChange?: (text: string) => void;\n\n\t/** Add text to history for up/down navigation */\n\taddToHistory?(text: string): void;\n\n\t/** Prompt history entries available for up/down navigation (most recent first). */\n\tgetHistory?(): readonly string[];\n\n\t/** Clear prompt history (e.g. when switching to a different session). */\n\tclearHistory?(): void;\n\n\t/** Insert text at current cursor position */\n\tinsertTextAtCursor?(text: string): void;\n\n\t/**\n\t * Get text with any markers expanded (e.g., paste markers).\n\t * Falls back to getText() if not implemented.\n\t */\n\tgetExpandedText?(): string;\n\n\tgetPasteSnapshot?(): EditorPasteSnapshot;\n\n\trestorePasteSnapshot?(snapshot: EditorPasteSnapshot): void;\n\n\t/** Set the autocomplete provider */\n\tsetAutocompleteProvider?(provider: AutocompleteProvider): void;\n\n\t/** Border color function */\n\tborderColor?: (str: string) => string;\n\n\t/** Background color function */\n\tbackgroundColor?: (str: string) => string;\n\n\t/** Set horizontal padding */\n\tsetPaddingX?(padding: number): void;\n\n\t/** Set max visible items in autocomplete dropdown */\n\tsetAutocompleteMaxVisible?(maxVisible: number): void;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-component.js","sourceRoot":"","sources":["../src/editor-component.ts"],"names":[],"mappings":"","sourcesContent":["import type { AutocompleteProvider } from \"./autocomplete.js\";\nimport type { Component } from \"./tui.js\";\n\nexport interface EditorPasteSnapshot {\n\tpastes: readonly (readonly [number, string])[];\n\tpasteCounter: number;\n}\n\n/**\n * Interface for custom editor components.\n *\n * This allows extensions to provide their own editor implementation\n * (e.g., vim mode, emacs mode, custom keybindings) while maintaining\n * compatibility with the core application.\n */\nexport interface EditorComponent extends Component {\n\t/** Get the current text content */\n\tgetText(): string;\n\n\t/** Set the text content */\n\tsetText(text: string): void;\n\n\t/** Handle raw terminal input (key presses, paste sequences, etc.) */\n\thandleInput(data: string): void;\n\n\t/** Called when user submits (e.g., Enter key) */\n\tonSubmit?: (text: string) => void;\n\n\t/** Called when text changes */\n\tonChange?: (text: string) => void;\n\n\t/** Add text to history for up/down navigation */\n\taddToHistory?(text: string): void;\n\n\t/** Prompt history entries available for up/down navigation (most recent first). */\n\tgetHistory?(): readonly string[];\n\n\t/** Clear prompt history (e.g. when switching to a different session). */\n\tclearHistory?(): void;\n\n\t/** Insert text at current cursor position */\n\tinsertTextAtCursor?(text: string): void;\n\n\t/**\n\t * Get text with any markers expanded (e.g., paste markers).\n\t * Falls back to getText() if not implemented.\n\t */\n\tgetExpandedText?(): string;\n\n\tgetPasteSnapshot?(): EditorPasteSnapshot;\n\n\trestorePasteSnapshot?(snapshot: EditorPasteSnapshot): void;\n\n\t/** Set the autocomplete provider */\n\tsetAutocompleteProvider?(provider: AutocompleteProvider): void;\n\n\t/** Border color function */\n\tborderColor?: (str: string) => string;\n\n\t/** Background color function */\n\tbackgroundColor?: (str: string) => string;\n\n\t/** Set horizontal padding */\n\tsetPaddingX?(padding: number): void;\n\n\t/** Set max visible items in autocomplete dropdown */\n\tsetAutocompleteMaxVisible?(maxVisible: number): void;\n}\n"]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fullscreen (alternate-screen) viewport: a scrollable window over the
|
|
3
|
+
* transcript with a dock (editor/footer) pinned to the bottom rows. Frames
|
|
4
|
+
* are a fixed grid painted with absolute addressing and diffed row-by-row;
|
|
5
|
+
* scroll position is application state, not terminal scrollback.
|
|
6
|
+
*/
|
|
7
|
+
import type { TableCellSelectionRegion } from "./selection-metadata.js";
|
|
8
|
+
export declare const FULLSCREEN_MIN_TRANSCRIPT_ROWS = 3;
|
|
9
|
+
export declare function clippedFullscreenDockHeight(dockLength: number, height: number): number;
|
|
10
|
+
export interface ScrollInfo {
|
|
11
|
+
following: boolean;
|
|
12
|
+
linesBelow: number;
|
|
13
|
+
linesAbove: number;
|
|
14
|
+
}
|
|
15
|
+
export type SelectionScrollDirection = -1 | 1;
|
|
16
|
+
interface FrameSelectionRegion {
|
|
17
|
+
line: number;
|
|
18
|
+
col: number;
|
|
19
|
+
width: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class FullscreenViewport {
|
|
22
|
+
private scrollTop;
|
|
23
|
+
private following;
|
|
24
|
+
private prevFrame;
|
|
25
|
+
private prevWidth;
|
|
26
|
+
private prevHeight;
|
|
27
|
+
private lastMaxScroll;
|
|
28
|
+
private lastWindowHeight;
|
|
29
|
+
private lastTranscript;
|
|
30
|
+
private lastFrame;
|
|
31
|
+
private lastFrameVisibleStart;
|
|
32
|
+
private lastFrameVisibleHeight;
|
|
33
|
+
private frameSelectionRegions;
|
|
34
|
+
private tableCellSelectionRegions;
|
|
35
|
+
private activeFrameSelection;
|
|
36
|
+
private activeTableSelection;
|
|
37
|
+
private selectionAnchor;
|
|
38
|
+
private selectionHead;
|
|
39
|
+
private selectionMode;
|
|
40
|
+
/**
|
|
41
|
+
* Compose a frame of exactly `height` lines: scrolled transcript window on
|
|
42
|
+
* top, dock pinned to the bottom. Following pins the window to the
|
|
43
|
+
* transcript end; otherwise it stays frozen while content appends.
|
|
44
|
+
*/
|
|
45
|
+
composeFrame(transcript: string[], dock: string[], height: number, tableCellSelectionRegions?: ReadonlyArray<TableCellSelectionRegion>): string[];
|
|
46
|
+
private orderedSelection;
|
|
47
|
+
private selectionSpan;
|
|
48
|
+
private highlightSelection;
|
|
49
|
+
/** Begin a selection at a screen position; false when outside the transcript window. */
|
|
50
|
+
beginSelection(screenRow: number, screenCol: number): boolean;
|
|
51
|
+
extendSelection(screenRow: number, screenCol: number): void;
|
|
52
|
+
selectionAutoScrollDirection(screenRow: number): SelectionScrollDirection | null;
|
|
53
|
+
scrollSelection(direction: SelectionScrollDirection, screenCol: number): boolean;
|
|
54
|
+
/** Finish the selection and return its plain text (null when empty). */
|
|
55
|
+
endSelection(): string | null;
|
|
56
|
+
extendActiveSelection(screenRow: number, screenCol: number): void;
|
|
57
|
+
endActiveSelection(): string | null;
|
|
58
|
+
/** Snapshot and highlight the final screen frame for overlay/dock selection. */
|
|
59
|
+
applyFrameSelection(frame: string[], height: number, selectableRegions: ReadonlyArray<FrameSelectionRegion>): void;
|
|
60
|
+
beginFrameSelection(screenRow: number, screenCol: number): boolean;
|
|
61
|
+
extendFrameSelection(screenRow: number, screenCol: number): void;
|
|
62
|
+
endFrameSelection(): string | null;
|
|
63
|
+
private highlightLine;
|
|
64
|
+
private framePoint;
|
|
65
|
+
private transcriptScreenBounds;
|
|
66
|
+
private transcriptLineForScreenRow;
|
|
67
|
+
private isFrameSelectable;
|
|
68
|
+
private tableRegions;
|
|
69
|
+
private tableAtPoint;
|
|
70
|
+
private closestTableCell;
|
|
71
|
+
private activeTableRange;
|
|
72
|
+
private selectedTableSpans;
|
|
73
|
+
private frameRegionsForLine;
|
|
74
|
+
private clampFrameSelectionPoint;
|
|
75
|
+
private selectedFrameSpans;
|
|
76
|
+
private extractFrameSelectionText;
|
|
77
|
+
private extractSelectionText;
|
|
78
|
+
private compareSelectionPoints;
|
|
79
|
+
private extractTableSelectionText;
|
|
80
|
+
clearSelection(): void;
|
|
81
|
+
hasSelection(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* OSC 8 hyperlink URL at a screen position in the last painted frame, or
|
|
84
|
+
* null when the position is not over a hyperlink. Covers the transcript
|
|
85
|
+
* window, the dock, and composited overlays.
|
|
86
|
+
*/
|
|
87
|
+
hyperlinkAt(screenRow: number, screenCol: number): string | null;
|
|
88
|
+
/** Row-diff a composed frame against the previous one with absolute addressing. */
|
|
89
|
+
paint(write: (data: string) => void, frame: string[], width: number, height: number, cursorPos: {
|
|
90
|
+
row: number;
|
|
91
|
+
col: number;
|
|
92
|
+
} | null): void;
|
|
93
|
+
/** Force the next paint to clear and repaint the whole screen. */
|
|
94
|
+
reset(): void;
|
|
95
|
+
/** Scrolling up pauses following; reaching the bottom resumes it. */
|
|
96
|
+
scrollBy(delta: number): void;
|
|
97
|
+
scrollToTop(): void;
|
|
98
|
+
scrollToBottom(): void;
|
|
99
|
+
pageSize(): number;
|
|
100
|
+
windowHeight(): number;
|
|
101
|
+
isFollowing(): boolean;
|
|
102
|
+
scrollInfo(): ScrollInfo;
|
|
103
|
+
}
|
|
104
|
+
export {};
|
|
105
|
+
//# sourceMappingURL=fullscreen.d.ts.map
|