| import React, { memo, useState } from 'react'; | |
| import { AlertCircle } from 'lucide-react'; | |
| import { icons } from '~/hooks/Endpoint/Icons'; | |
| export const URLIcon = memo( | |
| ({ | |
| iconURL, | |
| altName, | |
| containerStyle = { width: 20, height: 20 }, | |
| imageStyle = { width: '100%', height: '100%' }, | |
| className = 'icon-md mr-1 shrink-0 overflow-hidden rounded-full', | |
| endpoint, | |
| }: { | |
| iconURL: string; | |
| altName?: string | null; | |
| className?: string; | |
| containerStyle?: React.CSSProperties; | |
| imageStyle?: React.CSSProperties; | |
| endpoint?: string; | |
| }) => { | |
| const [imageError, setImageError] = useState(false); | |
| const handleImageError = () => { | |
| setImageError(true); | |
| }; | |
| const DefaultIcon: React.ElementType = | |
| endpoint && icons[endpoint] ? icons[endpoint]! : icons.unknown!; | |
| if (imageError || !iconURL) { | |
| return ( | |
| <div className="relative" style={{ ...containerStyle, margin: '2px' }}> | |
| <div className={className}> | |
| <DefaultIcon endpoint={endpoint} context="menu-item" size={containerStyle.width} /> | |
| </div> | |
| {imageError && iconURL && ( | |
| <div | |
| className="absolute flex items-center justify-center rounded-full bg-red-500" | |
| style={{ width: '14px', height: '14px', top: 0, right: 0 }} | |
| > | |
| <AlertCircle size={10} className="text-white" /> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className={className} style={containerStyle}> | |
| <img | |
| src={iconURL} | |
| alt={altName ?? 'Icon'} | |
| style={imageStyle} | |
| className="object-cover" | |
| onError={handleImageError} | |
| loading="lazy" | |
| decoding="async" | |
| width={Number(containerStyle.width) || 20} | |
| height={Number(containerStyle.height) || 20} | |
| /> | |
| </div> | |
| ); | |
| }, | |
| ); | |
| URLIcon.displayName = 'URLIcon'; | |