import { MessageCircle, Trash2 } from "lucide-react"; import { useLayoutEffect, useRef, useState, type ReactNode } from "react"; import { Button } from "~/components/ui/button"; import { Textarea } from "~/components/ui/textarea"; import { isCommentSubmitShortcut } from "./commentSubmitShortcut"; interface DiffCommentSecondaryAction { readonly label: string; readonly icon?: ReactNode; readonly allowEmpty?: boolean; readonly onAction: (text: string) => void; } interface DiffCommentAnnotationProps { kind: "draft" | "comment"; rangeLabel: string; text: string; onTextChange?: (text: string) => void; onCancel: () => void; onComment: (text: string) => void; onDelete?: () => void; placeholder?: string; submitLabel?: string; pending?: boolean; secondaryAction?: DiffCommentSecondaryAction; focusOnMount?: boolean; } /** The shared inline comment treatment for file previews, thread diffs, and pull-request diffs. */ export function DiffCommentAnnotation({ kind, rangeLabel, text, onTextChange, onCancel, onComment, onDelete, placeholder = "Add a comment…", submitLabel = "Comment", pending = false, secondaryAction, focusOnMount = true, }: DiffCommentAnnotationProps) { const [localDraftText, setLocalDraftText] = useState(""); const displayedText = kind === "draft" && !onTextChange ? localDraftText : text; const trimmedText = displayedText.trim(); const textareaRef = useRef(null); useLayoutEffect(() => { if (kind !== "draft" || !focusOnMount) return; const frame = window.requestAnimationFrame(() => { textareaRef.current?.focus({ preventScroll: true }); }); return () => window.cancelAnimationFrame(frame); }, [focusOnMount, kind]); if (kind === "comment") { return (
event.stopPropagation()} >
); } return (
event.stopPropagation()} >