From de59facad671368d40f1f3da75063c370ee66fad Mon Sep 17 00:00:00 2001 From: YoVinchen Date: Thu, 29 Jan 2026 01:12:48 +0800 Subject: [PATCH] feat(ui): add auto-height support for JsonEditor component Add autoHeight prop to dynamically resize editor based on content lines. Apply to config preview sections in Codex, Gemini, and CommonConfig forms. --- src/components/JsonEditor.tsx | 35 ++++++++++++++++--- .../providers/forms/CodexConfigSections.tsx | 6 ++-- .../providers/forms/CommonConfigEditor.tsx | 3 +- .../providers/forms/GeminiConfigSections.tsx | 3 +- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/components/JsonEditor.tsx b/src/components/JsonEditor.tsx index 65ba9f01c..3b4eaa28d 100644 --- a/src/components/JsonEditor.tsx +++ b/src/components/JsonEditor.tsx @@ -24,6 +24,8 @@ interface JsonEditorProps { showMinimap?: boolean; // 添加此属性以防未来使用 /** 只读模式 */ readOnly?: boolean; + /** 自动高度模式:根据内容自动调整高度,rows 作为最小行数 */ + autoHeight?: boolean; } const JsonEditor: React.FC = ({ @@ -36,6 +38,7 @@ const JsonEditor: React.FC = ({ language = "json", height, readOnly = false, + autoHeight = false, }) => { const { t } = useTranslation(); const editorRef = useRef(null); @@ -85,7 +88,14 @@ const JsonEditor: React.FC = ({ if (!editorRef.current) return; // 创建编辑器扩展 - const minHeightPx = height ? undefined : Math.max(1, rows) * 18; + const lineHeight = 18; + const minHeightPx = height ? undefined : Math.max(1, rows) * lineHeight; + + // 自动高度模式:计算内容行数 + const contentLines = value ? value.split("\n").length : 1; + const autoHeightPx = autoHeight + ? Math.max(rows, contentLines) * lineHeight + 10 // +10 for padding + : undefined; // 使用 baseTheme 定义基础样式,优先级低于 oneDark,但可以正确响应主题 const baseTheme = EditorView.baseTheme({ @@ -126,9 +136,17 @@ const JsonEditor: React.FC = ({ ? `${height}px` : height : undefined; + + // 确定最终高度:优先级 height > autoHeight > minHeight + const finalHeight = heightValue + ? heightValue + : autoHeightPx + ? `${autoHeightPx}px` + : undefined; + const sizingTheme = EditorView.theme({ - "&": heightValue - ? { height: heightValue } + "&": finalHeight + ? { height: finalHeight } : { minHeight: `${minHeightPx}px` }, ".cm-scroller": { overflow: "auto" }, ".cm-content": { @@ -227,7 +245,16 @@ const JsonEditor: React.FC = ({ view.destroy(); viewRef.current = null; }; - }, [darkMode, rows, height, language, jsonLinter, readOnly]); // 依赖项中不包含 onChange 和 placeholder,避免不必要的重建 + }, [ + darkMode, + rows, + height, + language, + jsonLinter, + readOnly, + autoHeight, + autoHeight ? value.split("\n").length : 0, + ]); // 依赖项中不包含 onChange 和 placeholder,避免不必要的重建;autoHeight 模式下根据行数变化重建 // 当 value 从外部改变时更新编辑器内容 useEffect(() => { diff --git a/src/components/providers/forms/CodexConfigSections.tsx b/src/components/providers/forms/CodexConfigSections.tsx index 8077a97ea..7d6c1b720 100644 --- a/src/components/providers/forms/CodexConfigSections.tsx +++ b/src/components/providers/forms/CodexConfigSections.tsx @@ -59,7 +59,8 @@ export const CodexAuthSection: React.FC = ({ onChange={handleChange} placeholder={t("codexConfig.authJsonPlaceholder")} darkMode={isDarkMode} - rows={6} + rows={3} + autoHeight={true} showValidation={true} language="json" /> @@ -204,7 +205,8 @@ export const CodexConfigSection: React.FC = ({ onChange={onChange} placeholder="" darkMode={isDarkMode} - rows={useCommonConfig && showPreview ? 6 : 8} + rows={useCommonConfig && showPreview ? 3 : 8} + autoHeight={useCommonConfig && showPreview} showValidation={false} language="javascript" /> diff --git a/src/components/providers/forms/CommonConfigEditor.tsx b/src/components/providers/forms/CommonConfigEditor.tsx index 92ddb472d..ea046d960 100644 --- a/src/components/providers/forms/CommonConfigEditor.tsx +++ b/src/components/providers/forms/CommonConfigEditor.tsx @@ -147,7 +147,8 @@ export function CommonConfigEditor({ } }`} darkMode={isDarkMode} - rows={useCommonConfig && showPreview ? 10 : 14} + rows={useCommonConfig && showPreview ? 3 : 14} + autoHeight={useCommonConfig && showPreview} showValidation={true} language="json" /> diff --git a/src/components/providers/forms/GeminiConfigSections.tsx b/src/components/providers/forms/GeminiConfigSections.tsx index 4ae74d67b..4488e2607 100644 --- a/src/components/providers/forms/GeminiConfigSections.tsx +++ b/src/components/providers/forms/GeminiConfigSections.tsx @@ -146,7 +146,8 @@ export const GeminiEnvSection: React.FC = ({ GEMINI_API_KEY=sk-your-api-key-here GEMINI_MODEL=gemini-3-pro-preview`} darkMode={isDarkMode} - rows={useCommonConfig && showPreview ? 4 : 6} + rows={useCommonConfig && showPreview ? 3 : 6} + autoHeight={useCommonConfig && showPreview} showValidation={false} language="javascript" />