mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 22:36:57 +10:00
229 lines
25 KiB
TypeScript
229 lines
25 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
||
|
|
import React, { Suspense, use, useMemo } from 'react';
|
||
|
|
import { useSettings } from '../../../hooks/useSettings.js';
|
||
|
|
import { useTerminalSize } from '../../../hooks/useTerminalSize.js';
|
||
|
|
import { stringWidth } from '../../../ink/stringWidth.js';
|
||
|
|
import { Ansi, Box, Text, useTheme } from '../../../ink.js';
|
||
|
|
import { type CliHighlight, getCliHighlightPromise } from '../../../utils/cliHighlight.js';
|
||
|
|
import { applyMarkdown } from '../../../utils/markdown.js';
|
||
|
|
import sliceAnsi from '../../../utils/sliceAnsi.js';
|
||
|
|
type PreviewBoxProps = {
|
||
|
|
/** The preview content to display. Markdown is rendered with syntax highlighting
|
||
|
|
* for code blocks (```ts, ```py, etc.). Also supports plain multi-line text. */
|
||
|
|
content: string;
|
||
|
|
/** Maximum number of lines to display before truncating. @default 20 */
|
||
|
|
maxLines?: number;
|
||
|
|
/** Minimum height (in lines) for the preview box. Content will be padded if shorter. */
|
||
|
|
minHeight?: number;
|
||
|
|
/** Minimum width for the preview box. @default 40 */
|
||
|
|
minWidth?: number;
|
||
|
|
/** Maximum width available for this box (e.g., the container width). */
|
||
|
|
maxWidth?: number;
|
||
|
|
};
|
||
|
|
const BOX_CHARS = {
|
||
|
|
topLeft: '┌',
|
||
|
|
topRight: '┐',
|
||
|
|
bottomLeft: '└',
|
||
|
|
bottomRight: '┘',
|
||
|
|
horizontal: '─',
|
||
|
|
vertical: '│',
|
||
|
|
teeLeft: '├',
|
||
|
|
teeRight: '┤'
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A bordered monospace box for displaying preview content.
|
||
|
|
* Truncates content that exceeds maxLines with an indicator.
|
||
|
|
* The parent component should pass maxLines based on its available height budget.
|
||
|
|
*/
|
||
|
|
export function PreviewBox(props) {
|
||
|
|
const $ = _c(4);
|
||
|
|
const settings = useSettings();
|
||
|
|
if (settings.syntaxHighlightingDisabled) {
|
||
|
|
let t0;
|
||
|
|
if ($[0] !== props) {
|
||
|
|
t0 = <PreviewBoxBody {...props} highlight={null} />;
|
||
|
|
$[0] = props;
|
||
|
|
$[1] = t0;
|
||
|
|
} else {
|
||
|
|
t0 = $[1];
|
||
|
|
}
|
||
|
|
return t0;
|
||
|
|
}
|
||
|
|
let t0;
|
||
|
|
if ($[2] !== props) {
|
||
|
|
t0 = <Suspense fallback={<PreviewBoxBody {...props} highlight={null} />}><PreviewBoxWithHighlight {...props} /></Suspense>;
|
||
|
|
$[2] = props;
|
||
|
|
$[3] = t0;
|
||
|
|
} else {
|
||
|
|
t0 = $[3];
|
||
|
|
}
|
||
|
|
return t0;
|
||
|
|
}
|
||
|
|
function PreviewBoxWithHighlight(props) {
|
||
|
|
const $ = _c(4);
|
||
|
|
let t0;
|
||
|
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||
|
|
t0 = getCliHighlightPromise();
|
||
|
|
$[0] = t0;
|
||
|
|
} else {
|
||
|
|
t0 = $[0];
|
||
|
|
}
|
||
|
|
const highlight = use(t0);
|
||
|
|
let t1;
|
||
|
|
if ($[1] !== highlight || $[2] !== props) {
|
||
|
|
t1 = <PreviewBoxBody {...props} highlight={highlight} />;
|
||
|
|
$[1] = highlight;
|
||
|
|
$[2] = props;
|
||
|
|
$[3] = t1;
|
||
|
|
} else {
|
||
|
|
t1 = $[3];
|
||
|
|
}
|
||
|
|
return t1;
|
||
|
|
}
|
||
|
|
function PreviewBoxBody(t0) {
|
||
|
|
const $ = _c(34);
|
||
|
|
const {
|
||
|
|
content,
|
||
|
|
maxLines,
|
||
|
|
minHeight,
|
||
|
|
minWidth: t1,
|
||
|
|
maxWidth,
|
||
|
|
highlight
|
||
|
|
} = t0;
|
||
|
|
const minWidth = t1 === undefined ? 40 : t1;
|
||
|
|
const {
|
||
|
|
columns: terminalWidth
|
||
|
|
} = useTerminalSize();
|
||
|
|
const [theme] = useTheme();
|
||
|
|
const effectiveMaxWidth = maxWidth ?? terminalWidth - 4;
|
||
|
|
const effectiveMaxLines = maxLines ?? 20;
|
||
|
|
let t2;
|
||
|
|
if ($[0] !== content || $[1] !== highlight || $[2] !== theme) {
|
||
|
|
t2 = applyMarkdown(content, theme, highlight);
|
||
|
|
$[0] = content;
|
||
|
|
$[1] = highlight;
|
||
|
|
$[2] = theme;
|
||
|
|
$[3] = t2;
|
||
|
|
} else {
|
||
|
|
t2 = $[3];
|
||
|
|
}
|
||
|
|
const rendered = t2;
|
||
|
|
let T0;
|
||
|
|
let bottomBorder;
|
||
|
|
let t3;
|
||
|
|
let t4;
|
||
|
|
let t5;
|
||
|
|
let truncationBar;
|
||
|
|
if ($[4] !== effectiveMaxLines || $[5] !== effectiveMaxWidth || $[6] !== minHeight || $[7] !== minWidth || $[8] !== rendered) {
|
||
|
|
const contentLines = rendered.split("\n");
|
||
|
|
const isTruncated = contentLines.length > effectiveMaxLines;
|
||
|
|
const truncatedLines = isTruncated ? contentLines.slice(0, effectiveMaxLines) : contentLines;
|
||
|
|
const effectiveMinHeight = Math.min(minHeight ?? 0, effectiveMaxLines);
|
||
|
|
const paddingNeeded = Math.max(0, effectiveMinHeight - truncatedLines.length - (isTruncated ? 1 : 0));
|
||
|
|
const lines = paddingNeeded > 0 ? [...truncatedLines, ...Array(paddingNeeded).fill("")] : truncatedLines;
|
||
|
|
const contentWidth = Math.max(minWidth, ...lines.map(_temp));
|
||
|
|
const boxWidth = Math.min(contentWidth + 4, effectiveMaxWidth);
|
||
|
|
const innerWidth = boxWidth - 4;
|
||
|
|
let t6;
|
||
|
|
if ($[15] !== boxWidth) {
|
||
|
|
t6 = BOX_CHARS.horizontal.repeat(boxWidth - 2);
|
||
|
|
$[15] = boxWidth;
|
||
|
|
$[16] = t6;
|
||
|
|
} else {
|
||
|
|
t6 = $[16];
|
||
|
|
}
|
||
|
|
const topBorder = `${BOX_CHARS.topLeft}${t6}${BOX_CHARS.topRight}`;
|
||
|
|
let t7;
|
||
|
|
if ($[17] !== boxWidth) {
|
||
|
|
t7 = BOX_CHARS.horizontal.repeat(boxWidth - 2);
|
||
|
|
$[17] = boxWidth;
|
||
|
|
$[18] = t7;
|
||
|
|
} else {
|
||
|
|
t7 = $[18];
|
||
|
|
}
|
||
|
|
bottomBorder = `${BOX_CHARS.bottomLeft}${t7}${BOX_CHARS.bottomRight}`;
|
||
|
|
truncationBar = isTruncated ? (() => {
|
||
|
|
const hiddenCount = contentLines.length - effectiveMaxLines;
|
||
|
|
const label = `${BOX_CHARS.horizontal.repeat(3)} \u2702 ${BOX_CHARS.horizontal.repeat(3)} ${hiddenCount} lines hidden `;
|
||
|
|
const labelWidth = stringWidth(label);
|
||
|
|
const fillWidth = Math.max(0, boxWidth - 2 - labelWidth);
|
||
|
|
return `${BOX_CHARS.teeLeft}${label}${BOX_CHARS.horizontal.repeat(fillWidth)}${BOX_CHARS.teeRight}`;
|
||
|
|
})() : null;
|
||
|
|
T0 = Box;
|
||
|
|
t3 = "column";
|
||
|
|
if ($[19] !== topBorder) {
|
||
|
|
t4 = <Text dimColor={true}>{topBorder}</Text>;
|
||
|
|
$[19] = topBorder;
|
||
|
|
$[20] = t4;
|
||
|
|
} else {
|
||
|
|
t4 = $[20];
|
||
|
|
}
|
||
|
|
let t8;
|
||
|
|
if ($[21] !== innerWidth) {
|
||
|
|
t8 = (line_0, index) => {
|
||
|
|
const lineWidth = stringWidth(line_0);
|
||
|
|
const displayLine = lineWidth > innerWidth ? sliceAnsi(line_0, 0, innerWidth) : line_0;
|
||
|
|
const padding = " ".repeat(Math.max(0, innerWidth - stringWidth(displayLine)));
|
||
|
|
return <Box key={index} flexDirection="row"><Text dimColor={true}>{BOX_CHARS.vertical} </Text><Ansi>{displayLine}</Ansi><Text dimColor={true}>{padding} {BOX_CHARS.vertical}</Text></Box>;
|
||
|
|
};
|
||
|
|
$[21] = innerWidth;
|
||
|
|
$[22] = t8;
|
||
|
|
} else {
|
||
|
|
t8 = $[22];
|
||
|
|
}
|
||
|
|
t5 = lines.map(t8);
|
||
|
|
$[4] = effectiveMaxLines;
|
||
|
|
$[5] = effectiveMaxWidth;
|
||
|
|
$[6] = minHeight;
|
||
|
|
$[7] = minWidth;
|
||
|
|
$[8] = rendered;
|
||
|
|
$[9] = T0;
|
||
|
|
$[10] = bottomBorder;
|
||
|
|
$[11] = t3;
|
||
|
|
$[12] = t4;
|
||
|
|
$[13] = t5;
|
||
|
|
$[14] = truncationBar;
|
||
|
|
} else {
|
||
|
|
T0 = $[9];
|
||
|
|
bottomBorder = $[10];
|
||
|
|
t3 = $[11];
|
||
|
|
t4 = $[12];
|
||
|
|
t5 = $[13];
|
||
|
|
truncationBar = $[14];
|
||
|
|
}
|
||
|
|
let t6;
|
||
|
|
if ($[23] !== truncationBar) {
|
||
|
|
t6 = truncationBar && <Text color="warning">{truncationBar}</Text>;
|
||
|
|
$[23] = truncationBar;
|
||
|
|
$[24] = t6;
|
||
|
|
} else {
|
||
|
|
t6 = $[24];
|
||
|
|
}
|
||
|
|
let t7;
|
||
|
|
if ($[25] !== bottomBorder) {
|
||
|
|
t7 = <Text dimColor={true}>{bottomBorder}</Text>;
|
||
|
|
$[25] = bottomBorder;
|
||
|
|
$[26] = t7;
|
||
|
|
} else {
|
||
|
|
t7 = $[26];
|
||
|
|
}
|
||
|
|
let t8;
|
||
|
|
if ($[27] !== T0 || $[28] !== t3 || $[29] !== t4 || $[30] !== t5 || $[31] !== t6 || $[32] !== t7) {
|
||
|
|
t8 = <T0 flexDirection={t3}>{t4}{t5}{t6}{t7}</T0>;
|
||
|
|
$[27] = T0;
|
||
|
|
$[28] = t3;
|
||
|
|
$[29] = t4;
|
||
|
|
$[30] = t5;
|
||
|
|
$[31] = t6;
|
||
|
|
$[32] = t7;
|
||
|
|
$[33] = t8;
|
||
|
|
} else {
|
||
|
|
t8 = $[33];
|
||
|
|
}
|
||
|
|
return t8;
|
||
|
|
}
|
||
|
|
function _temp(line) {
|
||
|
|
return stringWidth(line);
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIlN1c3BlbnNlIiwidXNlIiwidXNlTWVtbyIsInVzZVNldHRpbmdzIiwidXNlVGVybWluYWxTaXplIiwic3RyaW5nV2lkdGgiLCJBbnNpIiwiQm94IiwiVGV4dCIsInVzZVRoZW1lIiwiQ2xpSGlnaGxpZ2h0IiwiZ2V0Q2xpSGlnaGxpZ2h0UHJvbWlzZSIsImFwcGx5TWFya2Rvd24iLCJzbGljZUFuc2kiLCJQcmV2aWV3Qm94UHJvcHMiLCJjb250ZW50IiwibWF4TGluZXMiLCJtaW5IZWlnaHQiLCJtaW5XaWR0aCIsIm1heFdpZHRoIiwiQk9YX0NIQVJTIiwidG9wTGVmdCIsInRvcFJpZ2h0IiwiYm90dG9tTGVmdCIsImJvdHRvbVJpZ2h0IiwiaG9yaXpvbnRhbCIsInZlcnRpY2FsIiwidGVlTGVmdCIsInRlZVJpZ2h0IiwiUHJldmlld0JveCIsInByb3BzIiwiJCIsIl9jIiwic2V0dGluZ3MiLCJzeW50YXhIaWdobGlnaHRpbmdEaXNhYmxlZCIsInQwIiwiUHJldmlld0JveFdpdGhIaWdobGlnaHQiLCJTeW1ib2wiLCJmb3IiLCJoaWdobGlnaHQiLCJ0MSIsIlByZXZpZXdCb3hCb2R5IiwidW5kZWZpbmVkIiwiY29sdW1ucyIsInRlcm1pbmFsV2lkdGgiLCJ0aGVtZSIsImVmZmVjdGl2ZU1heFdpZHRoIiwiZWZmZWN0aXZlTWF4TGluZXMiLCJ0MiIsInJlbmRlcmVkIiwiVDAiLCJib3R0b21Cb3JkZXIiLCJ0MyIsInQ0IiwidDUiLCJ0cnVuY2F0aW9uQmFyIiwiY29udGVudExpbmVzIiwic3BsaXQiLCJpc1RydW5jYXRlZCIsImxlbmd0aCIsInRydW5jYXRlZExpbmVzIiwic2xpY2UiLCJlZmZlY3RpdmVNaW5IZWlnaHQiLCJNYXRoIiwibWluIiwicGFkZGluZ05lZWRlZCIsIm1heCIsImxpbmVzIiwiQXJyYXkiLCJmaWxsIiwiY29udGVudFdpZHRoIiwibWFwIiwiX3RlbXAiLCJib3hXaWR0aCIsImlubmVyV2lkdGgiLCJ0NiIsInJlcGVhdCIsInRvcEJvcmRlciIsInQ3IiwiaGlkZGVuQ291bnQiLCJsYWJlbCIsImxhYmVsV2lkdGgiLCJmaWxsV2lkdGgiLCJ0OCIsImxpbmVfMCIsImluZGV4IiwibGluZVdpZHRoIiwibGluZSIsImRpc3BsYXlMaW5lIiwicGFkZGluZyJdLCJzb3VyY2VzIjpbIlByZXZpZXdCb3gudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwgeyBTdXNwZW5zZSwgdXNlLCB1c2VNZW1vIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyB1c2VTZXR0aW5ncyB9IGZyb20gJy4uLy4uLy4uL2hvb2tzL3VzZVNldHRpbmdzLmpzJ1xuaW1wb3J0IHsgdXNlVGVybWluYWxTaXplIH0gZnJvbSAnLi4vLi4vLi4vaG9va3MvdXNlVGVybWluYWxTaXplLmpzJ1xuaW1wb3J0IHsgc3RyaW5nV2lkdGggfSBmcm9tICcuLi8uLi8uLi9pbmsvc3RyaW5nV2lkdGguanMnXG5pbXBvcnQgeyBBbnNpLCBCb3gsIFRleHQsIHVzZVRoZW1lIH0gZnJvbSAnLi4vLi4vLi4vaW5rLmpzJ1xuaW1wb3J0IHtcbiAgdHlwZSBDbGlIaWdobGlnaHQsXG4gIGdldENsaUhpZ2hsaWdodFByb21pc2UsXG59IGZyb20gJy4uLy4uLy4uL3V0aWxzL2NsaUhpZ2hsaWdodC5qcydcbmltcG9ydCB7IGFwcGx5TWFya2Rvd24gfSBmcm9tICcuLi8uLi8uLi91dGlscy9tYXJrZG93bi5qcydcbmltcG9ydCBzbGljZUFuc2kgZnJvbSAnLi4vLi4vLi4vdXRpbHMvc2xpY2VBbnNpLmpzJ1xuXG50eXBlIFByZXZpZXdCb3hQcm9wcyA9IHtcbiAgLyoqIFRoZSBwcmV2aWV3IGNvbnRlbnQgdG8gZGlzcGxheS4gTWFya2Rvd24gaXMgcmVuZGVyZWQgd2l0aCBzeW50YXggaGlnaGxpZ2h0aW5nXG4gICAqIGZvciBjb2RlIGJsb2NrcyAoYGBgdHMsIGBgYHB5LCBldGMuKS4gQWxzbyBzdXBwb3J0cyBwbGFpbiBtdWx0aS1saW5lIHRleHQuICovXG4gIGNvbnRlbnQ6IHN0cmluZ1xuICAvKiogTWF4aW11bSBudW1iZXIgb2YgbGluZXMgdG8gZGlzcGxheSBiZWZvcmUgdHJ1bmNhdGluZy4gQGRlZmF1bHQgMjAgKi9cbiAgbWF4TGluZXM/OiBudW1iZXJcbiAgLyoqIE1pbmltdW0gaGVpZ2h0IChpbiBsaW5lcykgZm9yIHRoZSBwcmV2aWV3IGJveC4gQ29udGVudCB3aWxsIGJlIHBhZGRlZCBpZiBzaG9ydGVyLiAqL1xuICBtaW5IZWlnaHQ/OiBudW1iZXJcbiAgLyoqIE1pbmltdW0gd2lkdGggZm9yIHRoZSBwcmV2aWV3IGJveC4gQGRlZmF1bHQgNDAgKi9cbiAgbWluV2lkdGg/OiBudW1iZXJcbiAgLyoqIE1heGltdW0gd2lkdGggYXZhaWxhYmxlIGZvciB0aGlzIGJveCAoZS5nLiwgdGhlIGNvbnRhaW5lciB3aWR0aCkuICovXG4gIG1heFdpZHRoPzogbnVtYmVyXG59XG5cbmNvbnN0IEJPWF9DSEFSUyA9IHtcbiAgdG9wTGVmdDogJ+KUjCcsXG4gIHRvcFJpZ2h0OiAn4pSQJyxcbiAgYm90dG9tTGVmdDogJ+KUlCcsXG4gIGJvdHRvbVJpZ2h0OiAn4pSYJyxcbiAgaG9yaXpvbnRhbDogJ+KUgCcsXG4gIHZlcnRpY2FsOiAn4pSCJyxcbiAgdGVlTGVmdDogJ+KUnCcsXG4gIHRlZVJpZ2h0OiAn4pSkJyxcbn1cblxuLyoqXG4gKiBBIGJvcmRlcmVkIG1vbm9zcGFjZSBib3ggZm9yIGRpc3BsYXlpbmcgcHJldmlldyBjb250ZW50LlxuICogVHJ1bmNhdGVzIGNvbnRlbnQgdGhhdCBleGNlZWRzIG1heExpbmVzIHdpdGggYW4gaW5kaWNhdG9yLlxuICogVGhlIHBhcmVudCBjb21wb25lbnQgc2hvdWxkIHBhc3MgbWF4TGluZXMgYmFzZWQgb24gaXRzIGF2YWlsYWJsZSBoZWlnaHQgYnVkZ2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gUHJldmlld0JveChwcm9wczogUHJldmlld0JveFByb3BzKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgY29uc3Qgc2V0dGluZ3MgPSB1c2VTZXR0aW5ncygpXG4gIGlmIChzZXR0aW5ncy5zeW50YXhIaWdobGlnaHRpbmdEaXNhYmxlZCkge1xuICAgIHJldHVybiA8UHJldmlld0JveEJvZHkgey4uLnByb3BzfSBoaWdobGlnaHQ9e251bGx9IC8+XG4gIH1cbiAgcmV0dXJuIChcbiAgICA8U3VzcGVuc2UgZmFsbGJhY2s9ezxQcmV2aWV3Qm94Qm9keSB7Li4ucHJvcHN9IGhpZ2hsaWdodD17bnVsbH0gLz59PlxuICAgICAgPFByZXZpZXdCb3hXaXRoSGlnaGxpZ2h0IHsuLi5wcm9wc30gLz5cbiAgICA8L1N1c3BlbnNlPlxuICApXG59XG5cbmZ1bmN0aW9uIFByZXZpZXdCb3hXaXRoSGlnaGxpZ2h0KHByb3B
|