Skip to content

Commit e25f7ba

Browse files
committed
fix(wheel): align angle/direction for pointer, input and background
#139
1 parent 1052662 commit e25f7ba

4 files changed

Lines changed: 60 additions & 10 deletions

File tree

packages/color-editable-input/src/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const EditableInput = React.forwardRef<HTMLInputElement, EditableInputProps>((pr
3333
} = props;
3434
const [value, setValue] = useState<string | number | undefined>(initValue);
3535
const isFocus = useRef(false);
36+
const inputIdRef = useRef(other.id || `${prefixCls}-${Math.random().toString(36).slice(2, 11)}`);
37+
const inputId = other.id || inputIdRef.current;
3638

3739
useEffect(() => {
3840
if (props.value !== value) {
@@ -103,6 +105,7 @@ const EditableInput = React.forwardRef<HTMLInputElement, EditableInputProps>((pr
103105
autoComplete: 'off',
104106
onFocus: () => (isFocus.current = true),
105107
...other,
108+
id: inputId,
106109
style: editableStyle,
107110
onFocusCapture: (e) => {
108111
let elm = e.target as HTMLInputElement;
@@ -113,7 +116,8 @@ const EditableInput = React.forwardRef<HTMLInputElement, EditableInputProps>((pr
113116
<div className={[prefixCls, className || ''].filter(Boolean).join(' ')} style={wrapperStyle}>
114117
{renderInput ? renderInput(inputProps, ref) : <input ref={ref} {...inputProps} />}
115118
{label && (
116-
<span
119+
<label
120+
htmlFor={inputId}
117121
style={{
118122
color: 'var(--editable-input-label-color)',
119123
textTransform: 'capitalize',

packages/color-wheel/src/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,15 @@ const Wheel = React.forwardRef<HTMLDivElement, WheelProps>((props, ref) => {
4242
} = props;
4343
const hsva = (typeof color === 'string' && validHex(color) ? hexToHsva(color) : color || {}) as HsvaColor;
4444
const hex = color ? hsvaToHex(hsva) : '';
45-
const positions = getWheelHandlePosition({ width }, hsva);
45+
const wheelProps = { width, direction, angle };
46+
const positions = getWheelHandlePosition(wheelProps, hsva);
4647
const comProps = {
4748
top: '0',
4849
left: '0',
4950
color: hex,
5051
};
5152
const handleChange = (interaction: Interaction, event: MouseEvent | TouchEvent) => {
52-
const result = getWheelValueFromInput({ width }, width - interaction.x, height - interaction.y);
53+
const result = getWheelValueFromInput(wheelProps, interaction.x, interaction.y);
5354
const handleHsva = {
5455
h: result.h,
5556
s: result.s,
@@ -91,8 +92,8 @@ const Wheel = React.forwardRef<HTMLDivElement, WheelProps>((props, ref) => {
9192
style={{
9293
position: 'absolute',
9394
borderRadius: '50%',
94-
background: direction === 'anticlockwise' ? HUE_GRADIENT_CLOCKWISE : HUE_GRADIENT_ANTICLOCKWISE,
95-
transform: `rotateZ(${angle + 90}deg)`,
95+
background: direction === 'anticlockwise' ? HUE_GRADIENT_ANTICLOCKWISE : HUE_GRADIENT_CLOCKWISE,
96+
transform: `rotateZ(${90 - angle}deg)`,
9697
inset: 0,
9798
}}
9899
/>

test/editable-input.test.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,19 @@ it('EditableInput', async () => {
4545
expect(child.type).toEqual('input');
4646
}
4747
if (typeof child === 'object' && idx === 1) {
48-
expect(child.type).toEqual('span');
48+
expect(child.type).toEqual('label');
4949
}
5050
});
5151
}
5252
}
5353
});
5454

55+
it('EditableInput supports getByLabelText', async () => {
56+
render(<EditableInput label="Hex" value="#ffffff" />);
57+
const input = screen.getByLabelText('Hex');
58+
expect(input.tagName).toEqual('INPUT');
59+
});
60+
5561
it('EditableInput placement = top', async () => {
5662
function MyComponent() {
5763
const [hsva, setHsva] = useState({ h: 209, s: 36, v: 90, a: 1 });

test/wheel.test.tsx

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import React, { useState } from 'react';
55
import TestRenderer from 'react-test-renderer';
66
import { screen, render, fireEvent } from '@testing-library/react';
77
import '@testing-library/jest-dom';
8+
import { hexToHsva, hsvaToHex } from '@uiw/color-convert';
89
import {
910
getWheelDimensions,
1011
getHandleRange,
@@ -28,20 +29,25 @@ class FakeMouseEvent extends MouseEvent {
2829

2930
it('Wheel mousedown onChange', async () => {
3031
const handleChange = jest.fn((color) => color.hex);
32+
const color = '#ff7300';
33+
const hsva = hexToHsva(color);
3134
const {
3235
container: { firstChild },
33-
} = render(<Wheel color="#ff7300" onChange={handleChange} />);
36+
} = render(<Wheel color={color} onChange={handleChange} />);
3437
fireEvent(firstChild!, new FakeMouseEvent('mousedown', { pageX: 20, pageY: 1 }));
35-
expect(handleChange).toHaveReturnedWith('#ffd900');
38+
const result = getWheelValueFromInput({ width: 200, direction: 'anticlockwise', angle: 180 }, 20, 1);
39+
expect(handleChange).toHaveReturnedWith(hsvaToHex({ ...hsva, ...result }));
3640
});
3741

3842
it('Wheel color=hsvaColor ', async () => {
3943
const handleChange = jest.fn((color) => color.hex);
44+
const hsva = { h: 209, s: 36, v: 90, a: 1 };
4045
const {
4146
container: { firstChild },
42-
} = render(<Wheel color={{ h: 209, s: 36, v: 90, a: 1 }} onChange={handleChange} />);
47+
} = render(<Wheel color={hsva} onChange={handleChange} />);
4348
fireEvent(firstChild!, new FakeMouseEvent('mousedown', { pageX: 20, pageY: 1 }));
44-
expect(handleChange).toHaveReturnedWith('#e6c300');
49+
const result = getWheelValueFromInput({ width: 200, direction: 'anticlockwise', angle: 180 }, 20, 1);
50+
expect(handleChange).toHaveReturnedWith(hsvaToHex({ ...hsva, ...result }));
4551
});
4652

4753
it('Wheel mousedown onChange 2', async () => {
@@ -62,6 +68,39 @@ it('Wheel direction="clockwise" onChange', async () => {
6268
expect(handleChange).toHaveReturnedWith('#000000');
6369
});
6470

71+
it('Wheel direction and angle should affect pointer position', () => {
72+
const hsv = { h: 60, s: 100, v: 100, a: 1 };
73+
const {
74+
container: { firstChild },
75+
container,
76+
} = render(<Wheel color={hsv} direction="clockwise" angle={30} />);
77+
expect(firstChild).toBeTruthy();
78+
const pointer = container.querySelector('.w-color-wheel-pointer') as HTMLDivElement;
79+
const { x, y } = getWheelHandlePosition({ width: 200, direction: 'clockwise', angle: 30 }, hsv);
80+
expect(pointer.style.transform).toContain(`translate(${x}px, ${y}px)`);
81+
});
82+
83+
it('Wheel direction and angle should affect onChange hue', async () => {
84+
const handleChange = jest.fn();
85+
const wheelProps = { width: 200, direction: 'clockwise' as const, angle: 30 };
86+
const {
87+
container: { firstChild },
88+
} = render(<Wheel color={{ h: 200, s: 20, v: 100, a: 1 }} {...wheelProps} onChange={handleChange} />);
89+
fireEvent(firstChild!, new FakeMouseEvent('mousedown', { pageX: 20, pageY: 1 }));
90+
const expected = getWheelValueFromInput(wheelProps, 20, 1).h;
91+
expect(handleChange).toHaveBeenCalled();
92+
expect(handleChange.mock.calls[0][0].hsva.h).toEqual(expected);
93+
});
94+
95+
it('Wheel background should rotate with angle in the same coordinate system', () => {
96+
const {
97+
container: { firstChild },
98+
} = render(<Wheel color={{ h: 0, s: 100, v: 100, a: 1 }} angle={30} />);
99+
expect(firstChild).toBeTruthy();
100+
const background = (firstChild as HTMLDivElement).children[1] as HTMLDivElement;
101+
expect(background.style.transform).toBe('rotateZ(60deg)');
102+
});
103+
65104
it('getWheelDimensions', () => {
66105
expect(getWheelDimensions({ width: 200 })).toEqual({
67106
cx: 100,

0 commit comments

Comments
 (0)