import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import { format } from 'date-fns'; import type { TFunction } from 'i18next'; import type { ReactElement } from 'react'; /** * Commit data structure matching react-git-log's Commit type. */ interface CommitData { hash: string; message: string; committerDate: string; author?: { name?: string; email?: string; }; files?: string[]; } /** * Props for CustomGitTooltip component. * Based on the react-git-log CustomTooltipProps interface. */ interface CustomGitTooltipProps { /** * Details of the commit that is being hovered over. */ commit: CommitData; /** * The brighter, border colour of the commit based on the current theme. */ borderColour: string; /** * The darker, background colour of the commit based on the current theme. */ backgroundColour: string; /** * Translation function passed from parent component to avoid hook usage in conditionally rendered component. */ t: TFunction; } /** * Custom tooltip component for git commit nodes. * Displays file count, file names, and commit date instead of hash. * * Note: This component cannot use hooks like useTranslation because it's rendered * conditionally (only when hovering), which would violate React's Rules of Hooks. * The translation function is passed as a prop instead. */ export function CustomGitTooltip({ commit, borderColour, backgroundColour, t }: CustomGitTooltipProps): ReactElement { const files = commit.files ?? []; const fileCount = files.length; // Show first 3 files const displayFiles = files.slice(0, 3); const hasMoreFiles = fileCount > 3; // Format the commit date const commitDate = commit.committerDate ? new Date(commit.committerDate) : null; const formattedDate = commitDate ? format(commitDate, 'yyyy-MM-dd HH:mm:ss') : t('GitLog.UnknownDate'); return ( {/* Commit Message */} {commit.message} {/* Commit Date */} {formattedDate} {/* File Count */} 0 ? '4px' : 0, opacity: 0.85, }} > {fileCount === 0 ? t('GitLog.NoFilesChanged') : t('GitLog.FilesChanged', { count: fileCount })} {/* File Names */} {displayFiles.length > 0 && ( {displayFiles.map((file, index) => { const fileName = file.split('/').pop() || file; return ( {fileName} ); })} {hasMoreFiles && ( {t('GitLog.AndMoreFiles', { count: fileCount - 3 })} )} )} ); }