Files
kandev/apps/web/hooks/use-diff-editor-height.ts
T
2026-02-19 22:18:01 +00:00

62 lines
1.8 KiB
TypeScript

import { useState, useEffect, useMemo } from "react";
import type { editor as monacoEditor } from "monaco-editor";
interface UseDiffEditorHeightOptions {
modifiedEditor: monacoEditor.ICodeEditor | null;
originalEditor: monacoEditor.ICodeEditor | null;
compact: boolean;
lineHeight: number;
originalContent: string;
modifiedContent: string;
}
const MIN_HEIGHT = 80;
const MAX_HEIGHT_NORMAL = 600;
const MAX_HEIGHT_COMPACT = 300;
function clampHeight(h: number, compact: boolean): number {
const max = compact ? MAX_HEIGHT_COMPACT : MAX_HEIGHT_NORMAL;
return Math.min(Math.max(h, MIN_HEIGHT), max);
}
export function useDiffEditorHeight({
modifiedEditor,
originalEditor,
compact,
lineHeight,
originalContent,
modifiedContent,
}: UseDiffEditorHeightOptions): number {
// Estimate before editors mount
const estimatedHeight = useMemo(() => {
const lines = Math.max(originalContent.split("\n").length, modifiedContent.split("\n").length);
return clampHeight(lines * lineHeight + 10, compact);
}, [originalContent, modifiedContent, lineHeight, compact]);
const [editorHeight, setEditorHeight] = useState<number | null>(null);
// Subscribe to content size changes on both editors
useEffect(() => {
if (!modifiedEditor || !originalEditor) return;
const update = () => {
const modH = modifiedEditor.getContentHeight();
const origH = originalEditor.getContentHeight();
setEditorHeight(clampHeight(Math.max(modH, origH), compact));
};
update();
const d1 = modifiedEditor.onDidContentSizeChange(update);
const d2 = originalEditor.onDidContentSizeChange(update);
return () => {
d1.dispose();
d2.dispose();
setEditorHeight(null);
};
}, [modifiedEditor, originalEditor, compact]);
return editorHeight ?? estimatedHeight;
}