import React from 'react'; import { useI18n } from '@/utils/chromeI18n'; import { cn } from '@/lib/utils'; import JsonTree from './JsonTree'; import type { DiffNode, DiffResult as DiffResultType, DiffType, ViewMode } from './types'; // 💡 顶层 Interface 继承原生 HTML 容器属性,扩展灵活性 export interface DiffResultProps extends React.HTMLAttributes { result: DiffResultType; viewMode: ViewMode; activePath?: string; } export default function DiffResult({ result, viewMode, activePath, className, ...props }: DiffResultProps) { const { t } = useI18n('jsonDiff'); if (viewMode === 'sideBySide') { return (
); } return ( /* 1. 单栏拍平视图容器: - 对齐 shadcn 规范,使用 bg-card、border-border 隔离。 - 注入 tabular-nums 配合 font-mono,消灭任何行高和字符抖动。 */
); } const SectionLabel = ({ text }: { text: string }) => ( {text} ); const formatPrimitive = (v: unknown): string => { if (v === undefined) return 'undefined'; if (v === null) return 'null'; if (typeof v === 'string') return JSON.stringify(v); if (typeof v === 'number' || typeof v === 'boolean') return String(v); return JSON.stringify(v); }; const isContainerType = (v: unknown): boolean => (typeof v === 'object' && v !== null) || Array.isArray(v); const prefixForType = (type: DiffType): string => { if (type === 'added') return '+'; if (type === 'removed') return '-'; if (type === 'modified') return '~'; return ' '; }; // 2. 状态色彩超进化: // 拒绝硬编码实色系,全部换用高度安全的语义色变体与暗黑模式自适应。 const typeThemeMap = { added: { text: 'text-emerald-600 dark:text-emerald-400', bg: 'bg-emerald-500/5 dark:bg-emerald-500/10', }, removed: { text: 'text-destructive', bg: 'bg-destructive/5 dark:bg-destructive/10', }, modified: { text: 'text-amber-600 dark:text-amber-400', bg: 'bg-amber-500/5 dark:bg-amber-500/10', }, unchanged: { text: 'text-foreground/80', bg: 'bg-transparent', }, }; interface UnifiedViewProps { node: DiffNode; depth: number; activePath?: string; } const UnifiedView = ({ node, depth, activePath }: UnifiedViewProps) => { const isRoot = depth === 0; const hasChildren = Array.isArray(node.children) && node.children.length > 0; const isContainer = hasChildren || isContainerType(node.oldValue) || isContainerType(node.newValue); const keyLabel = isRoot ? '' : `${node.key}: `; if (!isContainer) { if (node.type === 'modified') { return ( <> ); } const value = node.type === 'added' ? node.newValue : node.oldValue; return ( ); } // 容器节点整块渲染处理 if (node.type === 'added') { return ( ); } if (node.type === 'removed') { return ( ); } const isArr = Array.isArray(node.oldValue) || Array.isArray(node.newValue); const open = isArr ? '[' : '{'; const close = isArr ? ']' : '}'; return ( <> {node.children?.map((child) => ( ))} ); }; interface UnifiedRowProps { depth: number; type: DiffType; text: string; active?: boolean; multiline?: boolean; } const UnifiedRow = ({ depth, type, text, active, multiline }: UnifiedRowProps) => { // 3. 高精度提取状态样式映射 const currentTheme = typeThemeMap[type] || typeThemeMap.unchanged; return (
{/* 5. 前缀标识:等宽锁定,强行占据 w-5 并让符号居中对齐,达成 VSCode 般的整洁排版 */} {prefixForType(type)} {text}
); }; const stringifyMultiline = (v: unknown, depth: number): string => { try { const json = JSON.stringify(v, null, 2); if (!json) return formatPrimitive(v); const indent = ' '.repeat(depth); return json .split('\n') .map((line, idx) => (idx === 0 ? line : indent + line)) .join('\n'); } catch { return formatPrimitive(v); } }; // 💡 彻底移除了文件底部引发 TS2484 冲突的 export type { DiffResultProps } 声明