UNPKG

capsule-ai-cli

Version:

The AI Model Orchestrator - Intelligent multi-model workflows with device-locked licensing

141 lines 6.51 kB
import React, { useMemo } from 'react'; import { Box, Text, useStdout } from 'ink'; import SelectInput from 'ink-select-input'; import chalk from 'chalk'; import { diffLines as diffLinesLib } from 'diff'; export const EditConfirmation = ({ filePath, oldContent, newContent, onConfirm, onCancel }) => { const { stdout } = useStdout(); const boxWidth = useMemo(() => { const terminalWidth = stdout.columns || 80; return Math.min(terminalWidth - 6, 100); }, []); const changeSummary = useMemo(() => { const diff = diffLinesLib(oldContent, newContent); let added = 0; let removed = 0; diff.forEach((part) => { const lines = part.value.split('\n'); if (lines.length > 0 && lines[lines.length - 1] === '') { lines.pop(); } if (part.added) added += lines.length; else if (part.removed) removed += lines.length; }); return { added, removed }; }, [oldContent, newContent]); const diffLineElements = useMemo(() => { const diff = diffLinesLib(oldContent, newContent); let oldLineNumber = 1; let newLineNumber = 1; const elements = []; const contextLines = 3; diff.forEach((part, index) => { const lines = part.value.split('\n'); if (lines.length > 0 && lines[lines.length - 1] === '') { lines.pop(); } if (part.added || part.removed) { lines.forEach((line, lineIndex) => { if (part.added) { const lineNum = newLineNumber.toString().padStart(3); elements.push(React.createElement(Box, { key: `${index}-${lineIndex}-added`, width: "100%" }, React.createElement(Text, null, chalk.gray(lineNum), " ", chalk.green('+'), " ", line))); newLineNumber++; } else { const lineNum = oldLineNumber.toString().padStart(3); elements.push(React.createElement(Box, { key: `${index}-${lineIndex}-removed`, width: "100%" }, React.createElement(Text, null, chalk.gray(lineNum), " ", chalk.red('-'), " ", line))); oldLineNumber++; } }); } else { const isNearChange = (lineIdx) => { const prevPart = index > 0 ? diff[index - 1] : null; const nextPart = index < diff.length - 1 ? diff[index + 1] : null; if (prevPart && (prevPart.added || prevPart.removed) && lineIdx < contextLines) { return true; } if (nextPart && (nextPart.added || nextPart.removed) && lineIdx >= lines.length - contextLines) { return true; } return false; }; let hiddenShown = false; lines.forEach((line, lineIndex) => { const lineNum = newLineNumber.toString().padStart(3); if (isNearChange(lineIndex)) { elements.push(React.createElement(Box, { key: `${index}-${lineIndex}-context`, width: "100%" }, React.createElement(Text, null, chalk.gray(lineNum), " ", line))); hiddenShown = false; } else if (!hiddenShown && lineIndex > contextLines && lineIndex < lines.length - contextLines) { elements.push(React.createElement(Box, { key: `${index}-${lineIndex}-hidden`, width: "100%" }, React.createElement(Text, null, chalk.gray('...'), " ", chalk.dim(`// ${lines.length - 2 * contextLines} lines hidden`)))); hiddenShown = true; } oldLineNumber++; newLineNumber++; }); } }); return elements; }, [oldContent, newContent, boxWidth]); const items = [ { label: chalk.green('✓ Apply this edit'), value: 'apply' }, { label: chalk.red('✗ Cancel this edit'), value: 'cancel' } ]; const handleSelect = (item) => { switch (item.value) { case 'apply': onConfirm(); break; case 'cancel': onCancel(); break; } }; const displayPath = useMemo(() => { if (filePath.length > boxWidth - 8) { return '...' + filePath.substring(filePath.length - (boxWidth - 11)); } return filePath; }, [filePath, boxWidth]); const maxHeight = useMemo(() => { const terminalHeight = stdout.rows || 24; return Math.max(10, Math.floor(terminalHeight * 0.6)); }, [stdout.rows]); return (React.createElement(Box, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, width: boxWidth }, React.createElement(Box, { marginBottom: 1, flexDirection: "column" }, React.createElement(Text, null, chalk.gray('└'), " Updated ", chalk.bold(displayPath), " with ", chalk.green(`${changeSummary.added} additions`), " and ", chalk.red(`${changeSummary.removed} removals`))), React.createElement(Box, { flexDirection: "column", marginBottom: 1, height: maxHeight - 6, overflow: "hidden" }, React.createElement(Box, { flexDirection: "column", height: maxHeight - 8 }, diffLineElements.slice(0, Math.min(diffLineElements.length, maxHeight - 10)))), React.createElement(SelectInput, { items: items, onSelect: handleSelect }))); }; //# sourceMappingURL=EditConfirmation.js.map