'use client'; import { ComponentProps, ReactNode, RefObject, useState } from 'react'; import LabeledIcon, { LabeledIconType } from '../primitives/LabeledIcon'; import Badge from '../Badge'; import { clsx } from 'clsx/lite'; import LinkWithStatus from '../LinkWithStatus'; import Spinner from '../Spinner'; import ResponsiveText from '../primitives/ResponsiveText'; import { SHOW_CATEGORY_IMAGE_HOVERS } from '@/app/config'; import EntityHover from './EntityHover'; import { getPhotosCachedAction } from '@/photo/actions'; import { PhotoQueryOptions } from '@/photo/db'; import { MAX_PHOTOS_TO_SHOW_PER_CATEGORY } from '@/image-response'; export interface EntityLinkExternalProps { ref?: RefObject type?: LabeledIconType badged?: boolean contrast?: ComponentProps['contrast'] uppercase?: boolean prefetch?: boolean suppressSpinner?: boolean className?: string countOnHover?: number showHover?: boolean hoverPhotoQueryOptions?: PhotoQueryOptions } export default function EntityLink({ ref, icon, iconBadgeStart, iconBadgeEnd, label, labelSmall, iconWide, type, badged, contrast = 'medium', path = '', // Make link optional for debugging purposes showHover = SHOW_CATEGORY_IMAGE_HOVERS, countOnHover, hoverPhotoQueryOptions, prefetch, title, action, truncate = true, className, classNameIcon, uppercase, suppressSpinner, debug, }: { icon: ReactNode iconBadgeStart?: ReactNode iconBadgeEnd?: ReactNode label: string labelSmall?: ReactNode iconWide?: boolean path?: string prefetch?: boolean title?: string action?: ReactNode truncate?: boolean className?: string classNameIcon?: string uppercase?: boolean debug?: boolean } & EntityLinkExternalProps) { const [isLoading, setIsLoading] = useState(false); const hasBadgeIcon = Boolean(iconBadgeStart || iconBadgeEnd); const classForContrast = () => { switch (contrast) { case 'low': return 'text-dim'; case 'high': return 'text-main'; case 'frosted': return 'text-black'; default: return 'text-medium'; } }; const showHoverEntity = !isLoading && countOnHover && !showHover; const renderLabel = {label} ; const renderLink = (useForHover?: boolean) => {badged && !useForHover ? {iconBadgeStart} {renderLabel} {iconBadgeEnd} : {renderLabel} } ; return ( {showHover && countOnHover && hoverPhotoQueryOptions ? getPhotosCachedAction({ ...hoverPhotoQueryOptions, limit: MAX_PHOTOS_TO_SHOW_PER_CATEGORY, })} color={contrast === 'frosted' ? 'frosted' : undefined} > {renderLink()} : renderLink()} {action && {action} } {showHoverEntity && {countOnHover} } {isLoading && !suppressSpinner && } ); }