This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { type FC, type InputHTMLAttributes, useState, useRef, useEffect } from 'react'
|
||||
import { clx } from '../helpers/utils'
|
||||
import Error from './Error'
|
||||
import Input from './Input'
|
||||
|
||||
type Props = {
|
||||
label?: string
|
||||
@@ -9,17 +10,21 @@ type Props = {
|
||||
isNotRequired?: boolean
|
||||
value?: string
|
||||
onChange?: (value: string) => void
|
||||
opacity?: number
|
||||
onOpacityChange?: (value: number) => void
|
||||
opacityLabel?: string
|
||||
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value'>
|
||||
|
||||
const ColorPicker: FC<Props> = (props: Props) => {
|
||||
const [color, setColor] = useState<string>(props.value || '#000000')
|
||||
const [opacityDisplay, setOpacityDisplay] = useState<string>(`${props.opacity ?? 100}`)
|
||||
const colorInputRef = useRef<HTMLInputElement>(null)
|
||||
const pickerOpenGuardRef = useRef(false)
|
||||
const showOpacity = props.onOpacityChange !== undefined
|
||||
|
||||
const inputClass = clx(
|
||||
'w-full bg-white h-[34px] text-black block pl-10 pr-10 text-xs rounded-xl border border-border',
|
||||
props.readOnly && 'bg-gray-100 border-0 text-description',
|
||||
props.className
|
||||
)
|
||||
|
||||
const handleColorChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -53,8 +58,31 @@ const ColorPicker: FC<Props> = (props: Props) => {
|
||||
}
|
||||
}, [props.value])
|
||||
|
||||
return (
|
||||
<div className='w-full'>
|
||||
useEffect(() => {
|
||||
if (props.opacity !== undefined) {
|
||||
setOpacityDisplay(`${props.opacity}`)
|
||||
}
|
||||
}, [props.opacity])
|
||||
|
||||
const handleOpacityChange = (rawValue: string) => {
|
||||
setOpacityDisplay(rawValue)
|
||||
const numValue = parseInt(rawValue, 10)
|
||||
if (!Number.isNaN(numValue) && numValue >= 0 && numValue <= 100) {
|
||||
props.onOpacityChange?.(numValue)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpacityBlur = (rawValue: string) => {
|
||||
const numValue = parseInt(rawValue, 10) || 0
|
||||
const clampedValue = Math.min(100, Math.max(0, numValue))
|
||||
setOpacityDisplay(`${clampedValue}`)
|
||||
props.onOpacityChange?.(clampedValue)
|
||||
}
|
||||
|
||||
const colorField = (
|
||||
<div
|
||||
className={clx('w-full', showOpacity && 'flex-1')}
|
||||
>
|
||||
<label className='text-xs'>
|
||||
{props.label}
|
||||
</label>
|
||||
@@ -115,6 +143,26 @@ const ColorPicker: FC<Props> = (props: Props) => {
|
||||
className='absolute opacity-0 pointer-events-none w-0 h-0'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={clx('w-full', showOpacity && 'flex gap-3', props.className)}>
|
||||
{colorField}
|
||||
{showOpacity && (
|
||||
<div className='w-28 shrink-0'>
|
||||
<Input
|
||||
type='number'
|
||||
label={props.opacityLabel ?? 'شفافیت'}
|
||||
className='px-3'
|
||||
value={opacityDisplay}
|
||||
onChange={(e) => handleOpacityChange(e.target.value)}
|
||||
onBlur={(e) => handleOpacityBlur(e.target.value)}
|
||||
min={0}
|
||||
max={100}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.error_text && (
|
||||
<Error errorText={props.error_text} />
|
||||
|
||||
Reference in New Issue
Block a user