/** Trump card drawn in SVG (no image assets). Big corner index for readability on PC and phones. */ import type { CSSProperties } from 'react'; const SUIT_SYMBOL: Record = { S: '♠', H: '♥', D: '◆', C: '♣' }; const SUIT_KO: Record = { S: '스페이드', H: '하트', D: '다이아', C: '클로버' }; const RANK_LABEL: Record = { T: '10', J: 'J', Q: 'Q', K: 'K', A: 'A' }; const FACE_KO: Record = { J: '잭', Q: '퀸', K: '킹', A: '에이스' }; export type CardSize = 'sm' | 'md' | 'lg'; const WIDTH: Record = { sm: 44, md: 64, lg: 88 }; export interface PlayingCardProps { /** e.g. "AS", "TD", "X1" (joker). null = face down. */ card: string | null; size?: CardSize; selected?: boolean; dimmed?: boolean; highlight?: boolean; onClick?: () => void; title?: string; style?: CSSProperties; /** Colour-blind friendly: 4-colour suits. */ fourColor?: boolean; } export function cardAria(card: string | null): string { if (!card) return '뒤집힌 카드'; if (card.startsWith('X')) return '조커'; const r = card[0]!; return `${SUIT_KO[card[1]!]} ${FACE_KO[r] ?? RANK_LABEL[r] ?? r}`; } export function PlayingCard({ card, size = 'md', selected, dimmed, highlight, onClick, title, style, fourColor }: PlayingCardProps) { const w = WIDTH[size]; const h = Math.round(w * 1.4); const lift = selected ? -Math.round(w * 0.22) : 0; const common: CSSProperties = { width: w, height: h, flex: 'none', transform: `translateY(${lift}px)`, transition: 'transform 0.12s ease', cursor: onClick ? 'pointer' : 'default', opacity: dimmed ? 0.45 : 1, filter: highlight ? 'drop-shadow(0 0 6px #f59e0b)' : 'drop-shadow(0 1px 2px rgba(0,0,0,0.25))', ...style, }; const Tag = onClick ? 'button' : 'span'; const btnReset: CSSProperties = onClick ? { padding: 0, border: 0, background: 'none' } : {}; if (!card) { return ( ); } const joker = card.startsWith('X'); const suit = card[1]!; const rank = card[0]!; const color = joker ? card === 'X1' ? '#111827' : '#dc2626' : fourColor ? { S: '#111827', H: '#dc2626', D: '#2563eb', C: '#15803d' }[suit]! : suit === 'H' || suit === 'D' ? '#dc2626' : '#111827'; const label = joker ? '★' : (RANK_LABEL[rank] ?? rank); const sym = joker ? '' : SUIT_SYMBOL[suit]; return ( {label} {sym} {joker ? ( JOKER ) : 'JQK'.includes(rank) ? ( <> {rank} ) : ( {sym} )} ); }