caro5 / client /src /components /SymbolPicker.tsx
Pedro de Carvalho
Add dragon icons
0a5fd27
Raw
History Blame Contribute Delete
5.64 kB
import { useState } from 'react'
import { theme } from '../theme.ts'
import { isImageSymbol, imageSymbolUrl } from '../binAssets'
interface Props {
current: string
onSelect: (symbol: string) => void
onClose: () => void
}
type Category = 'classic' | 'hearts' | 'emojis' | 'letters' | 'dragons'
const CATEGORIES: { id: Category; label: string }[] = [
{ id: 'classic', label: 'Classic' },
{ id: 'hearts', label: 'Hearts' },
{ id: 'emojis', label: 'Emojis' },
{ id: 'letters', label: 'Letters' },
{ id: 'dragons', label: 'Dragons' },
]
const SYMBOLS: Record<Category, string[]> = {
classic: ['X', 'O', 'โ—', 'โ—‹', 'โ˜…', 'โ˜†', 'โ™ ', 'โ™ฅ', 'โ™ฆ', 'โ™ฃ', 'โšซ', 'โšช', '๐Ÿ”ต', '๐Ÿ”ด'],
hearts: ['โค๏ธ', '๐Ÿงก', '๐Ÿ’›', '๐Ÿ’š', '๐Ÿ’™', '๐Ÿ’œ', '๐Ÿ–ค', '๐Ÿค', '๐ŸคŽ', '๐Ÿ’', '๐Ÿ’–', '๐Ÿ’—'],
emojis: [
'๐Ÿ˜€', '๐Ÿ˜', '๐Ÿคฉ', '๐Ÿ˜Ž', '๐Ÿ˜‚', '๐Ÿฅณ', '๐Ÿคฏ', '๐Ÿ˜ˆ', '๐Ÿ‘ป', '๐Ÿ‘ฝ',
'๐Ÿ˜บ', '๐Ÿ˜ป', '๐Ÿค–', '๐Ÿฅท', '๐Ÿง™', '๐Ÿงš', '๐Ÿง›', '๐Ÿฆธ', '๐Ÿฆน', '๐Ÿงž',
'๐Ÿš€', 'โญ', '๐ŸŒŸ', '๐ŸŽฏ', '๐Ÿ”ฅ', '๐Ÿ’Ž', '๐Ÿ†', '๐Ÿ‘‘', '๐ŸŽฎ', '๐ŸŽฒ',
'๐Ÿ›ธ', '๐Ÿ›ฐ๏ธ', '๐ŸŒŒ', '๐Ÿช', 'โ˜„๏ธ', '๐ŸŒ ', '๐ŸŒƒ', '๐Ÿ”ญ', '๐Ÿงญ', 'โš”๏ธ',
'๐Ÿฑ', '๐Ÿถ', '๐ŸฆŠ', '๐Ÿผ', '๐Ÿฆ„', '๐Ÿธ', '๐Ÿจ', '๐Ÿฒ', '๐Ÿฌ', '๐Ÿฆ‹',
'๐Ÿ‰', '๐Ÿฆ', '๐Ÿฏ', '๐Ÿบ', '๐Ÿฆ…', '๐Ÿฆ‰', '๐Ÿข', '๐Ÿฆ–', '๐Ÿฆ•', '๐Ÿ',
'๐ŸŒˆ', 'โšก', '๐Ÿ€', '๐ŸŒบ', '๐ŸŒธ', '๐ŸŒป', '๐ŸŒ', '๐ŸŒ™', 'โ˜€๏ธ', 'โ„๏ธ',
'๐ŸŒฒ', '๐ŸŒณ', '๐Ÿ„', '๐ŸŒฟ', '๐Ÿ', '๐ŸŒŠ', '๐Ÿ’ง', '๐Ÿชจ', '๐Ÿชต', '๐Ÿชท',
'๐Ÿ•', '๐Ÿ”', '๐ŸŒฎ', '๐Ÿฉ', '๐Ÿช', '๐Ÿ‰', '๐Ÿ‡', '๐Ÿ“',
'๐Ÿ’', '๐Ÿ‘', '๐Ÿ', '๐Ÿฅ', '๐Ÿฅจ', '๐Ÿœ', '๐Ÿฃ', '๐Ÿ™',
'โšฝ', '๐Ÿ€', '๐ŸŽธ', '๐ŸŽน', '๐ŸŽจ', '๐ŸŽญ', '๐Ÿ“ท', '๐Ÿ’ก',
'๐Ÿน', '๐Ÿฅ', '๐ŸŽบ', '๐ŸŽง', '๐ŸŽช', '๐ŸŽฌ', '๐Ÿ•น๏ธ', '๐Ÿงธ',
'โ™ ๏ธ', 'โ™ฅ๏ธ', 'โ™ฆ๏ธ', 'โ™ฃ๏ธ', 'โ™Ÿ๏ธ', '๐ŸŽฐ', '๐Ÿ”ฎ', '๐Ÿ—๏ธ',
'๐Ÿ›ก๏ธ', '๐Ÿ—ก๏ธ', '๐Ÿ’ฐ', '๐Ÿ’ฃ', '๐Ÿงจ', '๐Ÿช™', '๐Ÿต๏ธ', '๐ŸŽ–๏ธ',
'๐Ÿ’ช', '๐Ÿง ', '๐Ÿ‘€', '๐Ÿซถ', '๐Ÿค', '๐ŸŽ€', '๐Ÿงฉ', '๐Ÿช„',
'โœจ', '๐Ÿ’ซ', '๐Ÿ’ฅ', '๐Ÿ’ค', '๐ŸŒ€', '๐Ÿงฟ', 'โ™พ๏ธ', 'โœ…',
],
letters: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
dragons: Array.from({ length: 20 }, (_, i) => `img:dragon-icons/dragon${i + 1}.png`),
}
export default function SymbolPicker({ current, onSelect, onClose }: Props) {
const [category, setCategory] = useState<Category>('classic')
const symbols = SYMBOLS[category]
return (
<div
style={{
position: 'fixed', inset: 0, zIndex: 100,
display: 'flex', alignItems: 'center', justifyContent: 'center',
background: 'rgba(0,0,0,0.5)',
animation: 'fadeIn 0.15s ease',
}}
onClick={onClose}
>
<div
style={{
background: theme.bgStr,
border: `1px solid ${theme.border}`,
borderRadius: 12,
padding: '1.25rem',
width: 'min(340px, 85vw)',
}}
onClick={(e) => e.stopPropagation()}
>
<span style={{
color: theme.text, fontWeight: 600, fontSize: '1rem',
display: 'block', marginBottom: '0.75rem',
}}>
Choose Your Symbol
</span>
<div style={{
display: 'flex', gap: '0.4rem', marginBottom: '0.75rem',
}}>
{CATEGORIES.map((cat) => (
<button
key={cat.id}
onClick={() => setCategory(cat.id)}
style={{
flex: 1,
padding: '0.35rem 0.25rem',
fontSize: '0.75rem',
fontWeight: 600,
cursor: 'pointer',
background: category === cat.id ? theme.player1Str : theme.bgPanel,
color: category === cat.id ? '#fff' : theme.textMuted,
border: category === cat.id ? `1px solid ${theme.player1Str}` : `1px solid ${theme.border}`,
borderRadius: 6,
transition: 'all 0.15s ease',
whiteSpace: 'nowrap',
}}
>
{cat.label}
</button>
))}
</div>
<div style={{
display: 'flex', flexWrap: 'wrap', gap: '0.6rem',
justifyContent: 'center',
maxHeight: 220,
overflowY: 'auto',
}}>
{symbols.map((s) => {
const isImg = isImageSymbol(s)
return (
<button
key={s}
onClick={() => { onSelect(s); onClose() }}
style={{
display: 'flex', alignItems: 'center', justifyContent: 'center',
width: 48, height: 48,
background: s === current ? theme.player1Str : theme.bgPanel,
border: s === current ? `2px solid ${theme.player1Str}` : `1px solid ${theme.border}`,
borderRadius: 8,
cursor: 'pointer',
fontSize: category === 'letters' ? '1.1rem' : '1.3rem',
color: s === current ? '#fff' : theme.text,
transition: 'all 0.15s ease',
flexShrink: 0,
padding: isImg ? 4 : 0,
}}
title={s}
>
{isImg ? (
<img
src={imageSymbolUrl(s)}
alt=""
style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }}
/>
) : s}
</button>
)
})}
</div>
</div>
</div>
)
}