Files
2026FIFAWorldCup/platform/web/components/TransparentImage.tsx

72 lines
2.2 KiB
TypeScript

'use client';
import React, { useState, useEffect } from 'react';
import Image, { ImageProps } from 'next/image';
interface TransparentImageProps extends Omit<ImageProps, 'src'> {
src: string;
alt: string;
teamOrBrandName?: string;
theme?: 'light' | 'dark'; // bg-stone-50 vs bg-stone-900
}
/**
* 字串過濾器 (String Formatter)
* 確保專有名詞的大小寫與字元間距嚴格對齊
*/
export const formatBrandName = (name: string) => {
return name.toUpperCase().replace(/\s+/g, ' ').trim();
};
export default function TransparentImage({
src,
alt,
teamOrBrandName,
theme = 'dark',
className = '',
...props
}: TransparentImageProps) {
const [isValidAlpha, setIsValidAlpha] = useState<boolean | null>(null);
useEffect(() => {
// 實務上這裡可以加上 Canvas 檢查,掃描圖片角落是否有典型的實體灰白棋盤格特徵
// 或者只允許載入已經過後端白名單校驗的 CDN 圖片
// 這裡我們假設 src 來自信任的 CDN 或本地 public
setIsValidAlpha(true);
}, [src]);
// 防呆機制:若檢測到無效透明度,顯示佔位符
if (isValidAlpha === false) {
return (
<div className={`flex flex-col items-center justify-center border border-quant-red border-dashed rounded ${className} p-2`}>
<span className="text-quant-red font-dotmatrix text-[10px] uppercase">Alpha Error</span>
</div>
);
}
// 移除 `mix-blend-mode` 偽裝去背,嚴格要求圖檔自帶真實 Alpha Channel
return (
<div className={`flex flex-col items-center ${className}`}>
<div className={`relative ${props.width ? `w-[${props.width}px]` : 'w-full'} ${props.height ? `h-[${props.height}px]` : 'h-full'}`}>
<Image
src={src}
alt={alt}
className="object-contain"
{...props}
/>
</div>
{teamOrBrandName && (
<span className="mt-2 text-sm font-dotmatrix tracking-widest uppercase">
{theme === 'dark' ? (
<span className="text-stone-300">{formatBrandName(teamOrBrandName)}</span>
) : (
<span className="text-stone-800">{formatBrandName(teamOrBrandName)}</span>
)}
</span>
)}
</div>
);
}