@dungle-scrubs/tallow 0.9.3 → 0.9.6
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/dist/cli.js +7 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/interactive-mode-patch.d.ts +24 -10
- package/dist/interactive-mode-patch.d.ts.map +1 -1
- package/dist/interactive-mode-patch.js +285 -148
- package/dist/interactive-mode-patch.js.map +1 -1
- package/dist/interactive-reset.d.ts +49 -0
- package/dist/interactive-reset.d.ts.map +1 -0
- package/dist/interactive-reset.js +40 -0
- package/dist/interactive-reset.js.map +1 -0
- package/dist/pi-tui-editor-patch.d.ts +10 -0
- package/dist/pi-tui-editor-patch.d.ts.map +1 -0
- package/dist/pi-tui-editor-patch.js +159 -0
- package/dist/pi-tui-editor-patch.js.map +1 -0
- package/dist/pi-tui-patch.d.ts +2 -0
- package/dist/pi-tui-patch.d.ts.map +1 -0
- package/dist/pi-tui-patch.js +563 -0
- package/dist/pi-tui-patch.js.map +1 -0
- package/dist/pi-tui-settings-list-patch.d.ts +11 -0
- package/dist/pi-tui-settings-list-patch.d.ts.map +1 -0
- package/dist/pi-tui-settings-list-patch.js +38 -0
- package/dist/pi-tui-settings-list-patch.js.map +1 -0
- package/dist/reset-diagnostics.d.ts +69 -0
- package/dist/reset-diagnostics.d.ts.map +1 -0
- package/dist/reset-diagnostics.js +41 -0
- package/dist/reset-diagnostics.js.map +1 -0
- package/dist/sdk.d.ts +5 -21
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +180 -149
- package/dist/sdk.js.map +1 -1
- package/dist/workspace-transition-interactive.d.ts +1 -0
- package/dist/workspace-transition-interactive.d.ts.map +1 -1
- package/dist/workspace-transition-interactive.js +7 -17
- package/dist/workspace-transition-interactive.js.map +1 -1
- package/extensions/__integration__/audit-findings.test.ts +6 -16
- package/extensions/__integration__/teams-runtime.test.ts +4 -1
- package/extensions/_icons/index.ts +2 -4
- package/extensions/_shared/__tests__/image-metadata.test.ts +33 -0
- package/extensions/_shared/__tests__/terminal-links.test.ts +18 -0
- package/extensions/_shared/image-metadata.ts +99 -0
- package/extensions/_shared/inline-preview.ts +1 -1
- package/extensions/_shared/pid-registry.ts +0 -1
- package/extensions/_shared/terminal-links.ts +22 -0
- package/extensions/ask-user-question-tool/index.ts +0 -3
- package/extensions/clear/__tests__/clear.test.ts +270 -3
- package/extensions/command-expansion/index.ts +1 -1
- package/extensions/context-files/index.ts +5 -1
- package/extensions/context-fork/__tests__/context-fork.test.ts +94 -1
- package/extensions/context-fork/extension.json +1 -1
- package/extensions/context-fork/index.ts +32 -0
- package/extensions/edit-tool-enhanced/index.ts +2 -1
- package/extensions/hooks/index.ts +33 -11
- package/extensions/loop/index.ts +14 -1
- package/extensions/lsp/index.ts +64 -13
- package/extensions/lsp/package.json +2 -2
- package/extensions/permissions/__tests__/permissions.test.ts +4 -4
- package/extensions/random-spinner/index.ts +7 -642
- package/extensions/read-tool-enhanced/index.ts +6 -8
- package/extensions/render-stabilizer/__tests__/render-stabilizer.test.ts +4 -5
- package/extensions/render-stabilizer/index.ts +6 -6
- package/extensions/show-system-prompt/__tests__/show-system-prompt.test.ts +1 -1
- package/extensions/slash-command-bridge/__tests__/slash-command-bridge.test.ts +26 -0
- package/extensions/slash-command-bridge/index.ts +14 -2
- package/extensions/subagent-tool/index.ts +1 -1
- package/extensions/subagent-tool/model-resolver.ts +274 -7
- package/extensions/tasks/__tests__/state-ui.test.ts +3 -3
- package/extensions/tasks/__tests__/widget-subagents.test.ts +2 -2
- package/extensions/tasks/commands/register-tasks-extension.ts +10 -10
- package/extensions/tasks/state/index.ts +1 -1
- package/extensions/tasks/ui/index.ts +2 -7
- package/extensions/teams-tool/tools/register-extension.ts +1 -3
- package/extensions/web-search-tool/index.ts +2 -1
- package/extensions/write-tool-enhanced/__tests__/write-tool-enhanced.test.ts +21 -6
- package/extensions/write-tool-enhanced/index.ts +2 -1
- package/node_modules/@mariozechner/pi-tui/README.md +56 -34
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts +18 -13
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js +182 -113
- package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js +3 -3
- package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts +45 -36
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.js +489 -325
- package/node_modules/@mariozechner/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts +1 -99
- package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/image.js +17 -192
- package/node_modules/@mariozechner/pi-tui/dist/components/image.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/input.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/input.js +57 -60
- package/node_modules/@mariozechner/pi-tui/dist/components/input.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts +2 -69
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.js +5 -102
- package/node_modules/@mariozechner/pi-tui/dist/components/loader.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js +111 -53
- package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts +19 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js +78 -67
- package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts +0 -2
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js +12 -23
- package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/index.d.ts +8 -10
- package/node_modules/@mariozechner/pi-tui/dist/index.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/index.js +6 -9
- package/node_modules/@mariozechner/pi-tui/dist/index.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts +108 -238
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.js +108 -365
- package/node_modules/@mariozechner/pi-tui/dist/keybindings.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts +33 -48
- package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/keys.js +239 -155
- package/node_modules/@mariozechner/pi-tui/dist/keys.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts +14 -94
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js +44 -186
- package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts +13 -58
- package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/terminal.js +78 -111
- package/node_modules/@mariozechner/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts +24 -110
- package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/tui.js +188 -435
- package/node_modules/@mariozechner/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts +0 -18
- package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts.map +1 -1
- package/node_modules/@mariozechner/pi-tui/dist/utils.js +251 -119
- package/node_modules/@mariozechner/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@mariozechner/pi-tui/package.json +6 -6
- package/node_modules/@mariozechner/pi-tui/src/__tests__/__snapshots__/render.test.ts.snap +3 -40
- package/node_modules/@mariozechner/pi-tui/src/__tests__/image-component.test.ts +71 -81
- package/node_modules/@mariozechner/pi-tui/src/__tests__/render.test.ts +0 -33
- package/node_modules/@mariozechner/pi-tui/src/__tests__/terminal-image.test.ts +93 -334
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-render-scheduling.test.ts +1 -1
- package/node_modules/@mariozechner/pi-tui/src/__tests__/utils.test.ts +11 -196
- package/node_modules/@mariozechner/pi-tui/src/autocomplete.ts +228 -142
- package/node_modules/@mariozechner/pi-tui/src/components/cancellable-loader.ts +3 -3
- package/node_modules/@mariozechner/pi-tui/src/components/editor.ts +624 -390
- package/node_modules/@mariozechner/pi-tui/src/components/image.ts +17 -227
- package/node_modules/@mariozechner/pi-tui/src/components/input.ts +71 -63
- package/node_modules/@mariozechner/pi-tui/src/components/loader.ts +5 -137
- package/node_modules/@mariozechner/pi-tui/src/components/markdown.ts +143 -52
- package/node_modules/@mariozechner/pi-tui/src/components/select-list.ts +136 -70
- package/node_modules/@mariozechner/pi-tui/src/components/settings-list.ts +11 -23
- package/node_modules/@mariozechner/pi-tui/src/index.ts +17 -36
- package/node_modules/@mariozechner/pi-tui/src/keybindings.ts +148 -421
- package/node_modules/@mariozechner/pi-tui/src/keys.ts +253 -181
- package/node_modules/@mariozechner/pi-tui/src/terminal-image.ts +51 -252
- package/node_modules/@mariozechner/pi-tui/src/terminal.ts +78 -133
- package/node_modules/@mariozechner/pi-tui/src/tui.ts +202 -478
- package/node_modules/@mariozechner/pi-tui/src/utils.ts +289 -125
- package/node_modules/@mariozechner/pi-tui/tsconfig.build.json +1 -0
- package/package.json +13 -13
- package/packages/tallow-tui/node_modules/@types/mime-types/README.md +8 -2
- package/packages/tallow-tui/node_modules/@types/mime-types/index.d.ts +6 -0
- package/packages/tallow-tui/node_modules/@types/mime-types/package.json +9 -3
- package/packages/tallow-tui/node_modules/get-east-asian-width/lookup-data.js +18 -0
- package/packages/tallow-tui/node_modules/get-east-asian-width/lookup.js +116 -384
- package/packages/tallow-tui/node_modules/get-east-asian-width/package.json +5 -4
- package/packages/tallow-tui/node_modules/get-east-asian-width/utilities.js +24 -0
- package/packages/tallow-tui/node_modules/marked/README.md +5 -4
- package/packages/tallow-tui/node_modules/marked/bin/main.js +10 -8
- package/packages/tallow-tui/node_modules/marked/bin/marked.js +2 -1
- package/packages/tallow-tui/node_modules/marked/lib/marked.d.ts +156 -125
- package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js +67 -2179
- package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js.map +3 -3
- package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js +67 -2201
- package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js.map +3 -3
- package/packages/tallow-tui/node_modules/marked/man/marked.1 +4 -2
- package/packages/tallow-tui/node_modules/marked/man/marked.1.md +2 -1
- package/packages/tallow-tui/node_modules/marked/package.json +26 -34
- package/runtime/model-metadata-overrides.ts +10 -1
- package/runtime/pid-schema.ts +26 -6
- package/skills/tallow-expert/SKILL.md +1 -3
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts +0 -32
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.js +0 -46
- package/node_modules/@mariozechner/pi-tui/dist/border-styles.js.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts +0 -52
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js +0 -89
- package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts +0 -14
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts.map +0 -1
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js +0 -55
- package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js.map +0 -1
- package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-change-listener.test.ts +0 -121
- package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-ghost-text.test.ts +0 -112
- package/node_modules/@mariozechner/pi-tui/src/__tests__/mouse-events.test.ts +0 -134
- package/node_modules/@mariozechner/pi-tui/src/__tests__/settings-list.test.ts +0 -49
- package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-diff-regression.test.ts +0 -555
- package/node_modules/@mariozechner/pi-tui/src/border-styles.ts +0 -60
- package/node_modules/@mariozechner/pi-tui/src/components/bordered-box.ts +0 -113
- package/node_modules/@mariozechner/pi-tui/src/test-utils/capability-env.ts +0 -56
- package/packages/tallow-tui/node_modules/marked/lib/marked.cjs +0 -2211
- package/packages/tallow-tui/node_modules/marked/lib/marked.cjs.map +0 -7
- package/packages/tallow-tui/node_modules/marked/lib/marked.d.cts +0 -728
- package/packages/tallow-tui/node_modules/marked/marked.min.js +0 -69
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getKeybindings } from "../keybindings.js";
|
|
2
2
|
import type { Component } from "../tui.js";
|
|
3
|
-
import { truncateToWidth } from "../utils.js";
|
|
3
|
+
import { truncateToWidth, visibleWidth } from "../utils.js";
|
|
4
|
+
|
|
5
|
+
const DEFAULT_PRIMARY_COLUMN_WIDTH = 32;
|
|
6
|
+
const PRIMARY_COLUMN_GAP = 2;
|
|
7
|
+
const MIN_DESCRIPTION_WIDTH = 10;
|
|
4
8
|
|
|
5
9
|
const normalizeToSingleLine = (text: string): string => text.replace(/[\r\n]+/g, " ").trim();
|
|
10
|
+
const clamp = (value: number, min: number, max: number): number =>
|
|
11
|
+
Math.max(min, Math.min(value, max));
|
|
6
12
|
|
|
7
13
|
export interface SelectItem {
|
|
8
14
|
value: string;
|
|
@@ -18,22 +24,43 @@ export interface SelectListTheme {
|
|
|
18
24
|
noMatch: (text: string) => string;
|
|
19
25
|
}
|
|
20
26
|
|
|
27
|
+
export interface SelectListTruncatePrimaryContext {
|
|
28
|
+
text: string;
|
|
29
|
+
maxWidth: number;
|
|
30
|
+
columnWidth: number;
|
|
31
|
+
item: SelectItem;
|
|
32
|
+
isSelected: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SelectListLayoutOptions {
|
|
36
|
+
minPrimaryColumnWidth?: number;
|
|
37
|
+
maxPrimaryColumnWidth?: number;
|
|
38
|
+
truncatePrimary?: (context: SelectListTruncatePrimaryContext) => string;
|
|
39
|
+
}
|
|
40
|
+
|
|
21
41
|
export class SelectList implements Component {
|
|
22
42
|
private items: SelectItem[] = [];
|
|
23
43
|
private filteredItems: SelectItem[] = [];
|
|
24
44
|
private selectedIndex: number = 0;
|
|
25
45
|
private maxVisible: number = 5;
|
|
26
46
|
private theme: SelectListTheme;
|
|
47
|
+
private layout: SelectListLayoutOptions;
|
|
27
48
|
|
|
28
49
|
public onSelect?: (item: SelectItem) => void;
|
|
29
50
|
public onCancel?: () => void;
|
|
30
51
|
public onSelectionChange?: (item: SelectItem) => void;
|
|
31
52
|
|
|
32
|
-
constructor(
|
|
53
|
+
constructor(
|
|
54
|
+
items: SelectItem[],
|
|
55
|
+
maxVisible: number,
|
|
56
|
+
theme: SelectListTheme,
|
|
57
|
+
layout: SelectListLayoutOptions = {}
|
|
58
|
+
) {
|
|
33
59
|
this.items = items;
|
|
34
60
|
this.filteredItems = items;
|
|
35
61
|
this.maxVisible = maxVisible;
|
|
36
62
|
this.theme = theme;
|
|
63
|
+
this.layout = layout;
|
|
37
64
|
}
|
|
38
65
|
|
|
39
66
|
setFilter(filter: string): void {
|
|
@@ -61,6 +88,8 @@ export class SelectList implements Component {
|
|
|
61
88
|
return lines;
|
|
62
89
|
}
|
|
63
90
|
|
|
91
|
+
const primaryColumnWidth = this.getPrimaryColumnWidth();
|
|
92
|
+
|
|
64
93
|
// Calculate visible range with scrolling
|
|
65
94
|
const startIndex = Math.max(
|
|
66
95
|
0,
|
|
@@ -80,68 +109,9 @@ export class SelectList implements Component {
|
|
|
80
109
|
const descriptionSingleLine = item.description
|
|
81
110
|
? normalizeToSingleLine(item.description)
|
|
82
111
|
: undefined;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// Use arrow indicator for selection - entire line uses selectedText color
|
|
87
|
-
const prefixWidth = 2; // "↗ " is 2 characters visually
|
|
88
|
-
const displayValue = item.label || item.value;
|
|
89
|
-
|
|
90
|
-
if (descriptionSingleLine && width > 40) {
|
|
91
|
-
// Calculate how much space we have for value + description
|
|
92
|
-
const maxValueWidth = Math.min(30, width - prefixWidth - 4);
|
|
93
|
-
const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
|
|
94
|
-
const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
|
|
95
|
-
|
|
96
|
-
// Calculate remaining space for description using visible widths
|
|
97
|
-
const descriptionStart = prefixWidth + truncatedValue.length + spacing.length;
|
|
98
|
-
const remainingWidth = width - descriptionStart - 2; // -2 for safety
|
|
99
|
-
|
|
100
|
-
if (remainingWidth > 10) {
|
|
101
|
-
const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
|
|
102
|
-
// Apply selectedText to entire line content
|
|
103
|
-
line = this.theme.selectedText(`↗ ${truncatedValue}${spacing}${truncatedDesc}`);
|
|
104
|
-
} else {
|
|
105
|
-
// Not enough space for description
|
|
106
|
-
const maxWidth = width - prefixWidth - 2;
|
|
107
|
-
line = this.theme.selectedText(`↗ ${truncateToWidth(displayValue, maxWidth, "")}`);
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
// No description or not enough width
|
|
111
|
-
const maxWidth = width - prefixWidth - 2;
|
|
112
|
-
line = this.theme.selectedText(`↗ ${truncateToWidth(displayValue, maxWidth, "")}`);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
const displayValue = item.label || item.value;
|
|
116
|
-
const prefix = " ";
|
|
117
|
-
|
|
118
|
-
if (descriptionSingleLine && width > 40) {
|
|
119
|
-
// Calculate how much space we have for value + description
|
|
120
|
-
const maxValueWidth = Math.min(30, width - prefix.length - 4);
|
|
121
|
-
const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
|
|
122
|
-
const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
|
|
123
|
-
|
|
124
|
-
// Calculate remaining space for description
|
|
125
|
-
const descriptionStart = prefix.length + truncatedValue.length + spacing.length;
|
|
126
|
-
const remainingWidth = width - descriptionStart - 2; // -2 for safety
|
|
127
|
-
|
|
128
|
-
if (remainingWidth > 10) {
|
|
129
|
-
const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
|
|
130
|
-
const descText = this.theme.description(spacing + truncatedDesc);
|
|
131
|
-
line = prefix + truncatedValue + descText;
|
|
132
|
-
} else {
|
|
133
|
-
// Not enough space for description
|
|
134
|
-
const maxWidth = width - prefix.length - 2;
|
|
135
|
-
line = prefix + truncateToWidth(displayValue, maxWidth, "");
|
|
136
|
-
}
|
|
137
|
-
} else {
|
|
138
|
-
// No description or not enough width
|
|
139
|
-
const maxWidth = width - prefix.length - 2;
|
|
140
|
-
line = prefix + truncateToWidth(displayValue, maxWidth, "");
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
lines.push(line);
|
|
112
|
+
lines.push(
|
|
113
|
+
this.renderItem(item, isSelected, width, descriptionSingleLine, primaryColumnWidth)
|
|
114
|
+
);
|
|
145
115
|
}
|
|
146
116
|
|
|
147
117
|
// Add scroll indicators if needed
|
|
@@ -155,34 +125,130 @@ export class SelectList implements Component {
|
|
|
155
125
|
}
|
|
156
126
|
|
|
157
127
|
handleInput(keyData: string): void {
|
|
158
|
-
const kb =
|
|
128
|
+
const kb = getKeybindings();
|
|
159
129
|
// Up arrow - wrap to bottom when at top
|
|
160
|
-
if (kb.matches(keyData, "
|
|
130
|
+
if (kb.matches(keyData, "tui.select.up")) {
|
|
161
131
|
this.selectedIndex =
|
|
162
132
|
this.selectedIndex === 0 ? this.filteredItems.length - 1 : this.selectedIndex - 1;
|
|
163
133
|
this.notifySelectionChange();
|
|
164
134
|
}
|
|
165
135
|
// Down arrow - wrap to top when at bottom
|
|
166
|
-
else if (kb.matches(keyData, "
|
|
136
|
+
else if (kb.matches(keyData, "tui.select.down")) {
|
|
167
137
|
this.selectedIndex =
|
|
168
138
|
this.selectedIndex === this.filteredItems.length - 1 ? 0 : this.selectedIndex + 1;
|
|
169
139
|
this.notifySelectionChange();
|
|
170
140
|
}
|
|
171
141
|
// Enter
|
|
172
|
-
else if (kb.matches(keyData, "
|
|
142
|
+
else if (kb.matches(keyData, "tui.select.confirm")) {
|
|
173
143
|
const selectedItem = this.filteredItems[this.selectedIndex];
|
|
174
144
|
if (selectedItem && this.onSelect) {
|
|
175
145
|
this.onSelect(selectedItem);
|
|
176
146
|
}
|
|
177
147
|
}
|
|
178
148
|
// Escape or Ctrl+C
|
|
179
|
-
else if (kb.matches(keyData, "
|
|
149
|
+
else if (kb.matches(keyData, "tui.select.cancel")) {
|
|
180
150
|
if (this.onCancel) {
|
|
181
151
|
this.onCancel();
|
|
182
152
|
}
|
|
183
153
|
}
|
|
184
154
|
}
|
|
185
155
|
|
|
156
|
+
private renderItem(
|
|
157
|
+
item: SelectItem,
|
|
158
|
+
isSelected: boolean,
|
|
159
|
+
width: number,
|
|
160
|
+
descriptionSingleLine: string | undefined,
|
|
161
|
+
primaryColumnWidth: number
|
|
162
|
+
): string {
|
|
163
|
+
const prefix = isSelected ? "→ " : " ";
|
|
164
|
+
const prefixWidth = visibleWidth(prefix);
|
|
165
|
+
|
|
166
|
+
if (descriptionSingleLine && width > 40) {
|
|
167
|
+
const effectivePrimaryColumnWidth = Math.max(
|
|
168
|
+
1,
|
|
169
|
+
Math.min(primaryColumnWidth, width - prefixWidth - 4)
|
|
170
|
+
);
|
|
171
|
+
const maxPrimaryWidth = Math.max(1, effectivePrimaryColumnWidth - PRIMARY_COLUMN_GAP);
|
|
172
|
+
const truncatedValue = this.truncatePrimary(
|
|
173
|
+
item,
|
|
174
|
+
isSelected,
|
|
175
|
+
maxPrimaryWidth,
|
|
176
|
+
effectivePrimaryColumnWidth
|
|
177
|
+
);
|
|
178
|
+
const truncatedValueWidth = visibleWidth(truncatedValue);
|
|
179
|
+
const spacing = " ".repeat(Math.max(1, effectivePrimaryColumnWidth - truncatedValueWidth));
|
|
180
|
+
const descriptionStart = prefixWidth + truncatedValueWidth + spacing.length;
|
|
181
|
+
const remainingWidth = width - descriptionStart - 2; // -2 for safety
|
|
182
|
+
|
|
183
|
+
if (remainingWidth > MIN_DESCRIPTION_WIDTH) {
|
|
184
|
+
const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
|
|
185
|
+
if (isSelected) {
|
|
186
|
+
return this.theme.selectedText(`${prefix}${truncatedValue}${spacing}${truncatedDesc}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const descText = this.theme.description(spacing + truncatedDesc);
|
|
190
|
+
return prefix + truncatedValue + descText;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const maxWidth = width - prefixWidth - 2;
|
|
195
|
+
const truncatedValue = this.truncatePrimary(item, isSelected, maxWidth, maxWidth);
|
|
196
|
+
if (isSelected) {
|
|
197
|
+
return this.theme.selectedText(`${prefix}${truncatedValue}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return prefix + truncatedValue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private getPrimaryColumnWidth(): number {
|
|
204
|
+
const { min, max } = this.getPrimaryColumnBounds();
|
|
205
|
+
const widestPrimary = this.filteredItems.reduce((widest, item) => {
|
|
206
|
+
return Math.max(widest, visibleWidth(this.getDisplayValue(item)) + PRIMARY_COLUMN_GAP);
|
|
207
|
+
}, 0);
|
|
208
|
+
|
|
209
|
+
return clamp(widestPrimary, min, max);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private getPrimaryColumnBounds(): { min: number; max: number } {
|
|
213
|
+
const rawMin =
|
|
214
|
+
this.layout.minPrimaryColumnWidth ??
|
|
215
|
+
this.layout.maxPrimaryColumnWidth ??
|
|
216
|
+
DEFAULT_PRIMARY_COLUMN_WIDTH;
|
|
217
|
+
const rawMax =
|
|
218
|
+
this.layout.maxPrimaryColumnWidth ??
|
|
219
|
+
this.layout.minPrimaryColumnWidth ??
|
|
220
|
+
DEFAULT_PRIMARY_COLUMN_WIDTH;
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
min: Math.max(1, Math.min(rawMin, rawMax)),
|
|
224
|
+
max: Math.max(1, Math.max(rawMin, rawMax)),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private truncatePrimary(
|
|
229
|
+
item: SelectItem,
|
|
230
|
+
isSelected: boolean,
|
|
231
|
+
maxWidth: number,
|
|
232
|
+
columnWidth: number
|
|
233
|
+
): string {
|
|
234
|
+
const displayValue = this.getDisplayValue(item);
|
|
235
|
+
const truncatedValue = this.layout.truncatePrimary
|
|
236
|
+
? this.layout.truncatePrimary({
|
|
237
|
+
text: displayValue,
|
|
238
|
+
maxWidth,
|
|
239
|
+
columnWidth,
|
|
240
|
+
item,
|
|
241
|
+
isSelected,
|
|
242
|
+
})
|
|
243
|
+
: truncateToWidth(displayValue, maxWidth, "");
|
|
244
|
+
|
|
245
|
+
return truncateToWidth(truncatedValue, maxWidth, "");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private getDisplayValue(item: SelectItem): string {
|
|
249
|
+
return item.label || item.value;
|
|
250
|
+
}
|
|
251
|
+
|
|
186
252
|
private notifySelectionChange(): void {
|
|
187
253
|
const selectedItem = this.filteredItems[this.selectedIndex];
|
|
188
254
|
if (selectedItem && this.onSelectionChange) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fuzzyFilter } from "../fuzzy.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getKeybindings } from "../keybindings.js";
|
|
3
3
|
import type { Component } from "../tui.js";
|
|
4
4
|
import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils.js";
|
|
5
5
|
import { Input } from "./input.js";
|
|
@@ -45,8 +45,6 @@ export class SettingsList implements Component {
|
|
|
45
45
|
// Submenu state
|
|
46
46
|
private submenuComponent: Component | null = null;
|
|
47
47
|
private submenuItemIndex: number | null = null;
|
|
48
|
-
private lastRenderLineCount = 0;
|
|
49
|
-
private nextMinLineCount = 0;
|
|
50
48
|
|
|
51
49
|
constructor(
|
|
52
50
|
items: SettingItem[],
|
|
@@ -81,17 +79,12 @@ export class SettingsList implements Component {
|
|
|
81
79
|
}
|
|
82
80
|
|
|
83
81
|
render(width: number): string[] {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (this.nextMinLineCount > lines.length) {
|
|
89
|
-
lines.push(...Array.from({ length: this.nextMinLineCount - lines.length }, () => ""));
|
|
82
|
+
// If submenu is active, render it instead
|
|
83
|
+
if (this.submenuComponent) {
|
|
84
|
+
return this.submenuComponent.render(width);
|
|
90
85
|
}
|
|
91
86
|
|
|
92
|
-
this.
|
|
93
|
-
this.lastRenderLineCount = lines.length;
|
|
94
|
-
return lines;
|
|
87
|
+
return this.renderMainList(width);
|
|
95
88
|
}
|
|
96
89
|
|
|
97
90
|
private renderMainList(width: number): string[] {
|
|
@@ -191,19 +184,19 @@ export class SettingsList implements Component {
|
|
|
191
184
|
}
|
|
192
185
|
|
|
193
186
|
// Main list input handling
|
|
194
|
-
const kb =
|
|
187
|
+
const kb = getKeybindings();
|
|
195
188
|
const displayItems = this.searchEnabled ? this.filteredItems : this.items;
|
|
196
|
-
if (kb.matches(data, "
|
|
189
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
197
190
|
if (displayItems.length === 0) return;
|
|
198
191
|
this.selectedIndex =
|
|
199
192
|
this.selectedIndex === 0 ? displayItems.length - 1 : this.selectedIndex - 1;
|
|
200
|
-
} else if (kb.matches(data, "
|
|
193
|
+
} else if (kb.matches(data, "tui.select.down")) {
|
|
201
194
|
if (displayItems.length === 0) return;
|
|
202
195
|
this.selectedIndex =
|
|
203
196
|
this.selectedIndex === displayItems.length - 1 ? 0 : this.selectedIndex + 1;
|
|
204
|
-
} else if (kb.matches(data, "
|
|
197
|
+
} else if (kb.matches(data, "tui.select.confirm") || data === " ") {
|
|
205
198
|
this.activateItem();
|
|
206
|
-
} else if (kb.matches(data, "
|
|
199
|
+
} else if (kb.matches(data, "tui.select.cancel")) {
|
|
207
200
|
this.onCancel();
|
|
208
201
|
} else if (this.searchEnabled && this.searchInput) {
|
|
209
202
|
const sanitized = data.replace(/ /g, "");
|
|
@@ -222,9 +215,7 @@ export class SettingsList implements Component {
|
|
|
222
215
|
if (!item) return;
|
|
223
216
|
|
|
224
217
|
if (item.submenu) {
|
|
225
|
-
//
|
|
226
|
-
// the editor→submenu swap as a destructive shrink/expand transition.
|
|
227
|
-
this.nextMinLineCount = this.lastRenderLineCount;
|
|
218
|
+
// Open submenu, passing current value so it can pre-select correctly
|
|
228
219
|
this.submenuItemIndex = this.selectedIndex;
|
|
229
220
|
this.submenuComponent = item.submenu(item.currentValue, (selectedValue?: string) => {
|
|
230
221
|
if (selectedValue !== undefined) {
|
|
@@ -244,9 +235,6 @@ export class SettingsList implements Component {
|
|
|
244
235
|
}
|
|
245
236
|
|
|
246
237
|
private closeSubmenu(): void {
|
|
247
|
-
// Preserve one frame of the submenu height so the transition back to the
|
|
248
|
-
// main settings list doesn't trigger a screen-clearing shrink redraw.
|
|
249
|
-
this.nextMinLineCount = this.lastRenderLineCount;
|
|
250
238
|
this.submenuComponent = null;
|
|
251
239
|
// Restore selection to the item that opened the submenu
|
|
252
240
|
if (this.submenuItemIndex !== null) {
|
|
@@ -4,33 +4,25 @@
|
|
|
4
4
|
export {
|
|
5
5
|
type AutocompleteItem,
|
|
6
6
|
type AutocompleteProvider,
|
|
7
|
+
type AutocompleteSuggestions,
|
|
7
8
|
CombinedAutocompleteProvider,
|
|
8
9
|
type SlashCommand,
|
|
9
10
|
} from "./autocomplete.js";
|
|
10
|
-
// Border styles
|
|
11
|
-
export {
|
|
12
|
-
type BorderStyle,
|
|
13
|
-
defaultBorderStyle,
|
|
14
|
-
FLAT,
|
|
15
|
-
ROUNDED,
|
|
16
|
-
SHARP,
|
|
17
|
-
setDefaultBorderStyle,
|
|
18
|
-
} from "./border-styles.js";
|
|
19
11
|
// Components
|
|
20
|
-
export { BorderedBox, type BorderedBoxOptions } from "./components/bordered-box.js";
|
|
21
12
|
export { Box } from "./components/box.js";
|
|
22
13
|
export { CancellableLoader } from "./components/cancellable-loader.js";
|
|
23
14
|
export { Editor, type EditorOptions, type EditorTheme } from "./components/editor.js";
|
|
24
|
-
export {
|
|
25
|
-
Image,
|
|
26
|
-
type ImageOptions,
|
|
27
|
-
type ImageTheme,
|
|
28
|
-
setNextImageFilePath,
|
|
29
|
-
} from "./components/image.js";
|
|
15
|
+
export { Image, type ImageOptions, type ImageTheme } from "./components/image.js";
|
|
30
16
|
export { Input } from "./components/input.js";
|
|
31
|
-
export { Loader
|
|
17
|
+
export { Loader } from "./components/loader.js";
|
|
32
18
|
export { type DefaultTextStyle, Markdown, type MarkdownTheme } from "./components/markdown.js";
|
|
33
|
-
export {
|
|
19
|
+
export {
|
|
20
|
+
type SelectItem,
|
|
21
|
+
SelectList,
|
|
22
|
+
type SelectListLayoutOptions,
|
|
23
|
+
type SelectListTheme,
|
|
24
|
+
type SelectListTruncatePrimaryContext,
|
|
25
|
+
} from "./components/select-list.js";
|
|
34
26
|
export {
|
|
35
27
|
type SettingItem,
|
|
36
28
|
SettingsList,
|
|
@@ -45,34 +37,28 @@ export type { EditorComponent } from "./editor-component.js";
|
|
|
45
37
|
export { type FuzzyMatch, fuzzyFilter, fuzzyMatch } from "./fuzzy.js";
|
|
46
38
|
// Keybindings
|
|
47
39
|
export {
|
|
48
|
-
DEFAULT_EDITOR_KEYBINDINGS,
|
|
49
|
-
type EditorAction,
|
|
50
|
-
type EditorKeybindingsConfig,
|
|
51
|
-
EditorKeybindingsManager,
|
|
52
|
-
getEditorKeybindings,
|
|
53
40
|
getKeybindings,
|
|
54
41
|
type Keybinding,
|
|
42
|
+
type KeybindingConflict,
|
|
55
43
|
type KeybindingDefinition,
|
|
44
|
+
type KeybindingDefinitions,
|
|
56
45
|
type Keybindings,
|
|
57
46
|
type KeybindingsConfig,
|
|
58
47
|
KeybindingsManager,
|
|
59
|
-
setEditorKeybindings,
|
|
60
48
|
setKeybindings,
|
|
61
49
|
TUI_KEYBINDINGS,
|
|
62
50
|
} from "./keybindings.js";
|
|
63
51
|
// Keyboard input handling
|
|
64
52
|
export {
|
|
53
|
+
decodeKittyPrintable,
|
|
65
54
|
isKeyRelease,
|
|
66
55
|
isKeyRepeat,
|
|
67
56
|
isKittyProtocolActive,
|
|
68
|
-
isMouseEvent,
|
|
69
57
|
Key,
|
|
70
58
|
type KeyEventType,
|
|
71
59
|
type KeyId,
|
|
72
|
-
type MouseEvent,
|
|
73
60
|
matchesKey,
|
|
74
61
|
parseKey,
|
|
75
|
-
parseMouseEvent,
|
|
76
62
|
setKittyProtocolActive,
|
|
77
63
|
} from "./keys.js";
|
|
78
64
|
// Input buffering for batch splitting
|
|
@@ -83,15 +69,12 @@ export { ProcessTerminal, type Terminal } from "./terminal.js";
|
|
|
83
69
|
export {
|
|
84
70
|
allocateImageId,
|
|
85
71
|
type CellDimensions,
|
|
86
|
-
|
|
87
|
-
createImageMetadata,
|
|
72
|
+
calculateImageRows,
|
|
88
73
|
deleteAllKittyImages,
|
|
89
74
|
deleteKittyImage,
|
|
90
75
|
detectCapabilities,
|
|
91
|
-
detectImageFormat,
|
|
92
76
|
encodeITerm2,
|
|
93
77
|
encodeKitty,
|
|
94
|
-
formatImageDimensions,
|
|
95
78
|
getCapabilities,
|
|
96
79
|
getCellDimensions,
|
|
97
80
|
getGifDimensions,
|
|
@@ -99,16 +82,14 @@ export {
|
|
|
99
82
|
getJpegDimensions,
|
|
100
83
|
getPngDimensions,
|
|
101
84
|
getWebpDimensions,
|
|
85
|
+
hyperlink,
|
|
102
86
|
type ImageDimensions,
|
|
103
|
-
type ImageFormat,
|
|
104
|
-
type ImageLayout,
|
|
105
|
-
type ImageMetadata,
|
|
106
87
|
type ImageProtocol,
|
|
107
88
|
type ImageRenderOptions,
|
|
108
89
|
imageFallback,
|
|
109
|
-
imageFormatToMime,
|
|
110
90
|
renderImage,
|
|
111
91
|
resetCapabilitiesCache,
|
|
92
|
+
setCapabilities,
|
|
112
93
|
setCellDimensions,
|
|
113
94
|
type TerminalCapabilities,
|
|
114
95
|
} from "./terminal-image.js";
|
|
@@ -126,4 +107,4 @@ export {
|
|
|
126
107
|
TUI,
|
|
127
108
|
} from "./tui.js";
|
|
128
109
|
// Utilities
|
|
129
|
-
export {
|
|
110
|
+
export { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "./utils.js";
|