88 lines
2.1 KiB
TypeScript
88 lines
2.1 KiB
TypeScript
'use client'
|
|
|
|
import * as React from 'react'
|
|
import { HexColorPicker } from 'react-colorful'
|
|
import { cn } from '@/utils/cn'
|
|
import { Input } from '@/components/ui/input'
|
|
|
|
interface ColorPickerProps {
|
|
color: string
|
|
onChange: (color: string) => void
|
|
presets?: string[]
|
|
className?: string
|
|
}
|
|
|
|
const defaultPresets = [
|
|
'#171412',
|
|
'#2E241C',
|
|
'#8A6742',
|
|
'#B79267',
|
|
'#D0B08C',
|
|
'#E8DFD1',
|
|
'#FFFDF8',
|
|
'#8F7CFF',
|
|
'#45D4FF',
|
|
'#FF78B8',
|
|
'#48D7C2',
|
|
'#FFB86B',
|
|
]
|
|
|
|
export function ColorPicker({
|
|
color,
|
|
onChange,
|
|
presets = defaultPresets,
|
|
className,
|
|
}: ColorPickerProps) {
|
|
const [inputValue, setInputValue] = React.useState(color)
|
|
|
|
React.useEffect(() => {
|
|
setInputValue(color)
|
|
}, [color])
|
|
|
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const val = e.target.value
|
|
setInputValue(val)
|
|
if (/^#[0-9A-F]{3,6}$/i.test(val)) {
|
|
onChange(val)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={cn('flex flex-col gap-3 w-[200px]', className)}>
|
|
<HexColorPicker
|
|
color={color}
|
|
onChange={onChange}
|
|
className="!w-full !h-[120px]"
|
|
/>
|
|
<div className="flex flex-row items-center gap-2">
|
|
<label className="text-[10px] font-medium text-muted-foreground uppercase w-8">
|
|
Hex
|
|
</label>
|
|
<Input
|
|
value={inputValue}
|
|
onChange={handleInputChange}
|
|
className="h-7 text-[10px] font-mono px-2"
|
|
/>
|
|
</div>
|
|
{presets.length > 0 && (
|
|
<div className="grid grid-cols-6 gap-1.5 pt-2 border-t border-border">
|
|
{presets.map((p) => (
|
|
<button
|
|
key={p}
|
|
type="button"
|
|
className={cn(
|
|
'w-5 h-5 rounded-sm border border-black/5 cursor-pointer transition-all hover:scale-110 active:scale-95',
|
|
color.toLowerCase() === p.toLowerCase() &&
|
|
'ring-2 ring-primary ring-offset-1'
|
|
)}
|
|
style={{ backgroundColor: p }}
|
|
onClick={() => onChange(p)}
|
|
title={p}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|