Skip to content

Commit 8c7e497

Browse files
committed
feat(color-hue): add reverse prop and performance optimizations #202
- Add reverse prop to flip hue progression direction (similar to color-alpha) - Fix vertical mode drag interaction logic for proper color mapping - Optimize performance with useCallback and useMemo for gradient functions - Improve color gradient calculation for both horizontal and vertical modes
1 parent a42b00a commit 8c7e497

2 files changed

Lines changed: 84 additions & 13 deletions

File tree

packages/color-hue/README.md

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,53 @@ npm i @uiw/react-color-hue
6060

6161
```jsx mdx:preview
6262
import React, { useState } from 'react';
63+
import { hsvaToRgbaString } from '@uiw/color-convert';
6364
import Hue from '@uiw/react-color-hue';
6465

6566
export default function Demo() {
66-
const [hsva, setHsva] = useState({ h: 0, s: 0, v: 68, a: 1 });
67+
const [hsva, setHsva] = useState({ "h":0,"s":100,"v":100,"a":1 });
6768
return (
68-
<Hue
69-
hue={hsva.h}
70-
onChange={(newHue) => {
71-
setHsva({ ...hsva, ...newHue });
72-
}}
73-
/>
69+
<>
70+
<div style={{ display: "flex", gap: 10, flexDirection: "column", paddingBottom: 20 }}>
71+
<Hue
72+
hue={hsva.h}
73+
onChange={(newHue) => {
74+
setHsva({ ...hsva, ...newHue });
75+
}}
76+
/>
77+
<Hue
78+
hue={hsva.h}
79+
reverse={true}
80+
onChange={(newHue) => {
81+
setHsva({ ...hsva, ...newHue });
82+
}}
83+
/>
84+
</div>
85+
<div style={{ display: "flex", gap: 10, flexDirection: "row" }}>
86+
<Hue
87+
hue={hsva.h}
88+
direction="vertical"
89+
width={16}
90+
height={120}
91+
onChange={(newHue) => {
92+
setHsva({ ...hsva, ...newHue });
93+
}}
94+
/>
95+
<Hue
96+
hue={hsva.h}
97+
direction="vertical"
98+
reverse={true}
99+
width={16}
100+
height={120}
101+
onChange={(newHue) => {
102+
setHsva({ ...hsva, ...newHue });
103+
}}
104+
/>
105+
</div>
106+
<div style={{ background: hsvaToRgbaString(hsva), marginTop: 30, padding: 10 }}>
107+
{JSON.stringify(hsva)}
108+
</div>
109+
</>
74110
);
75111
}
76112
```

packages/color-hue/src/index.tsx

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,60 @@
1-
import React from 'react';
1+
import React, { useCallback, useMemo } from 'react';
22
import Alpha, { AlphaProps } from '@uiw/react-color-alpha';
33

4+
const NORMAL_COLORS =
5+
'rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%';
6+
const REVERSED_COLORS =
7+
'rgb(255, 0, 0) 0%, rgb(255, 0, 255) 17%, rgb(0, 0, 255) 33%, rgb(0, 255, 255) 50%, rgb(0, 255, 0) 67%, rgb(255, 255, 0) 83%, rgb(255, 0, 0) 100%';
8+
49
export interface HueProps extends Omit<AlphaProps, 'hsva' | 'onChange'> {
510
onChange?: (newHue: { h: number }) => void;
611
hue?: number;
712
}
813

914
const Hue = React.forwardRef<HTMLDivElement, HueProps>((props, ref) => {
10-
const { prefixCls = 'w-color-hue', className, hue = 0, onChange, direction = 'horizontal', ...other } = props;
15+
const { prefixCls = 'w-color-hue', className, hue = 0, onChange, direction = 'horizontal', reverse = false, ...other } = props;
16+
17+
const getGradientBackground = useCallback(() => {
18+
if (direction === 'horizontal') {
19+
const colors = reverse ? REVERSED_COLORS : NORMAL_COLORS;
20+
const gradientDirection = 'right';
21+
return `linear-gradient(to ${gradientDirection}, ${colors})`;
22+
} else {
23+
// 垂直模式下,由于交互逻辑使用了 1-value,所以渐变颜色也要反转
24+
const colors = reverse ? NORMAL_COLORS : REVERSED_COLORS;
25+
const gradientDirection = 'bottom';
26+
return `linear-gradient(to ${gradientDirection}, ${colors})`;
27+
}
28+
}, [direction, reverse]);
29+
30+
const getHueFromInteraction = useCallback(
31+
(interaction: any) => {
32+
const value = direction === 'horizontal' ? interaction.left : interaction.top;
33+
let normalizedValue;
34+
if (direction === 'horizontal') {
35+
normalizedValue = reverse ? 1 - value : value;
36+
} else {
37+
// 垂直模式下,正常情况下顶部应该是0,底部是360,所以需要反转
38+
normalizedValue = reverse ? value : 1 - value;
39+
}
40+
return 360 * normalizedValue;
41+
},
42+
[direction, reverse],
43+
);
44+
45+
const gradientBackground = useMemo(() => getGradientBackground(), [getGradientBackground]);
46+
1147
return (
1248
<Alpha
1349
ref={ref}
1450
className={`${prefixCls} ${className || ''}`}
1551
{...other}
1652
direction={direction}
17-
background={`linear-gradient(to ${
18-
direction === 'horizontal' ? 'right' : 'bottom'
19-
}, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%)`}
53+
reverse={reverse}
54+
background={gradientBackground}
2055
hsva={{ h: hue, s: 100, v: 100, a: hue / 360 }}
2156
onChange={(_, interaction) => {
22-
onChange && onChange({ h: direction === 'horizontal' ? 360 * interaction.left : 360 * interaction.top });
57+
onChange && onChange({ h: getHueFromInteraction(interaction) });
2358
}}
2459
/>
2560
);

0 commit comments

Comments
 (0)