Skip to content

Commit

Permalink
feat: [color-picker] 新增新版颜色组件及单测
Browse files Browse the repository at this point in the history
  • Loading branch information
邵祺 authored and albyben committed Oct 31, 2024
1 parent cc0867c commit 5fbb280
Show file tree
Hide file tree
Showing 23 changed files with 1,089 additions and 384 deletions.
388 changes: 286 additions & 102 deletions components/color-picker/__tests__/__snapshots__/index.test.tsx.snap

Large diffs are not rendered by default.

314 changes: 261 additions & 53 deletions components/color-picker/__tests__/index.test.tsx

Large diffs are not rendered by default.

295 changes: 177 additions & 118 deletions components/color-picker/color-picker-panel.tsx

Large diffs are not rendered by default.

103 changes: 73 additions & 30 deletions components/color-picker/color-picker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useContext, useState, useRef, useEffect } from 'react'
import React, { FC, useContext, useState, useRef, useEffect, useCallback } from 'react'
import classNames from 'classnames'
import { ConfigContext } from '../config-provider'
import { Input } from '../index'
Expand All @@ -20,9 +20,11 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
value,
className,
style,
pure,
functionalColor,
functionalColorName,
switchName,
showAlphaInput,
showClear,
showSwitch,
showColorTransfer,
Expand All @@ -43,29 +45,45 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
onVisibleChange,
} = colorPickerProps
const [inputColorValue, setInputColorValue] = useState<string>(defaultValue || '')
const [inputCorrectColorValue, setInputCorrectColorValue] = useState<string>('')
const [correctColorValue, setCorrectColorValue] = useState<string>(defaultValue || defaultSystemColor)
const [currentColorType, setCurrentColorType] = useState<IColorTypesObj['type']>(panelFormatConfig.default)
const [colTypeArr, setColTypeArr] = useState<Array<IColorTypesObj>>(colorTypes as IColorTypesObj[])
const [showPanel, setShowPanel] = useState<boolean>(typeof visible === 'undefined' ? !!defaultOpen : !!visible)
const [alpha, setAlpha] = useState<number>(0)
const [alphaNoVerifyVal, setAlphaNoVerifyVal] = useState<string>(alpha * 100 + '%')
const [isFollow, setIsFollow] = useState<boolean>(false)
const [clickedColorIndex, setClickedColorIndex] = useState<number>()
const [clickedPresetColorIndex, setClickedPresetColorIndex] = useState<number>()
const [clickedHistoricalColorIndex, setClickedHistoricalColorIndex] = useState<number>()

const colorPickerPrefixCls = getPrefixCls!(prefixCls, 'color-picker')
const popUpLayer = getPrefixCls!(prefixCls, 'color-picker-pop')
const containerCls = classNames(`${colorPickerPrefixCls}-container`)
const containerCls = classNames(`${colorPickerPrefixCls}-container`, {
[`${colorPickerPrefixCls}-container-pure`]: pure,
})
const inputCls = classNames(`${colorPickerPrefixCls}-input`, className)
const inputRef = useRef<HTMLInputElement>(null)
const showColorPickerPanel =
showColorTransfer ||
(typeof showPresetColor === 'boolean' && showPresetColor && presetColor?.length) ||
(typeof showPresetColor === 'boolean' && showPresetColor && (presetColor?.length || systemPresetColor.length)) ||
typeof showPresetColor === 'undefined' ||
showClear ||
historicalColor?.length ||
(functionalColor?.length && showSwitch) ||
showColorPickerBox?.showBox ||
showColorPickerBox?.showHue ||
showColorPickerBox?.showOpacity

const setClickColorIndex = (value: string | number) => {
if (typeof value === 'number') {
setClickedPresetColorIndex(value)
setClickedHistoricalColorIndex(value)
} else {
setClickedPresetColorIndex(highlightPresetColorIndex(value, presetColorToHEX(presetColor || systemPresetColor)))
setClickedHistoricalColorIndex(highlightPresetColorIndex(value, presetColorToHEX(historicalColor)))
}
}

const setIconColor = (value: string) => {
value === functionalColorName ? setIsFollow(true) : setIsFollow(false)
const inpValue = value === functionalColorName ? functionalColor : value
Expand All @@ -87,28 +105,27 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
Color(getColorObj(inpValue)).alpha(),
getAlphaStr(inpValue),
)
setClickedColorIndex(
highlightPresetColorIndex(formatArr[0].value, presetColorToHEX(presetColor || systemPresetColor)),
)
setClickColorIndex(formatArr[0].value)
} else if (inpValue) {
const formatArr = colorFormat(correctColorValue) as IColorTypesObj[]
const formatArr = colorFormat(correctColorValue, alpha) as IColorTypesObj[]
setState(formatArr, correctColorValue, alpha, alphaNoVerifyVal)
} else {
const formatArr = colorFormat(defaultSystemColor) as IColorTypesObj[]
const formatArr = colorFormat(defaultSystemColor, 0) as IColorTypesObj[]
setState(formatArr, defaultSystemColor, 0, '0%')
}
}

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setClickedColorIndex(-1)
setClickColorIndex(-1)
const inpValue = e.target.value
if (!inpValue) setInputCorrectColorValue('')
if (value === undefined) {
setIconColor(inpValue)
setInputColorValue(inpValue)
}
setInputColorValue(inpValue)
const callback = (val: string, alpha: number) => {
const formatArr = colorFormat(val, alpha) as IColorTypesObj[]
onChange && onChange(inpValue, formatArr)
onChange?.(inpValue, formatArr)
}
if (validateColor(inpValue)) {
callback(inpValue, alpha)
Expand All @@ -118,21 +135,43 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
functionalColor && showSwitch && setIsFollow(false)
}

const handleBlur = (e: React.ChangeEvent<HTMLInputElement>) => {
const inpValue = e.target.value
const formatArr = colorFormat(correctColorValue, alpha) as IColorTypesObj[]
const getCurrentOutputColor = () => {
if (inputCorrectColorValue) {
return formatArr.find((item) => item.type === format)!.value
}
return ''
}
if (value === undefined) {
setIconColor(inpValue)
setInputColorValue(getCurrentOutputColor())
}
onChange?.(getCurrentOutputColor(), formatArr)
}

const handleClick = () => {
if (typeof visible === 'undefined') {
setShowPanel(!showPanel)
}
onVisibleChange && onVisibleChange(!showPanel)
}

useEffect(() => {
if (validateColor(value ?? inputColorValue)) {
setInputCorrectColorValue(value ?? inputColorValue)
}
}, [inputColorValue, value])

useEffect(() => {
if (typeof visible !== 'undefined') {
setShowPanel(visible)
}
}, [visible])

useEffect(() => {
if (value) {
if (value !== undefined) {
setIconColor(value)
} else {
if (defaultValue) {
Expand All @@ -141,45 +180,43 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
}
}, [value, defaultValue])

const afterIcon = () => {
const beforeIcon = useCallback(() => {
const afterIconContainerCls = classNames(`${colorPickerPrefixCls}-icon`, {
[`${colorPickerPrefixCls}-icon-underline`]: borderType === 'underline',
[`${colorPickerPrefixCls}-icon-bordered`]: borderType === 'bordered',
[`${colorPickerPrefixCls}-icon-up`]: showPanel,
[`${colorPickerPrefixCls}-icon-down`]: !showPanel,
})

const noneLineCls = `${colorPickerPrefixCls}-icon-no-color-line`

return (
<div
className={afterIconContainerCls}
style={{ backgroundColor: `${colTypeArr[2].value || defaultSystemColor}` }}
>
{!value && !defaultValue && !inputColorValue && <div className={noneLineCls} />}
{!validateColor(value) && !inputCorrectColorValue && <div className={noneLineCls} />}
</div>
)
}
}, [borderType, colTypeArr, colorPickerPrefixCls, inputCorrectColorValue, value])

const colorInputEle = (
<div className={containerCls} ref={inputRef}>
<Input
borderType={borderType}
borderType={pure ? 'bordered' : borderType}
placeholder={placeholder}
value={value ?? inputColorValue}
className={inputCls}
onChange={handleChange}
onBlur={handleBlur}
style={style}
onClick={handleClick}
prefix={
<div onClick={handleClick} className={`${colorPickerPrefixCls}-icon-container`}>
{(prefixIcon && prefixIcon(colTypeArr[2].value)) || afterIcon()}
{prefixIcon ? prefixIcon(colTypeArr[2].value, beforeIcon()) : beforeIcon()}
</div>
}
suffix={
suffixIcon && (
<div onClick={handleClick} className={`${colorPickerPrefixCls}-icon-container`}>
{suffixIcon(colTypeArr[2].value)}
{suffixIcon(colTypeArr[2].value, beforeIcon())}
</div>
)
}
Expand All @@ -190,6 +227,7 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
const panel = (
<ColorPickerPanel
// API
showAlphaInput={showAlphaInput}
showClear={showClear}
showSwitch={showSwitch}
showColorTransfer={showColorTransfer}
Expand All @@ -207,24 +245,29 @@ const ColorPicker: FC<Partial<IColorPickerProps>> = (props) => {
showPanel={showPanel}
onVisibleChange={onVisibleChange}
// private
setInputCorrectColorValue={setInputCorrectColorValue}
setInputColorValue={setInputColorValue}
setCorrectColorValue={setCorrectColorValue}
setClickedPresetColorIndex={setClickedPresetColorIndex}
setClickedHistoricalColorIndex={setClickedHistoricalColorIndex}
setClickColorIndex={setClickColorIndex}
setAlpha={setAlpha}
setAlphaNoVerifyVal={setAlphaNoVerifyVal}
setIsFollow={setIsFollow}
setShowPanel={setShowPanel}
setColTypeArr={setColTypeArr}
setCurrentColorType={setCurrentColorType}
correctColorValue={correctColorValue}
clickedColorIndex={clickedColorIndex}
setClickedColorIndex={setClickedColorIndex}
inputCorrectColorValue={inputCorrectColorValue}
clickedPresetColorIndex={clickedPresetColorIndex}
clickedHistoricalColorIndex={clickedHistoricalColorIndex}
onChange={onChange}
alpha={alpha}
setAlpha={setAlpha}
alphaNoVerifyVal={alphaNoVerifyVal}
setAlphaNoVerifyVal={setAlphaNoVerifyVal}
isFollow={isFollow}
setIsFollow={setIsFollow}
setShowPanel={setShowPanel}
inputRef={inputRef}
colTypeArr={colTypeArr}
setColTypeArr={setColTypeArr}
currentColorType={currentColorType}
setCurrentColorType={setCurrentColorType}
showColorPickerPanel={showColorPickerPanel}
/>
)
Expand Down
28 changes: 28 additions & 0 deletions components/color-picker/demo/color-picker-alpha.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: 透明度输入框可配置
order: 12
---

我们提供透明度输入的配置能力,可通过 showAlphaInput 控制透明度输入框的显隐

```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { ColorPicker } from '@kdcloudjs/kdesign'

const Demo: React.FC = () => {
const onChange = (inputValue: string) => {
console.log('color', inputValue)
}

return (
<>
<ColorPicker onChange={onChange} />
<br />
<ColorPicker onChange={onChange} showAlphaInput={false} />
</>
)
}

ReactDOM.render(<Demo />, mountNode)
```
4 changes: 2 additions & 2 deletions components/color-picker/demo/color-picker-controlled.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ReactDOM from 'react-dom'
import { ColorPicker, Button } from '@kdcloudjs/kdesign'

const Demo: React.FC = () => {
const [color, setColor] = React.useState<string>('#ff0000')
const [color, setColor] = React.useState<string>('#FF0000')

const onChange = (inputValue: string) => {
console.log('inputValue', inputValue)
Expand All @@ -27,7 +27,7 @@ const Demo: React.FC = () => {
<Button style={{ marginBottom: '20px' }} onClick={handleClick}>
改变颜色
</Button>
<ColorPicker onChange={onChange} value={color} showSwitch functionalColor="#0000ff" showColorPickerBox />
<ColorPicker onChange={onChange} value={color} showSwitch functionalColor="#0000FF" showColorPickerBox />
</>
)
}
Expand Down
2 changes: 1 addition & 1 deletion components/color-picker/demo/color-picker-default-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Demo: React.FC = () => {
console.log('color', inputValue)
}

return <ColorPicker onChange={onChange} defaultValue='blue' />
return <ColorPicker onChange={onChange} defaultValue="#FF0000" />
}

ReactDOM.render(<Demo />, mountNode)
Expand Down
28 changes: 28 additions & 0 deletions components/color-picker/demo/color-picker-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: 输出颜色格式可配置
order: 13
---

可以通过 format 属性对输出的颜色格式进行限制

```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { ColorPicker } from '@kdcloudjs/kdesign'

const Demo: React.FC = () => {
const onChange = (inputValue: string) => {
console.log('color', inputValue)
}

return (
<>
<ColorPicker onChange={onChange} format="HEX" />
<br />
<ColorPicker onChange={onChange} format="RGB" />
</>
)
}

ReactDOM.render(<Demo />, mountNode)
```
4 changes: 2 additions & 2 deletions components/color-picker/demo/color-picker-function-color.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ const Demo: React.FC = () => {

return (
<>
<ColorPicker onChange={onChange} functionalColor={'rgb(55, 92, 202)'} showSwitch={true} />
<ColorPicker onChange={onChange} functionalColor={'RGB(55, 92, 202)'} showSwitch={true} />
<br />
<ColorPicker
onChange={onChange}
functionalColor={'rgb(55, 92, 202)'}
functionalColor={'RGB(55, 92, 202)'}
showSwitch={true}
functionalColorName="#lightColor"
switchName={{ name: '跟随明亮色' }}
Expand Down
34 changes: 34 additions & 0 deletions components/color-picker/demo/color-picker-historical-color.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: 面板最近使用颜色可配置
order: 15
---

可以通过 historicalColor 属性在颜色面板中进行最近使用颜色的配置,最近颜色支持透明度

```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { ColorPicker } from '@kdcloudjs/kdesign'

const Demo: React.FC = () => {
const onChange = (inputValue: string) => {
console.log('color', inputValue)
}

const historicalColor = [
'blue',
'#0000FF',
'#0000FFEE',
'RGB(0,0,255)',
'RGBA(0,0,200,0.5)',
'HSL(240,100%,50%)',
'HSLA(240,100%,50%,0.5)',
'HSB(240,100%,100%)',
'HSBA(240,100%,100%,0.5)',
]

return <ColorPicker onChange={onChange} format="HEX" historicalColor={historicalColor} />
}

ReactDOM.render(<Demo />, mountNode)
```
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ReactDOM from 'react-dom'
import { ColorPicker, Button } from '@kdcloudjs/kdesign'

const Demo: React.FC = () => {
const [color, setColor] = React.useState<string>('#ff0000')
const [color, setColor] = React.useState<string>('#FF0000')
const handleClick = () => {
setColor('blue')
}
Expand All @@ -21,7 +21,7 @@ const Demo: React.FC = () => {
<Button style={{ marginBottom: '20px' }} onClick={handleClick}>
改变颜色
</Button>
<ColorPicker value={color} showSwitch functionalColor="#0000ff" showColorPickerBox />
<ColorPicker value={color} showSwitch functionalColor="#0000FF" showColorPickerBox />
</>
)
}
Expand Down
Loading

0 comments on commit 5fbb280

Please sign in to comment.