import type { Attachment } from "@assistant-ui/react"; import * as PopoverPrimitive from "@radix-ui/react-popover"; import { IconClipboardText, IconX } from "@tabler/icons-react"; import { useCallback, useEffect, useState } from "react"; import { cn } from "../utils.js"; import { countLines, unwrapAttachmentEnvelope } from "./pasted-text.js"; function readAttachmentText(attachment: Attachment): Promise | string { if ("file" in attachment && attachment.file instanceof File) { return attachment.file.text(); } const textPart = attachment.content?.find( (p): p is { type: "text"; text: string } => p.type === "text" && "text" in p && typeof p.text === "string", ); return textPart ? unwrapAttachmentEnvelope(textPart.text) : ""; } function usePastedAttachmentText(attachment: Attachment): { text: string; lines: number; chars: number; } { const [text, setText] = useState(""); useEffect(() => { let cancelled = false; const result = readAttachmentText(attachment); if (typeof result === "string") { setText(result); return; } result .then((value) => { if (!cancelled) setText(value); }) .catch(() => {}); return () => { cancelled = true; }; }, [attachment]); return { text, lines: countLines(text), chars: text.length }; } export interface PastedTextChipProps { attachment: Attachment; onRemove?: (id: string) => void; /** Compact variant rendered inside sent user messages. */ compact?: boolean; } export function PastedTextChip({ attachment, onRemove, compact = false, }: PastedTextChipProps) { const [open, setOpen] = useState(false); const { text, lines, chars } = usePastedAttachmentText(attachment); const handleRemove = useCallback( (event: React.MouseEvent) => { event.stopPropagation(); onRemove?.(attachment.id); }, [attachment.id, onRemove], ); const summary = lines > 0 ? `${lines} lines` : `${chars} chars`; return (
Pasted text {lines} lines ยท {chars} chars
            {text}
          
); }