@morndream/mihomo-tui 0.5.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -0
- package/LICENSE +21 -0
- package/README.md +462 -0
- package/bin/mihomo-tui +34 -0
- package/dist/App.js +161 -0
- package/dist/App.js.map +1 -0
- package/dist/api/client.js +239 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/status.js +43 -0
- package/dist/api/status.js.map +1 -0
- package/dist/api/stream.js +139 -0
- package/dist/api/stream.js.map +1 -0
- package/dist/api/types.js +6 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli.js +221 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/conn.js +122 -0
- package/dist/commands/conn.js.map +1 -0
- package/dist/commands/logs.js +99 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/output.js +177 -0
- package/dist/commands/output.js.map +1 -0
- package/dist/commands/provider.js +140 -0
- package/dist/commands/provider.js.map +1 -0
- package/dist/commands/proxy.js +161 -0
- package/dist/commands/proxy.js.map +1 -0
- package/dist/commands/proxyEnv.js +193 -0
- package/dist/commands/proxyEnv.js.map +1 -0
- package/dist/commands/rules.js +87 -0
- package/dist/commands/rules.js.map +1 -0
- package/dist/commands/status.js +75 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/components/ConfirmDialog.js +31 -0
- package/dist/components/ConfirmDialog.js.map +1 -0
- package/dist/components/DelayBadge.js +27 -0
- package/dist/components/DelayBadge.js.map +1 -0
- package/dist/components/InputDialog.js +325 -0
- package/dist/components/InputDialog.js.map +1 -0
- package/dist/components/ListDialog.js +86 -0
- package/dist/components/ListDialog.js.map +1 -0
- package/dist/components/ProgressDialog.js +34 -0
- package/dist/components/ProgressDialog.js.map +1 -0
- package/dist/components/ScrollList.js +26 -0
- package/dist/components/ScrollList.js.map +1 -0
- package/dist/components/StatusBar.js +58 -0
- package/dist/components/StatusBar.js.map +1 -0
- package/dist/components/TextEditor.js +112 -0
- package/dist/components/TextEditor.js.map +1 -0
- package/dist/components/textEditorModel.js +154 -0
- package/dist/components/textEditorModel.js.map +1 -0
- package/dist/config/manager.js +296 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/preserveGroups.js +9 -0
- package/dist/config/preserveGroups.js.map +1 -0
- package/dist/config/ruleDocument.js +88 -0
- package/dist/config/ruleDocument.js.map +1 -0
- package/dist/config/ruleService.js +256 -0
- package/dist/config/ruleService.js.map +1 -0
- package/dist/config/ruleValidation.js +98 -0
- package/dist/config/ruleValidation.js.map +1 -0
- package/dist/config/service.js +63 -0
- package/dist/config/service.js.map +1 -0
- package/dist/config/settingsService.js +162 -0
- package/dist/config/settingsService.js.map +1 -0
- package/dist/config/skeleton.js +324 -0
- package/dist/config/skeleton.js.map +1 -0
- package/dist/config/subscriptionService.js +284 -0
- package/dist/config/subscriptionService.js.map +1 -0
- package/dist/config/subscriptions.js +200 -0
- package/dist/config/subscriptions.js.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config.js +101 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks/useProviders.js +138 -0
- package/dist/hooks/useProviders.js.map +1 -0
- package/dist/hooks/useProxies.js +298 -0
- package/dist/hooks/useProxies.js.map +1 -0
- package/dist/hooks/useStream.js +127 -0
- package/dist/hooks/useStream.js.map +1 -0
- package/dist/kernel/installer.js +317 -0
- package/dist/kernel/installer.js.map +1 -0
- package/dist/kernel/releases.js +111 -0
- package/dist/kernel/releases.js.map +1 -0
- package/dist/kernel/sources.js +98 -0
- package/dist/kernel/sources.js.map +1 -0
- package/dist/rules/editor.js +181 -0
- package/dist/rules/editor.js.map +1 -0
- package/dist/rules/matcher.js +83 -0
- package/dist/rules/matcher.js.map +1 -0
- package/dist/rules/model.js +25 -0
- package/dist/rules/model.js.map +1 -0
- package/dist/rules/runtime.js +46 -0
- package/dist/rules/runtime.js.map +1 -0
- package/dist/rules/types.js +10 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/ui/FooterLine.js +62 -0
- package/dist/ui/FooterLine.js.map +1 -0
- package/dist/ui/Panel.js +47 -0
- package/dist/ui/Panel.js.map +1 -0
- package/dist/ui/RowIndicator.js +25 -0
- package/dist/ui/RowIndicator.js.map +1 -0
- package/dist/ui/SectionHeader.js +14 -0
- package/dist/ui/SectionHeader.js.map +1 -0
- package/dist/ui/StatusDot.js +15 -0
- package/dist/ui/StatusDot.js.map +1 -0
- package/dist/ui/TopBar.js +81 -0
- package/dist/ui/TopBar.js.map +1 -0
- package/dist/ui/exitGuard.js +20 -0
- package/dist/ui/exitGuard.js.map +1 -0
- package/dist/ui/keyCapture.js +28 -0
- package/dist/ui/keyCapture.js.map +1 -0
- package/dist/ui/layout.js +32 -0
- package/dist/ui/layout.js.map +1 -0
- package/dist/ui/rowIndicator.js +42 -0
- package/dist/ui/rowIndicator.js.map +1 -0
- package/dist/ui/tableHeader.js +33 -0
- package/dist/ui/tableHeader.js.map +1 -0
- package/dist/ui/theme.js +47 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/tone.js +131 -0
- package/dist/ui/tone.js.map +1 -0
- package/dist/version.js +27 -0
- package/dist/version.js.map +1 -0
- package/dist/views/Conns.js +107 -0
- package/dist/views/Conns.js.map +1 -0
- package/dist/views/Logs.js +89 -0
- package/dist/views/Logs.js.map +1 -0
- package/dist/views/Providers.js +392 -0
- package/dist/views/Providers.js.map +1 -0
- package/dist/views/Proxies.js +233 -0
- package/dist/views/Proxies.js.map +1 -0
- package/dist/views/RuleEditor.js +356 -0
- package/dist/views/RuleEditor.js.map +1 -0
- package/dist/views/Rules.js +286 -0
- package/dist/views/Rules.js.map +1 -0
- package/dist/views/Settings.js +734 -0
- package/dist/views/Settings.js.map +1 -0
- package/dist/views/groupDisplay.js +53 -0
- package/dist/views/groupDisplay.js.map +1 -0
- package/dist/views/subscriptionFields.js +59 -0
- package/dist/views/subscriptionFields.js.map +1 -0
- package/dist/views/yamlFile.js +32 -0
- package/dist/views/yamlFile.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* proxy_tui status —— 内核版本、模式、端口、provider 概览。
|
|
3
|
+
* 检查点 1 的验证目标:能连上 19090 并打印 v1.19.24。
|
|
4
|
+
*/
|
|
5
|
+
import { MihomoClient } from '../api/client.js';
|
|
6
|
+
import { formatRelativeTime, printJson, renderTable } from './output.js';
|
|
7
|
+
/** /providers/proxies 会把代理组也列为 vehicleType=Compatible 的伪 provider,需剔除 */
|
|
8
|
+
export function realProviders(providers) {
|
|
9
|
+
return Object.entries(providers).filter(([, provider]) => provider.vehicleType === 'HTTP' || provider.vehicleType === 'File');
|
|
10
|
+
}
|
|
11
|
+
export function countAlive(proxies) {
|
|
12
|
+
return proxies.filter((proxy) => proxy.alive && proxy.history.length > 0).length;
|
|
13
|
+
}
|
|
14
|
+
export function isGroup(proxy) {
|
|
15
|
+
return Array.isArray(proxy.all);
|
|
16
|
+
}
|
|
17
|
+
export async function runStatus(config, options) {
|
|
18
|
+
const client = new MihomoClient(config);
|
|
19
|
+
const [version, configs, proxies, providers] = await Promise.all([
|
|
20
|
+
client.version(),
|
|
21
|
+
client.configs(),
|
|
22
|
+
client.proxies(),
|
|
23
|
+
client.providers(),
|
|
24
|
+
]);
|
|
25
|
+
const groups = Object.values(proxies).filter(isGroup);
|
|
26
|
+
const nodes = Object.values(proxies).filter((proxy) => !isGroup(proxy));
|
|
27
|
+
const subs = realProviders(providers);
|
|
28
|
+
if (options.json) {
|
|
29
|
+
printJson({
|
|
30
|
+
api: client.api,
|
|
31
|
+
version,
|
|
32
|
+
mode: configs.mode,
|
|
33
|
+
logLevel: configs['log-level'],
|
|
34
|
+
mixedPort: configs['mixed-port'],
|
|
35
|
+
allowLan: configs['allow-lan'],
|
|
36
|
+
bindAddress: configs['bind-address'],
|
|
37
|
+
groups: groups.length,
|
|
38
|
+
nodes: nodes.length,
|
|
39
|
+
providers: subs.map(([name, provider]) => ({
|
|
40
|
+
name,
|
|
41
|
+
type: provider.vehicleType,
|
|
42
|
+
nodes: provider.proxies.length,
|
|
43
|
+
alive: countAlive(provider.proxies),
|
|
44
|
+
updatedAt: provider.updatedAt ?? null,
|
|
45
|
+
})),
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const lines = [
|
|
50
|
+
renderTable(['项目', '值'], [
|
|
51
|
+
['内核', `mihomo ${version.version}${version.meta ? ' (meta)' : ''}`],
|
|
52
|
+
['控制口', client.api],
|
|
53
|
+
['模式', configs.mode],
|
|
54
|
+
['日志级别', configs['log-level']],
|
|
55
|
+
['混合代理口', `${configs['bind-address'] || '127.0.0.1'}:${configs['mixed-port']}`],
|
|
56
|
+
['allow-lan', String(configs['allow-lan'])],
|
|
57
|
+
['代理组 / 节点', `${groups.length} 组 / ${nodes.length} 节点`],
|
|
58
|
+
]),
|
|
59
|
+
];
|
|
60
|
+
if (subs.length > 0) {
|
|
61
|
+
const rows = subs.map(([name, provider]) => [
|
|
62
|
+
name,
|
|
63
|
+
provider.vehicleType.toLowerCase(),
|
|
64
|
+
String(provider.proxies.length),
|
|
65
|
+
String(countAlive(provider.proxies)),
|
|
66
|
+
formatRelativeTime(provider.updatedAt),
|
|
67
|
+
]);
|
|
68
|
+
lines.push('', renderTable(['PROVIDER', 'TYPE', 'NODES', 'ALIVE', 'UPDATED'], rows));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
lines.push('', 'provider:无(当前为整份 proxies 配置,尚未迁移到 proxy-providers 架构)');
|
|
72
|
+
}
|
|
73
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* 确认对话框(cc-switch 确认卡片语言,spec 2026-09-13 dialogs-topbar-polish §3.1)。
|
|
4
|
+
* 键帽反色块居中、问题文案居中、大留白;无内部标题行——问题文案即内容。
|
|
5
|
+
* y/Y 确认,n/N/ESC 取消;danger 模式红色边框与文案,用于不可撤销的删除类操作。
|
|
6
|
+
*
|
|
7
|
+
* borderTitle:内嵌边框标题形态(如退出确认的「退出」,Panel 同款顶线)——
|
|
8
|
+
* 键帽紧贴顶线、与文案间隔三行、底部三行留白;缺省保持紧凑确认卡形态。
|
|
9
|
+
*/
|
|
10
|
+
import { Box, Text, useInput } from 'ink';
|
|
11
|
+
import { colors, styles } from '../ui/theme.js';
|
|
12
|
+
import { TOP_PREFIX, panelTopParts } from '../ui/Panel.js';
|
|
13
|
+
import { useKeyCapture } from '../ui/keyCapture.js';
|
|
14
|
+
export function ConfirmDialog({ message, danger = false, width = 56, enterConfirms = false, borderTitle, onConfirm, onCancel, }) {
|
|
15
|
+
useKeyCapture(true);
|
|
16
|
+
useInput((input, key) => {
|
|
17
|
+
if (key.escape || input === 'n' || input === 'N') {
|
|
18
|
+
onCancel();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (input === 'y' || input === 'Y' || (enterConfirms && key.return)) {
|
|
22
|
+
onConfirm();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const lines = Array.isArray(message) ? message : [message];
|
|
26
|
+
const borderColor = danger ? colors.danger : colors.accent;
|
|
27
|
+
const titleStyle = danger ? { color: colors.danger, bold: true } : styles.panelTitle;
|
|
28
|
+
const parts = borderTitle !== undefined ? panelTopParts(borderTitle, width) : null;
|
|
29
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, children: [parts ? (_jsxs(Text, { children: [_jsx(Text, { color: borderColor, children: TOP_PREFIX }), _jsx(Text, { ...titleStyle, children: parts.title }), _jsx(Text, { color: borderColor, children: parts.tail })] })) : null, _jsxs(Box, { flexDirection: "column", alignItems: "center", borderStyle: "round", borderTop: parts ? false : undefined, borderColor: borderColor, paddingX: 1, paddingTop: parts ? 0 : 1, paddingBottom: parts ? 1 : 2, children: [_jsxs(Text, { children: [_jsx(Text, { inverse: true, children: enterConfirms ? 'Enter 确认' : 'y 确认' }), _jsx(Text, { children: ' ' }), _jsx(Text, { inverse: true, children: enterConfirms ? 'Esc 取消' : 'n/Esc 取消' })] }), _jsx(Box, { flexDirection: "column", alignItems: "center", marginTop: parts ? 3 : 1, children: lines.map((line, index) => (_jsx(Text, { color: danger ? colors.danger : undefined, dimColor: !danger && index > 0, children: line }, index))) })] })] }));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ConfirmDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.js","sourceRoot":"","sources":["../../src/components/ConfirmDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/** 延迟着色标签。五状态对应 SPEC 6.2 的表格。 */
|
|
3
|
+
import { Text } from 'ink';
|
|
4
|
+
import { colors } from '../ui/theme.js';
|
|
5
|
+
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
6
|
+
export function spinnerFrame(tick) {
|
|
7
|
+
return SPINNER[tick % SPINNER.length] ?? SPINNER[0];
|
|
8
|
+
}
|
|
9
|
+
export function DelayBadge({ status, delay, testing, width = 7 }) {
|
|
10
|
+
if (testing) {
|
|
11
|
+
return (_jsx(Text, { color: colors.info, children: '测速中'.padStart(width) }));
|
|
12
|
+
}
|
|
13
|
+
switch (status) {
|
|
14
|
+
case 'good':
|
|
15
|
+
return _jsx(Text, { color: colors.success, children: `${delay}ms`.padStart(width) });
|
|
16
|
+
case 'fair':
|
|
17
|
+
return _jsx(Text, { color: colors.warning, children: `${delay}ms`.padStart(width) });
|
|
18
|
+
case 'slow':
|
|
19
|
+
return _jsx(Text, { color: colors.danger, children: `${delay}ms`.padStart(width) });
|
|
20
|
+
case 'dead':
|
|
21
|
+
return _jsx(Text, { color: colors.danger, children: '超时'.padStart(width - 2) });
|
|
22
|
+
default:
|
|
23
|
+
// 未测试 ≠ 不可用:lazy 组在被使用前 history 恒为空(SPEC 3.4)
|
|
24
|
+
return _jsx(Text, { dimColor: true, children: '---'.padStart(width) });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=DelayBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DelayBadge.js","sourceRoot":"","sources":["../../src/components/DelayBadge.tsx"],"names":[],"mappings":";AAAA,iCAAiC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAWvC,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAElE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,CAAE,CAAA;AACtD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,EAAmB;IAC/E,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,IAAI,YAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAQ,CACzD,CAAA;IACH,CAAC;IACD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,OAAO,YAAG,GAAG,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAQ,CAAA;QAC3E,KAAK,MAAM;YACT,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,OAAO,YAAG,GAAG,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAQ,CAAA;QAC3E,KAAK,MAAM;YACT,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,YAAG,GAAG,KAAK,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAQ,CAAA;QAC1E,KAAK,MAAM;YACT,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,YAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,GAAQ,CAAA;QACtE;YACE,8CAA8C;YAC9C,OAAO,KAAC,IAAI,IAAC,QAAQ,kBAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAQ,CAAA;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* 通用多字段输入对话框(设计稿 5.1,交互参照 cc-switch 的表单样式重做)。
|
|
4
|
+
*
|
|
5
|
+
* 键位:字符输入当前字段;↑↓/Tab 切换字段;Enter 当前字段合法则前进,
|
|
6
|
+
* 到最后一个字段且整表合法时提交;ESC 取消。
|
|
7
|
+
*
|
|
8
|
+
* 粘贴:ink 7 的 usePaste 走 bracketed paste 独立通道,整串插入当前字段;
|
|
9
|
+
* 终端不支持 bracketed paste 时,粘贴会作为多字符 chunk 进入 useInput,
|
|
10
|
+
* 旧实现 `input.length === 1` 会把整串丢弃(新增订阅框贴不进 URL 的根因),
|
|
11
|
+
* 现按「过滤控制字符后整串插入」兜底。
|
|
12
|
+
*
|
|
13
|
+
* 编辑:←→/Home/End 移动光标(含 Ctrl+A/E/B/F),Backspace/Delete 删字符,
|
|
14
|
+
* Ctrl+U 清空、Ctrl+K 删至行尾、Ctrl+W 向前删一个词。光标始终可见(反色块),
|
|
15
|
+
* 超长值(订阅 URL)按显示宽度开窗滚动,不折行不撑破布局。
|
|
16
|
+
*
|
|
17
|
+
* 实现要点:终端一次 read 往往带来一串字符(快速打字/粘贴),同一轮事件里
|
|
18
|
+
* handler 会被连续调用多次 —— 因此按键处理一律读写 valuesRef/activeRef/
|
|
19
|
+
* cursorRef(始终最新的镜像),不能依赖 useState 闭包里的旧值。
|
|
20
|
+
* 光标与增删一律按码点数组操作,emoji 等代理对不会被 slice 切断。
|
|
21
|
+
*/
|
|
22
|
+
import { Box, Text, useInput, usePaste } from 'ink';
|
|
23
|
+
import { FooterLine } from '../ui/FooterLine.js';
|
|
24
|
+
import { ListDialog } from './ListDialog.js';
|
|
25
|
+
import { MIN_PANEL_WIDTH, Panel, TOP_PREFIX, panelTopParts } from '../ui/Panel.js';
|
|
26
|
+
import { colors } from '../ui/theme.js';
|
|
27
|
+
import { useRef, useState } from 'react';
|
|
28
|
+
import { displayWidth, truncateDisplay } from '../commands/output.js';
|
|
29
|
+
import { useKeyCapture } from '../ui/keyCapture.js';
|
|
30
|
+
export function validateField(field, value) {
|
|
31
|
+
if (field.readOnly)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (field.required && value === '')
|
|
34
|
+
return `${field.label}不能为空`;
|
|
35
|
+
return field.validate?.(value);
|
|
36
|
+
}
|
|
37
|
+
/** 逐字段求错误;只读字段恒无错误 */
|
|
38
|
+
export function allErrors(fields, values) {
|
|
39
|
+
const errors = {};
|
|
40
|
+
for (const field of fields) {
|
|
41
|
+
errors[field.key] = validateField(field, values[field.key] ?? '');
|
|
42
|
+
}
|
|
43
|
+
return errors;
|
|
44
|
+
}
|
|
45
|
+
export function isFormValid(fields, values) {
|
|
46
|
+
return Object.values(allErrors(fields, values)).every((error) => error === undefined);
|
|
47
|
+
}
|
|
48
|
+
/** 丢掉控制字符(换行、制表、0x00-0x1f、DEL),保留可打印内容 */
|
|
49
|
+
export function sanitizeInput(raw) {
|
|
50
|
+
return [...raw]
|
|
51
|
+
.filter((char) => char >= ' ' && char !== '\u007f')
|
|
52
|
+
.join('');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 把超长单行值按显示宽度开窗,保证光标字符可见。
|
|
56
|
+
* display 是已经过掩码处理的展示串(secret 字段传 * 串);cursor 是其中的码点下标;
|
|
57
|
+
* max 是可用显示列数。
|
|
58
|
+
*/
|
|
59
|
+
export function inputWindow(display, cursor, max) {
|
|
60
|
+
const chars = [...display];
|
|
61
|
+
const clamped = Math.min(Math.max(0, cursor), chars.length);
|
|
62
|
+
const widths = chars.map((char) => displayWidth(char));
|
|
63
|
+
const total = widths.reduce((sum, w) => sum + w, 0);
|
|
64
|
+
if (max <= 0)
|
|
65
|
+
return { text: '', cursorOffset: 0 };
|
|
66
|
+
if (total <= max) {
|
|
67
|
+
return { text: display, cursorOffset: clamped };
|
|
68
|
+
}
|
|
69
|
+
// 以光标为中心向两侧扩张,指示符 … 各预留 1 列
|
|
70
|
+
const cursorWidth = clamped < chars.length ? widths[clamped] ?? 1 : 1;
|
|
71
|
+
let start = clamped; // [start, clamped) 是光标左侧片段
|
|
72
|
+
let end = Math.min(clamped + 1, chars.length); // [clamped, end) 含光标字符与其右侧片段
|
|
73
|
+
let used = cursorWidth;
|
|
74
|
+
while (true) {
|
|
75
|
+
if (start > 0 && used + widths[start - 1] + 2 <= max) {
|
|
76
|
+
start -= 1;
|
|
77
|
+
used += widths[start];
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (end < chars.length && used + widths[end] + 2 <= max) {
|
|
81
|
+
used += widths[end];
|
|
82
|
+
end += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
const markLeft = start > 0;
|
|
88
|
+
const markRight = end < chars.length;
|
|
89
|
+
// 预算里已含两侧 … 的 2 列,这里直接落位
|
|
90
|
+
const middle = chars.slice(start, end).join('');
|
|
91
|
+
const prefix = markLeft ? '…' : '';
|
|
92
|
+
const suffix = markRight ? '…' : '';
|
|
93
|
+
return {
|
|
94
|
+
text: prefix + middle + suffix,
|
|
95
|
+
cursorOffset: (markLeft ? 1 : 0) + (clamped - start),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function InputDialog({ title, fields, width = 64, singleLinePaste = false, onSubmit, onCancel }) {
|
|
99
|
+
const [pasteError, setPasteError] = useState('');
|
|
100
|
+
const [values, setValues] = useState(() => {
|
|
101
|
+
const initial = {};
|
|
102
|
+
for (const field of fields)
|
|
103
|
+
initial[field.key] = field.value ?? '';
|
|
104
|
+
return initial;
|
|
105
|
+
});
|
|
106
|
+
const valuesRef = useRef(values);
|
|
107
|
+
const [active, setActive] = useState(0);
|
|
108
|
+
const activeRef = useRef(0);
|
|
109
|
+
const cursorRef = useRef(Math.min(fields[0]?.value?.length ?? 0, Number.MAX_SAFE_INTEGER));
|
|
110
|
+
const [attempted, setAttempted] = useState(false); // 只有在提交被拦后才开始逐字段标红
|
|
111
|
+
// 选择型字段(options)按下 Enter 时弹出的选项列表;null 表示未打开
|
|
112
|
+
const [picking, setPicking] = useState(null);
|
|
113
|
+
const errors = allErrors(fields, values);
|
|
114
|
+
const commitValues = (next) => {
|
|
115
|
+
valuesRef.current = next;
|
|
116
|
+
setValues(next);
|
|
117
|
+
};
|
|
118
|
+
/** 切到某字段时按其当前值末尾落位光标(表单的通行习惯) */
|
|
119
|
+
const moveTo = (index) => {
|
|
120
|
+
const clamped = Math.min(fields.length - 1, Math.max(0, index));
|
|
121
|
+
const field = fields[clamped];
|
|
122
|
+
cursorRef.current = clamped >= 0 && field ? (valuesRef.current[field.key] ?? '').length : 0;
|
|
123
|
+
activeRef.current = clamped;
|
|
124
|
+
setActive(clamped);
|
|
125
|
+
};
|
|
126
|
+
/** 对当前字段按码点数组做一次原位变换,返回 null 表示不修改 */
|
|
127
|
+
const editCurrent = (transform) => {
|
|
128
|
+
const field = fields[activeRef.current];
|
|
129
|
+
if (!field || field.readOnly)
|
|
130
|
+
return;
|
|
131
|
+
const key = field.key;
|
|
132
|
+
const chars = [...(valuesRef.current[key] ?? '')];
|
|
133
|
+
const result = transform(chars, Math.min(cursorRef.current, chars.length));
|
|
134
|
+
if (!result)
|
|
135
|
+
return;
|
|
136
|
+
cursorRef.current = result.cursor;
|
|
137
|
+
commitValues({ ...valuesRef.current, [key]: result.chars.join('') });
|
|
138
|
+
};
|
|
139
|
+
const insertText = (raw) => {
|
|
140
|
+
if (singleLinePaste && /[\r\n\0]/.test(raw)) {
|
|
141
|
+
setPasteError('只能输入单条规则,不允许换行或 NUL');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
setPasteError('');
|
|
145
|
+
const cleaned = sanitizeInput(raw);
|
|
146
|
+
if (!cleaned)
|
|
147
|
+
return;
|
|
148
|
+
editCurrent((chars, cursor) => ({
|
|
149
|
+
chars: [...chars.slice(0, cursor), ...[...cleaned], ...chars.slice(cursor)],
|
|
150
|
+
cursor: cursor + [...cleaned].length,
|
|
151
|
+
}));
|
|
152
|
+
};
|
|
153
|
+
usePaste(insertText);
|
|
154
|
+
// 对话框存活期间捕获全部按键:App 全局 handler(含 ESC 退出)一律让路
|
|
155
|
+
useKeyCapture(true);
|
|
156
|
+
useInput((input, key) => {
|
|
157
|
+
if (picking)
|
|
158
|
+
return;
|
|
159
|
+
if (key.escape) {
|
|
160
|
+
onCancel();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (key.upArrow) {
|
|
164
|
+
moveTo(activeRef.current - 1);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (key.downArrow || key.tab) {
|
|
168
|
+
moveTo(activeRef.current + 1);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Enter 一律提交整表(与列表页「Enter = 确认」一致)。
|
|
172
|
+
// 选择列表统一用 e 打开:options 为纯选择,suggestions 为可输入也可选。
|
|
173
|
+
if (input === 'e' && !key.ctrl) {
|
|
174
|
+
const current = fields[activeRef.current];
|
|
175
|
+
const choices = current?.options ?? current?.suggestions;
|
|
176
|
+
if (current && choices && choices.length > 0) {
|
|
177
|
+
setPicking(current);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (key.return) {
|
|
182
|
+
if (isFormValid(fields, valuesRef.current)) {
|
|
183
|
+
onSubmit({ ...valuesRef.current });
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
setAttempted(true);
|
|
187
|
+
// 跳到第一个有错误的字段,让问题就地可见
|
|
188
|
+
const current = allErrors(fields, valuesRef.current);
|
|
189
|
+
const firstInvalid = fields.findIndex((field) => current[field.key] !== undefined);
|
|
190
|
+
if (firstInvalid >= 0)
|
|
191
|
+
moveTo(firstInvalid);
|
|
192
|
+
}
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (key.leftArrow) {
|
|
196
|
+
editCurrent((chars, cursor) => ({ chars, cursor: Math.max(0, cursor - 1) }));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (key.rightArrow) {
|
|
200
|
+
editCurrent((chars, cursor) => ({ chars, cursor: Math.min(chars.length, cursor + 1) }));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (key.home || (key.ctrl && input === 'a')) {
|
|
204
|
+
editCurrent((chars, cursor) => ({ chars, cursor: 0 }));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (key.end || (key.ctrl && input === 'e')) {
|
|
208
|
+
editCurrent((chars, cursor) => ({ chars, cursor: chars.length }));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (key.backspace) {
|
|
212
|
+
editCurrent((chars, cursor) => cursor === 0 ? null : { chars: [...chars.slice(0, cursor - 1), ...chars.slice(cursor)], cursor: cursor - 1 });
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (key.delete) {
|
|
216
|
+
editCurrent((chars, cursor) => cursor >= chars.length ? null : { chars: [...chars.slice(0, cursor), ...chars.slice(cursor + 1)], cursor });
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (key.ctrl) {
|
|
220
|
+
if (input === 'b') {
|
|
221
|
+
editCurrent((chars, cursor) => ({ chars, cursor: Math.max(0, cursor - 1) }));
|
|
222
|
+
}
|
|
223
|
+
else if (input === 'f') {
|
|
224
|
+
editCurrent((chars, cursor) => ({ chars, cursor: Math.min(chars.length, cursor + 1) }));
|
|
225
|
+
}
|
|
226
|
+
else if (input === 'u') {
|
|
227
|
+
editCurrent(() => ({ chars: [], cursor: 0 }));
|
|
228
|
+
}
|
|
229
|
+
else if (input === 'k') {
|
|
230
|
+
editCurrent((chars, cursor) => ({ chars: chars.slice(0, cursor), cursor }));
|
|
231
|
+
}
|
|
232
|
+
else if (input === 'w') {
|
|
233
|
+
editCurrent((chars, cursor) => {
|
|
234
|
+
let i = cursor;
|
|
235
|
+
while (i > 0 && chars[i - 1] === ' ')
|
|
236
|
+
i -= 1;
|
|
237
|
+
while (i > 0 && chars[i - 1] !== ' ')
|
|
238
|
+
i -= 1;
|
|
239
|
+
return { chars: [...chars.slice(0, i), ...chars.slice(cursor)], cursor: i };
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (key.meta)
|
|
245
|
+
return;
|
|
246
|
+
// 纯选择字段不接受自由输入;带候选项的字段中 e 打开选择列表
|
|
247
|
+
const current = fields[activeRef.current];
|
|
248
|
+
if (current?.options)
|
|
249
|
+
return;
|
|
250
|
+
if (current?.suggestions && input === 'e') {
|
|
251
|
+
setPicking(current);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// 整串插入(多字符 chunk = 不带 bracketed paste 标记的粘贴 / 快速输入)
|
|
255
|
+
insertText(input);
|
|
256
|
+
});
|
|
257
|
+
const tried = attempted;
|
|
258
|
+
// 居中窄卡片(spec 2026-09-13 §5.3):min(64, max(44, width-8));
|
|
259
|
+
// 终端窄于 44 列时退化为全宽(无居中),保可用性
|
|
260
|
+
// 字段多时卡片变高,收窄宽度换取纵向空间,避免撑出屏幕
|
|
261
|
+
const cardWidth = width < 44 ? width : Math.min(fields.length > 4 ? 56 : 64, Math.max(44, width - 8));
|
|
262
|
+
// 字段槽位宽:卡片 Panel 边框 2 + paddingX 2;输入盒内可用列再减槽位边框 2 + paddingX 2
|
|
263
|
+
const slotWidth = Math.max(0, cardWidth - 4);
|
|
264
|
+
const innerWidth = Math.max(10, cardWidth - 8);
|
|
265
|
+
// 校验错误集中展示:优先当前字段,其次第一个出错字段(替代逐字段错误行)
|
|
266
|
+
let shownError;
|
|
267
|
+
if (tried) {
|
|
268
|
+
const activeField = fields[active];
|
|
269
|
+
shownError = (activeField && errors[activeField.key]) || fields.map((f) => errors[f.key]).find(Boolean);
|
|
270
|
+
}
|
|
271
|
+
const renderSlotContent = (field, value, isActive) => {
|
|
272
|
+
if (!isActive) {
|
|
273
|
+
const display = field.secret ? '*'.repeat(value.length) : value;
|
|
274
|
+
const optionLabel = field.options?.find((option) => option.value === value)?.label;
|
|
275
|
+
// 未聚焦时按显示宽度截断到一行,超长值(订阅 URL)尾部省略,避免撑高槽位
|
|
276
|
+
const shown = truncateDisplay(optionLabel ?? display, innerWidth) || (field.placeholder ?? '—');
|
|
277
|
+
return _jsx(Text, { dimColor: true, wrap: "truncate", children: shown });
|
|
278
|
+
}
|
|
279
|
+
const display = field.secret ? '*'.repeat(value.length) : value;
|
|
280
|
+
const windowed = value
|
|
281
|
+
? inputWindow(display, Math.min(cursorRef.current, [...display].length), innerWidth)
|
|
282
|
+
: { text: '', cursorOffset: 0 };
|
|
283
|
+
const windowChars = [...windowed.text];
|
|
284
|
+
const at = value ? (windowChars[windowed.cursorOffset] ?? ' ') : ' ';
|
|
285
|
+
const before = value ? windowChars.slice(0, windowed.cursorOffset).join('') : '';
|
|
286
|
+
const after = value ? windowChars.slice(windowed.cursorOffset + 1).join('') : '';
|
|
287
|
+
return (_jsx(Text, { children: value ? (_jsxs(_Fragment, { children: [before, _jsx(Text, { inverse: true, children: at }), after] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { inverse: true, children: ' ' }), field.options || field.suggestions ? (_jsx(Text, { dimColor: true, children: field.options ? 'e 选择' : 'e 选择已有' })) : field.placeholder ? (_jsx(Text, { dimColor: true, children: field.placeholder })) : null] })) }));
|
|
288
|
+
};
|
|
289
|
+
/** 字段槽位:恒 3 行的内嵌标题 mini-Panel。聚焦 accent 亮起(invalid 转
|
|
290
|
+
* danger),非聚焦/readOnly 退后为 surfaceBorder + dim。顶线复用
|
|
291
|
+
* panelTopParts 的截断/宽度逻辑。marginTop 只加在首个字段之前,字段之间
|
|
292
|
+
* 紧贴,保证多字段时卡片高度一致、不靠字段数撑出参差空白。 */
|
|
293
|
+
const renderSlot = (field, value, index) => {
|
|
294
|
+
const isActive = index === active && !field.readOnly;
|
|
295
|
+
const invalid = tried && isActive && errors[field.key] !== undefined;
|
|
296
|
+
const borderColor = invalid ? colors.danger : isActive ? colors.accent : colors.surfaceBorder;
|
|
297
|
+
const labelStyle = invalid
|
|
298
|
+
? { color: colors.danger, bold: true }
|
|
299
|
+
: isActive
|
|
300
|
+
? { color: colors.accent, bold: true }
|
|
301
|
+
: { color: colors.muted };
|
|
302
|
+
const label = field.readOnly ? `${field.label}(只读)` : field.label;
|
|
303
|
+
const fullTitle = field.required ? `${label} *` : label;
|
|
304
|
+
const parts = panelTopParts(fullTitle, slotWidth);
|
|
305
|
+
// required 的 * 单独 danger 色;标题被截断(以 … 结尾)时整段按 labelStyle 渲染
|
|
306
|
+
const starSuffix = field.required && parts.title.endsWith(' *');
|
|
307
|
+
const labelShown = starSuffix ? parts.title.replace(/ \*$/, '') : parts.title;
|
|
308
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: index === 0 ? 1 : 0, width: slotWidth, children: slotWidth < MIN_PANEL_WIDTH ? (_jsxs(_Fragment, { children: [_jsx(Text, { ...labelStyle, children: fullTitle }), renderSlotContent(field, value, isActive)] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [_jsx(Text, { color: borderColor, children: TOP_PREFIX }), _jsx(Text, { ...labelStyle, children: labelShown }), starSuffix ? _jsx(Text, { color: colors.danger, children: ' *' }) : null, _jsx(Text, { color: borderColor, children: parts.tail })] }), _jsx(Box, { flexDirection: "column", borderStyle: "round", borderTop: false, borderColor: borderColor, paddingX: 1, children: renderSlotContent(field, value, isActive) })] })) }, field.key));
|
|
309
|
+
};
|
|
310
|
+
const card = (_jsxs(Panel, { title: `◆ ${title}`, width: cardWidth, children: [fields.map((field, index) => renderSlot(field, values[field.key] ?? '', index)), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [shownError || pasteError ? _jsx(Text, { color: colors.danger, children: `⚠ ${shownError || pasteError}` }) : null, _jsx(FooterLine, { hints: [
|
|
311
|
+
{ key: 'Enter', label: '确认' },
|
|
312
|
+
{ key: '↑↓', label: '切换' },
|
|
313
|
+
{ key: 'ESC', label: '取消' },
|
|
314
|
+
], width: cardWidth - 4 })] })] }));
|
|
315
|
+
// 选择型字段:Enter(options)或 e(suggestions)打开选项列表,选中后回填
|
|
316
|
+
const pickingChoices = picking?.options ?? picking?.suggestions;
|
|
317
|
+
if (picking && pickingChoices) {
|
|
318
|
+
return (_jsx(ListDialog, { borderTitle: picking.label, items: pickingChoices.map((option) => ({ value: option.value, label: option.label })), width: cardWidth, onSubmit: (value) => {
|
|
319
|
+
commitValues({ ...valuesRef.current, [picking.key]: value });
|
|
320
|
+
setPicking(null);
|
|
321
|
+
}, onCancel: () => setPicking(null) }));
|
|
322
|
+
}
|
|
323
|
+
return width < 44 ? card : _jsx(Box, { justifyContent: "center", children: card });
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=InputDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputDialog.js","sourceRoot":"","sources":["../../src/components/InputDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* 通用列表选择对话框(设置页的日志级别 / 内核版本 / 下载源共用)。
|
|
4
|
+
* 边框内嵌标题(Panel 同款顶线语言)+ 不可选的 dim 分组头 + ❯ 光标行。
|
|
5
|
+
*
|
|
6
|
+
* 键位:↑↓ 移动(自动跳过分组头)、Enter 选中、ESC 取消。
|
|
7
|
+
* 条目超过 maxVisible 时按光标位置开窗,不折行不撑破布局。
|
|
8
|
+
*/
|
|
9
|
+
import { Box, Text, useInput } from 'ink';
|
|
10
|
+
import { FooterLine } from '../ui/FooterLine.js';
|
|
11
|
+
import { TOP_PREFIX, panelTopParts } from '../ui/Panel.js';
|
|
12
|
+
import { colors, styles } from '../ui/theme.js';
|
|
13
|
+
import { useKeyCapture } from '../ui/keyCapture.js';
|
|
14
|
+
import { displayWidth, padDisplay } from '../commands/output.js';
|
|
15
|
+
import { useRef, useState } from 'react';
|
|
16
|
+
/** 纯函数:从任意下标出发,找到下一个可选条目(跳过分组头);无则 null */
|
|
17
|
+
export function nextSelectable(items, from, step) {
|
|
18
|
+
let index = from + step;
|
|
19
|
+
while (index >= 0 && index < items.length) {
|
|
20
|
+
if (!items[index].section && items[index].value !== undefined)
|
|
21
|
+
return index;
|
|
22
|
+
index += step;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/** 纯函数:窗口起始下标,保证 active 落在 [start, start + maxVisible) 内 */
|
|
27
|
+
export function windowStart(active, items, maxVisible) {
|
|
28
|
+
if (items.length <= maxVisible)
|
|
29
|
+
return 0;
|
|
30
|
+
return Math.min(Math.max(0, active - Math.floor(maxVisible / 2)), items.length - maxVisible);
|
|
31
|
+
}
|
|
32
|
+
export function ListDialog({ borderTitle, items, width = 56, maxVisible = 12, onSubmit, onCancel, }) {
|
|
33
|
+
const first = nextSelectable(items, -1, 1) ?? -1;
|
|
34
|
+
const [active, setActive] = useState(first);
|
|
35
|
+
const activeRef = useRef(first);
|
|
36
|
+
const move = (step) => {
|
|
37
|
+
const next = nextSelectable(items, activeRef.current, step);
|
|
38
|
+
if (next === null)
|
|
39
|
+
return;
|
|
40
|
+
activeRef.current = next;
|
|
41
|
+
setActive(next);
|
|
42
|
+
};
|
|
43
|
+
// 对话框存活期间捕获全部按键:App 全局 handler(含 ESC 退出)一律让路
|
|
44
|
+
useKeyCapture(true);
|
|
45
|
+
useInput((_input, key) => {
|
|
46
|
+
if (key.escape) {
|
|
47
|
+
onCancel();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (key.upArrow) {
|
|
51
|
+
move(-1);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (key.downArrow) {
|
|
55
|
+
move(1);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (key.return) {
|
|
59
|
+
const item = items[activeRef.current];
|
|
60
|
+
if (item && !item.section && item.value !== undefined)
|
|
61
|
+
onSubmit(item.value);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const parts = panelTopParts(borderTitle, width);
|
|
65
|
+
const innerWidth = Math.max(10, width - 4);
|
|
66
|
+
const start = windowStart(Math.max(0, active), items, Math.max(1, maxVisible));
|
|
67
|
+
const visible = items.slice(start, start + Math.max(1, maxVisible));
|
|
68
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, children: [_jsxs(Text, { children: [_jsx(Text, { color: colors.accent, children: TOP_PREFIX }), _jsx(Text, { ...styles.panelTitle, children: parts.title }), _jsx(Text, { color: colors.accent, children: parts.tail })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderTop: false, borderColor: colors.accent, paddingX: 1, children: [visible.map((item, offset) => {
|
|
69
|
+
const index = start + offset;
|
|
70
|
+
if (item.section) {
|
|
71
|
+
return (_jsx(Text, { dimColor: true, children: ` ${item.label}` }, `s-${item.label}`));
|
|
72
|
+
}
|
|
73
|
+
const focused = index === active;
|
|
74
|
+
const hint = item.hint;
|
|
75
|
+
const hintWidth = hint ? displayWidth(hint) : 0;
|
|
76
|
+
const labelShown = hint
|
|
77
|
+
? padDisplay(item.label, Math.max(1, innerWidth - 2 - hintWidth - 1))
|
|
78
|
+
: item.label;
|
|
79
|
+
return (_jsxs(Text, { wrap: "truncate-end", children: [focused ? (_jsx(Text, { ...styles.rowFocus, bold: true, children: '❯ ' })) : (_jsx(Text, { children: ' ' })), _jsx(Text, { ...(focused ? styles.rowSelected : {}), children: labelShown }), hint ? _jsx(Text, { dimColor: true, children: ` ${hint}` }) : null] }, item.value ?? item.label));
|
|
80
|
+
}), _jsx(Box, { marginTop: 1, children: _jsx(FooterLine, { hints: [
|
|
81
|
+
{ key: '↑↓', label: '选择' },
|
|
82
|
+
{ key: 'Enter', label: '确认' },
|
|
83
|
+
{ key: 'ESC', label: '取消' },
|
|
84
|
+
], width: innerWidth }) })] })] }));
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=ListDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListDialog.js","sourceRoot":"","sources":["../../src/components/ListDialog.tsx"],"names":[],"mappings":"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"}
|