color opacity
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-07-08 09:21:41 +03:30
parent 3c764a1652
commit a2a591420c
25 changed files with 178 additions and 62 deletions
+51 -3
View File
@@ -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} />