File Diff
beui/file-diffFreeComponent
A syntax-highlighted file change disclosure with progressive rows, line numbers, live change counts, smooth following, and completion collapse.
Install it
npx shadcn@latest add https://beui.dev/r/file-diff.jsonSource
1"use client";2// beui.dev/components/agents/file-diff34import {5 Check,6 ChevronDown,7 Copy,8 FileCode2,9 LoaderCircle,10} from "lucide-react";11import { motion, useReducedMotion } from "motion/react";12import {13 type ReactNode,14 useCallback,15 useEffect,16 useId,17 useLayoutEffect,18 useRef,19 useState,20} from "react";21import {22 type AgentCodeLanguage,23 AgentCodeLine,24 useAgentCodeTokens,25} from "@/components/agents/agent-code";26import { AgentDisclosure } from "@/components/agents/agent-disclosure";27import { SPRING_PRESS, SPRING_SWAP } from "@/lib/ease";28import { cn } from "@/lib/utils";2930export type FileDiffStatus = "streaming" | "complete";31export type FileDiffLineType = "added" | "removed" | "context";3233export interface FileDiffLine {34 id: string;35 type?: FileDiffLineType;36 oldLine?: number;37 newLine?: number;38 content: string;39}4041export interface FileDiffProps {42 file: ReactNode;43 lines: FileDiffLine[];44 status?: FileDiffStatus;45 open?: boolean;46 defaultOpen?: boolean;47 onOpenChange?: (open: boolean) => void;48 collapseOnComplete?: boolean;49 maxHeight?: number;50 language?: AgentCodeLanguage;51 copyText?: string;52 onCopy?: () => void | Promise<void>;53 className?: string;54}5556function ChangeCount({ value, type }: { value: number; type: "added" | "removed" }) {57 if (!value) return null;58 return (59 <span60 className={cn(61 "font-mono text-xs tabular-nums",62 type === "added"63 ? "text-emerald-600 dark:text-emerald-400"64 : "text-rose-600 dark:text-rose-400",65 )}66 >67 {type === "added" ? "+" : "−"}68 {value}69 </span>70 );71}7273export function FileDiff({74 file,75 lines,76 status = "streaming",77 open,78 defaultOpen = true,79 onOpenChange,80 collapseOnComplete = true,81 maxHeight = 220,82 language = "typescript",83 copyText,84 onCopy,85 className,86}: FileDiffProps) {87 const reduce = useReducedMotion() ?? false;88 const baseId = useId();89 const triggerId = `${baseId}-trigger`;90 const contentId = `${baseId}-content`;91 const viewportRef = useRef<HTMLDivElement>(null);92 const previousStatus = useRef(status);93 const copyTimer = useRef<number | undefined>(undefined);94 const [copied, setCopied] = useState(false);95 const [internalOpen, setInternalOpen] = useState(defaultOpen);96 const currentOpen = open ?? internalOpen;97 const streaming = status === "streaming";98 const additions = lines.filter((line) => line.type === "added").length;99// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Swap Bluraction-swap-blur | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Cascadeaction-swap-cascade | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Rollaction-swap-roll | beui | Components | Free | 3 deps · 4 files | |
| Agent Activityagent-activity | beui | Components | Free | 4 deps · 9 files | |
| Agent Loading States Agent Progressagent-progress | beui | Components | Free | 3 deps · 3 files | |
| AI Sidebarai-sidebar | beui | Components | Free | 4 deps · 5 files | |
| Animated Badgeanimated-badge | beui | Components | Free | 4 deps · 3 files | |
| Number Animation Animated Numberanimated-number | beui | Components | Free | 3 deps · 3 files |
