/** * ExportDropdown - Download icon button with dropdown for exporting session data. * * Supports three formats: Markdown (.md), JSON (.json), Plain Text (.txt). * Follows the same close-on-outside-click / Escape patterns as RepositoryDropdown. */ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { triggerDownload } from '@renderer/utils/sessionExporter'; import { Braces, Download, FileText, Type } from 'lucide-react'; import type { SessionDetail } from '@renderer/types/data'; import type { ExportFormat } from '@renderer/utils/sessionExporter'; interface ExportDropdownProps { sessionDetail: SessionDetail; } interface FormatOption { format: ExportFormat; label: string; icon: React.ComponentType<{ className?: string }>; ext: string; } const FORMAT_OPTIONS: FormatOption[] = [ { format: 'markdown', label: 'Markdown', icon: FileText, ext: '.md' }, { format: 'json', label: 'JSON', icon: Braces, ext: '.json' }, { format: 'plaintext', label: 'Plain Text', icon: Type, ext: '.txt' }, ]; export const ExportDropdown = ({ sessionDetail, }: Readonly): React.JSX.Element => { const [isOpen, setIsOpen] = useState(false); const [buttonHover, setButtonHover] = useState(false); const [hoveredFormat, setHoveredFormat] = useState(null); const containerRef = useRef(null); // Close on outside click useEffect(() => { if (!isOpen) return; const handleClickOutside = (event: MouseEvent): void => { if (containerRef.current && !containerRef.current.contains(event.target as Node)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, [isOpen]); // Close on Escape useEffect(() => { if (!isOpen) return; const handleEscape = (event: KeyboardEvent): void => { if (event.key === 'Escape') { setIsOpen(false); } }; document.addEventListener('keydown', handleEscape); return () => document.removeEventListener('keydown', handleEscape); }, [isOpen]); const handleExport = useCallback( (format: ExportFormat) => { triggerDownload(sessionDetail, format); setIsOpen(false); }, [sessionDetail] ); return (
{/* Trigger button */} {/* Dropdown menu */} {isOpen && (
{/* Header */}
Export Session
{/* Format options */} {FORMAT_OPTIONS.map((option) => ( ))}
)}
); };