Spaces:
Build error
Build error
File size: 7,236 Bytes
6a059d3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | import React, { useMemo } from "react"
import ReactDiffViewer, { DiffMethod } from "react-diff-viewer-continued"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { GitCompare, ArrowRight } from "lucide-react"
import { GithubDiff } from "./types"
interface LegalDiffViewerProps {
diff: GithubDiff
className?: string
}
export function LegalDiffViewer({ diff, className }: LegalDiffViewerProps) {
// Calculate percentage/number change for the badge
const changeBadge = useMemo(() => {
try {
// Extract numbers from old and new text
const oldNumbers = diff.old_text.match(/(\d+(\.\d+)?)/g)?.map(Number) || []
const newNumbers = diff.new_text.match(/(\d+(\.\d+)?)/g)?.map(Number) || []
// Simple heuristic: if we find one number in each that changed
if (oldNumbers.length === 1 && newNumbers.length === 1) {
const oldVal = oldNumbers[0]
const newVal = newNumbers[0]
if (oldVal !== newVal) {
const percentChange = ((newVal - oldVal) / oldVal) * 100
const isIncrease = newVal > oldVal
return {
text: `${isIncrease ? "+" : ""}${percentChange.toFixed(1)}% ${isIncrease ? "Increase" : "Decrease"}`,
variant: isIncrease ? "destructive" : "default" as "default" | "destructive" | "outline" | "secondary",
color: isIncrease ? "bg-red-600" : "bg-green-600" // Higher taxes (increase) usually bad/red, lower good/green? Or just standard diff colors?
// Let's stick to standard: Green = Increase, Red = Decrease for numbers usually,
// BUT for taxes: Increase = Bad (Red), Decrease = Good (Green).
// Let's just use neutral or standard diff colors to avoid bias.
// For the badge, let's just show the change.
}
}
}
// Check for specific keywords like "increased from X to Y"
// This is handled by the diff view itself visually, but a badge is nice.
return null
} catch (e) {
return null
}
}, [diff.old_text, diff.new_text])
// Custom styles for react-diff-viewer-2 to match Kenyan flag theme
// Red (#B91C1C) for deleted, Green (#16A34A) for added
const newStyles = {
variables: {
light: {
diffViewerBackground: "transparent",
diffViewerColor: "currentColor",
addedBackground: "rgba(22, 163, 74, 0.2)", // Green #16A34A
addedColor: "currentColor",
removedBackground: "rgba(185, 28, 28, 0.2)", // Red #B91C1C
removedColor: "currentColor",
wordAddedBackground: "rgba(22, 163, 74, 0.4)",
wordRemovedBackground: "rgba(185, 28, 28, 0.4)",
addedGutterBackground: "rgba(22, 163, 74, 0.1)",
removedGutterBackground: "rgba(185, 28, 28, 0.1)",
gutterBackground: "transparent",
gutterBackgroundDark: "transparent",
highlightBackground: "rgba(255, 255, 255, 0.1)",
highlightGutterBackground: "rgba(255, 255, 255, 0.1)",
codeFoldGutterBackground: "transparent",
codeFoldBackground: "transparent",
emptyLineBackground: "transparent",
gutterColor: "currentColor",
addedGutterColor: "currentColor",
removedGutterColor: "currentColor",
codeFoldContentColor: "currentColor",
diffViewerTitleBackground: "transparent",
diffViewerTitleColor: "currentColor",
diffViewerTitleBorderColor: "transparent",
},
dark: {
diffViewerBackground: "transparent",
diffViewerColor: "currentColor",
addedBackground: "rgba(22, 163, 74, 0.2)", // Green
addedColor: "currentColor",
removedBackground: "rgba(185, 28, 28, 0.2)", // Red
removedColor: "currentColor",
wordAddedBackground: "rgba(22, 163, 74, 0.4)",
wordRemovedBackground: "rgba(185, 28, 28, 0.4)",
addedGutterBackground: "rgba(22, 163, 74, 0.1)",
removedGutterBackground: "rgba(185, 28, 28, 0.1)",
gutterBackground: "transparent",
gutterBackgroundDark: "transparent",
highlightBackground: "rgba(255, 255, 255, 0.1)",
highlightGutterBackground: "rgba(255, 255, 255, 0.1)",
codeFoldGutterBackground: "transparent",
codeFoldBackground: "transparent",
emptyLineBackground: "transparent",
gutterColor: "currentColor",
addedGutterColor: "currentColor",
removedGutterColor: "currentColor",
codeFoldContentColor: "currentColor",
diffViewerTitleBackground: "transparent",
diffViewerTitleColor: "currentColor",
diffViewerTitleBorderColor: "transparent",
}
},
line: {
padding: '10px 2px',
'&:hover': {
background: 'rgba(255, 255, 255, 0.05)',
},
},
content: {
fontFamily: 'inherit',
fontSize: '0.9rem',
}
}
return (
<Card className={`w-full overflow-hidden border-primary/20 bg-card/50 backdrop-blur-sm ${className}`}>
<CardHeader className="pb-2 border-b border-border/50 bg-muted/30">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="p-2 rounded-lg bg-primary/10 text-primary">
<GitCompare className="w-5 h-5" />
</div>
<div>
<CardTitle className="text-base font-bold text-primary flex items-center gap-2">
{diff.title}
</CardTitle>
</div>
</div>
{changeBadge && (
<Badge variant={changeBadge.variant} className={`${changeBadge.color} text-white border-0`}>
{changeBadge.text}
</Badge>
)}
</div>
</CardHeader>
<CardContent className="p-0 overflow-x-auto">
<div className="min-w-[500px] text-sm">
{/* We force dark mode styles if the app is in dark mode, but react-diff-viewer-2
uses a 'useDarkTheme' prop. We can try to detect or just pass true/false.
For now, let's assume the app handles theme via class 'dark'.
Since we can't easily detect system preference here without hooks,
we'll rely on the parent passing a theme or default to light/dark based on CSS variables.
Actually, react-diff-viewer-2 styles object handles both light and dark keys,
but we need to tell it which one to use.
*/}
<ReactDiffViewer
oldValue={diff.old_text}
newValue={diff.new_text}
splitView={diff.highlight_type === "side_by_side"}
compareMethod={DiffMethod.WORDS}
styles={newStyles}
useDarkTheme={true} // Force dark theme styles for now as they look better in both modes with our transparent bg
leftTitle="Original Text"
rightTitle="Amended Text"
/>
</div>
</CardContent>
</Card>
)
}
|