my-multiplayer-app / components /EnhancedColorPicker.tsx
Jaimodiji's picture
Sync all client files to fix build
e1753d8 verified
import { useEffect, useRef, useState } from 'react'
// Declare iro for TypeScript
declare global {
interface Window {
iro: any
}
}
interface EnhancedColorPickerProps {
color: string
onChange: (color: string) => void
label?: string
}
export function EnhancedColorPicker({ color, onChange, label }: EnhancedColorPickerProps) {
const [isOpen, setIsOpen] = useState(false)
const [currentColor, setCurrentColor] = useState(color)
const containerRef = useRef<HTMLDivElement>(null)
const pickerRef = useRef<any>(null)
const pickerInstanceRef = useRef<any>(null)
useEffect(() => {
setCurrentColor(color)
if (pickerInstanceRef.current) {
pickerInstanceRef.current.color.hexString = color
}
}, [color])
useEffect(() => {
if (isOpen && pickerRef.current && !pickerInstanceRef.current) {
// Load iro.js if not already loaded
if (!window.iro) {
const script = document.createElement('script')
script.src = 'https://cdn.jsdelivr.net/npm/@jaames/iro@5'
script.onload = () => initializePicker()
document.head.appendChild(script)
} else {
initializePicker()
}
}
return () => {
if (pickerInstanceRef.current) {
// Cleanup if needed
}
}
}, [isOpen])
const initializePicker = () => {
if (pickerRef.current && window.iro && !pickerInstanceRef.current) {
pickerInstanceRef.current = new window.iro.ColorPicker(pickerRef.current, {
width: 200,
color: currentColor,
layout: [
{
component: window.iro.ui.Wheel,
options: {}
},
{
component: window.iro.ui.Slider,
options: {
sliderType: 'value'
}
}
]
})
pickerInstanceRef.current.on('color:change', (color: any) => {
setCurrentColor(color.hexString)
onChange(color.hexString)
})
}
}
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
setIsOpen(false)
}
}
if (isOpen) {
document.addEventListener('mousedown', handleClickOutside)
return () => document.removeEventListener('mousedown', handleClickOutside)
}
}, [isOpen])
return (
<div ref={containerRef} style={{ position: 'relative' }}>
{label && (
<div style={{
fontSize: '10px',
marginBottom: '4px',
color: 'var(--color-text-2)',
fontWeight: 600,
textTransform: 'uppercase'
}}>
{label}
</div>
)}
<button
onClick={() => setIsOpen(!isOpen)}
style={{
width: '100%',
height: '32px',
border: '1px solid var(--color-divider)',
borderRadius: 'var(--radius-small)',
background: 'var(--color-low)',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '8px',
padding: '0 8px'
}}
>
<div
style={{
width: '20px',
height: '20px',
borderRadius: '4px',
background: currentColor,
border: '1px solid var(--color-divider)',
flexShrink: 0
}}
/>
<span style={{
fontSize: '11px',
fontFamily: 'monospace',
color: 'var(--color-text)',
flex: 1,
textAlign: 'left'
}}>
{currentColor}
</span>
</button>
{isOpen && (
<div
style={{
position: 'absolute',
top: '100%',
left: 0,
marginTop: '4px',
background: 'var(--color-panel)',
border: '1px solid var(--color-divider)',
borderRadius: 'var(--radius-medium)',
padding: '12px',
boxShadow: 'var(--shadow-3)',
zIndex: 1000,
backdropFilter: 'blur(20px)'
}}
onClick={(e) => e.stopPropagation()}
>
<div ref={pickerRef} />
</div>
)}
</div>
)
}