Files
claude-code/src/components/HelpV2/HelpV2.tsx
claude-code-best 5b1a52b8e0 更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)
* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files)

纯格式化:移除分号、React Compiler import、import 多行展开。
修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-2): 格式化 commands (79 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-5): 格式化 components其余 + hooks + tools (232 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md

- README.md: 大幅重写,更详细版本历史和配置示例
- Run.ps1: 新增 Windows 启动脚本
- TODO.md: 新增包完成清单
- V6.md: 删除(架构重构规划已不适用)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: 修复以前的问题

* fix: 修复 login 面板的问题

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 23:24:27 +08:00

139 lines
4.1 KiB
TypeScript

import * as React from 'react'
import { useExitOnCtrlCDWithKeybindings } from 'src/hooks/useExitOnCtrlCDWithKeybindings.js'
import { useShortcutDisplay } from 'src/keybindings/useShortcutDisplay.js'
import {
builtInCommandNames,
type Command,
type CommandResultDisplay,
INTERNAL_ONLY_COMMANDS,
} from '../../commands.js'
import { useIsInsideModal } from '../../context/modalContext.js'
import { useTerminalSize } from '../../hooks/useTerminalSize.js'
import { Box, Link, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
import { Pane } from '../design-system/Pane.js'
import { Tab, Tabs } from '../design-system/Tabs.js'
import { Commands } from './Commands.js'
import { General } from './General.js'
type Props = {
onClose: (
result?: string,
options?: { display?: CommandResultDisplay },
) => void
commands: Command[]
}
export function HelpV2({ onClose, commands }: Props): React.ReactNode {
const { rows, columns } = useTerminalSize()
const maxHeight = Math.floor(rows / 2)
// Inside the modal slot, FullscreenLayout already caps height and Pane/Tabs
// use flexShrink=0 (see #23592) — our own height= constraint would clip the
// footer since Tabs won't shrink to fit. Let the modal slot handle sizing.
const insideModal = useIsInsideModal()
const close = () => onClose('Help dialog dismissed', { display: 'system' })
useKeybinding('help:dismiss', close, { context: 'Help' })
const exitState = useExitOnCtrlCDWithKeybindings(close)
const dismissShortcut = useShortcutDisplay('help:dismiss', 'Help', 'esc')
const builtinNames = builtInCommandNames()
let builtinCommands = commands.filter(
cmd => builtinNames.has(cmd.name) && !cmd.isHidden,
)
let antOnlyCommands: Command[] = []
// We have to do this in an `if` to help treeshaking
if (process.env.USER_TYPE === 'ant') {
const internalOnlyNames = new Set(INTERNAL_ONLY_COMMANDS.map(_ => _.name))
builtinCommands = builtinCommands.filter(
cmd => !internalOnlyNames.has(cmd.name),
)
antOnlyCommands = commands.filter(
cmd => internalOnlyNames.has(cmd.name) && !cmd.isHidden,
)
}
const customCommands = commands.filter(
cmd => !builtinNames.has(cmd.name) && !cmd.isHidden,
)
const tabs = [
<Tab key="general" title="general">
<General />
</Tab>,
]
tabs.push(
<Tab key="commands" title="commands">
<Commands
commands={builtinCommands}
maxHeight={maxHeight}
columns={columns}
title="Browse default commands:"
onCancel={close}
/>
</Tab>,
)
tabs.push(
<Tab key="custom" title="custom-commands">
<Commands
commands={customCommands}
maxHeight={maxHeight}
columns={columns}
title="Browse custom commands:"
emptyMessage="No custom commands found"
onCancel={close}
/>
</Tab>,
)
if (process.env.USER_TYPE === 'ant' && antOnlyCommands.length > 0) {
tabs.push(
<Tab key="ant-only" title="[ant-only]">
<Commands
commands={antOnlyCommands}
maxHeight={maxHeight}
columns={columns}
title="Browse ant-only commands:"
onCancel={close}
/>
</Tab>,
)
}
return (
<Box flexDirection="column" height={insideModal ? undefined : maxHeight}>
<Pane color="professionalBlue">
<Tabs
title={
process.env.USER_TYPE === 'ant'
? '/help'
: `Claude Code v${MACRO.VERSION}`
}
color="professionalBlue"
defaultTab="general"
>
{tabs}
</Tabs>
<Box marginTop={1}>
<Text>
For more help:{' '}
<Link url="https://code.claude.com/docs/en/overview" />
</Text>
</Box>
<Box marginTop={1}>
<Text dimColor>
{exitState.pending ? (
<>Press {exitState.keyName} again to exit</>
) : (
<Text italic>{dismissShortcut} to cancel</Text>
)}
</Text>
</Box>
</Pane>
</Box>
)
}