add component color picker

This commit is contained in:
hamid zarghami
2025-11-22 15:17:38 +03:30
parent 8b98f47bd5
commit 9eadbb568b
4 changed files with 134 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+102
View File
@@ -0,0 +1,102 @@
import { type FC, type InputHTMLAttributes, useState, useRef, useEffect } from 'react'
import { clx } from '../helpers/utils'
import Error from './Error'
import ColorfilterIcon from '@/assets/images/color.png'
type Props = {
label?: string
className?: string
error_text?: string
isNotRequired?: boolean
value?: string
onChange?: (value: string) => void
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value'>
const ColorPicker: FC<Props> = (props: Props) => {
const [color, setColor] = useState<string>(props.value || '#000000')
const colorInputRef = useRef<HTMLInputElement>(null)
const inputClass = clx(
'w-full bg-white h-10 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>) => {
const newColor = event.target.value
setColor(newColor)
props.onChange?.(newColor)
}
const handleTextChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value
if (/^#[0-9A-Fa-f]{0,6}$/.test(value) || value === '') {
const finalColor = value || '#000000'
setColor(finalColor)
props.onChange?.(finalColor)
}
}
const handleColorIconClick = () => {
if (!props.readOnly) {
colorInputRef.current?.click()
}
}
useEffect(() => {
if (props.value !== undefined) {
setColor(props.value)
}
}, [props.value])
return (
<div className='w-full'>
<label className='text-sm'>
{props.label}
</label>
<div className='w-full relative mt-1'>
<input
type='text'
value={color}
onChange={handleTextChange}
placeholder='#000000'
readOnly={props.readOnly}
className={inputClass}
/>
<button
type='button'
onClick={handleColorIconClick}
disabled={props.readOnly}
className={clx(
'absolute top-0 bottom-0 my-auto left-3 cursor-pointer',
props.readOnly && 'cursor-not-allowed opacity-50'
)}
>
<img src={ColorfilterIcon} alt='color-filter' className='size-7' />
</button>
<div
className='absolute top-0 bottom-0 my-auto right-3 w-5 h-5 rounded-full'
style={{ backgroundColor: color }}
/>
<input
ref={colorInputRef}
type='color'
value={color}
onChange={handleColorChange}
className='absolute opacity-0 pointer-events-none w-0 h-0'
/>
{props.error_text && (
<Error errorText={props.error_text} />
)}
</div>
</div>
)
}
export default ColorPicker
+25
View File
@@ -0,0 +1,25 @@
import ColorPicker from '@/components/ColorPicker'
import Input from '@/components/Input'
import { type FC } from 'react'
const GeneralSettings: FC = () => {
return (
<div className='bg-white rounded-4xl p-8'>
<div className='text-lg font-light'>
تنظیمات عمومی
</div>
<div className='mt-8 rowTwoInput'>
<Input
label='نام رستوران'
/>
<ColorPicker
label='رنگ منو'
/>
</div>
</div>
)
}
export default GeneralSettings
+7
View File
@@ -2,6 +2,7 @@ import Tabs from '@/components/Tabs'
import { Card, KeySquare, Setting4, TruckFast } from 'iconsax-react'
import { useState, type FC } from 'react'
import { SettingTabEnum } from './enum/Enum'
import GeneralSettings from './GeneralSettings'
const Setting: FC = () => {
@@ -39,6 +40,12 @@ const Setting: FC = () => {
active={activeTab}
/>
</div>
<div className='mt-8'>
{
activeTab === SettingTabEnum.GENERAL && <GeneralSettings />
}
</div>
</div>
)
}