@react-aria/color 3.0.0-beta.3 → 3.0.0-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/import.mjs +1377 -0
- package/dist/main.js +1360 -492
- package/dist/main.js.map +1 -1
- package/dist/module.js +1359 -457
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +45 -18
- package/dist/types.d.ts.map +1 -1
- package/package.json +21 -15
- package/src/index.ts +9 -4
- package/src/useColorArea.ts +460 -0
- package/src/useColorAreaGradient.ts +254 -0
- package/src/useColorField.ts +34 -18
- package/src/useColorSlider.ts +18 -21
- package/src/useColorWheel.ts +103 -69
package/src/useColorWheel.ts
CHANGED
|
@@ -12,40 +12,39 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaColorWheelProps} from '@react-types/color';
|
|
14
14
|
import {ColorWheelState} from '@react-stately/color';
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
15
|
+
import {DOMAttributes} from '@react-types/shared';
|
|
16
|
+
import {focusWithoutScrolling, mergeProps, useFormReset, useGlobalListeners, useLabels} from '@react-aria/utils';
|
|
17
|
+
import React, {ChangeEvent, InputHTMLAttributes, RefObject, useCallback, useRef} from 'react';
|
|
17
18
|
import {useKeyboard, useMove} from '@react-aria/interactions';
|
|
18
19
|
import {useLocale} from '@react-aria/i18n';
|
|
19
20
|
|
|
20
|
-
interface
|
|
21
|
+
export interface AriaColorWheelOptions extends AriaColorWheelProps {
|
|
21
22
|
/** The outer radius of the color wheel. */
|
|
22
23
|
outerRadius: number,
|
|
23
24
|
/** The inner radius of the color wheel. */
|
|
24
25
|
innerRadius: number
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
interface ColorWheelAria {
|
|
28
|
+
export interface ColorWheelAria {
|
|
28
29
|
/** Props for the track element. */
|
|
29
|
-
trackProps:
|
|
30
|
+
trackProps: DOMAttributes,
|
|
30
31
|
/** Props for the thumb element. */
|
|
31
|
-
thumbProps:
|
|
32
|
+
thumbProps: DOMAttributes,
|
|
32
33
|
/** Props for the visually hidden range input element. */
|
|
33
34
|
inputProps: InputHTMLAttributes<HTMLInputElement>
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const PAGE_MIN_STEP_SIZE = 6;
|
|
37
|
-
|
|
38
37
|
/**
|
|
39
38
|
* Provides the behavior and accessibility implementation for a color wheel component.
|
|
40
39
|
* Color wheels allow users to adjust the hue of an HSL or HSB color value on a circular track.
|
|
41
40
|
*/
|
|
42
|
-
export function useColorWheel(props:
|
|
41
|
+
export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelState, inputRef: RefObject<HTMLInputElement>): ColorWheelAria {
|
|
43
42
|
let {
|
|
44
43
|
isDisabled,
|
|
45
|
-
step = 1,
|
|
46
44
|
innerRadius,
|
|
47
45
|
outerRadius,
|
|
48
|
-
'aria-label': ariaLabel
|
|
46
|
+
'aria-label': ariaLabel,
|
|
47
|
+
name
|
|
49
48
|
} = props;
|
|
50
49
|
|
|
51
50
|
let {addGlobalListener, removeGlobalListener} = useGlobalListeners();
|
|
@@ -58,33 +57,58 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
58
57
|
}
|
|
59
58
|
}, [inputRef]);
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
useFormReset(inputRef, state.hue, state.setHue);
|
|
61
|
+
|
|
62
|
+
let currentPosition = useRef<{x: number, y: number} | null>(null);
|
|
63
|
+
|
|
64
|
+
let {keyboardProps} = useKeyboard({
|
|
65
|
+
onKeyDown(e) {
|
|
66
|
+
// these are the cases that useMove doesn't handle
|
|
67
|
+
if (!/^(PageUp|PageDown)$/.test(e.key)) {
|
|
68
|
+
e.continuePropagation();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// same handling as useMove, don't need to stop propagation, useKeyboard will do that for us
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
// remember to set this and unset it so that onChangeEnd is fired
|
|
74
|
+
state.setDragging(true);
|
|
75
|
+
switch (e.key) {
|
|
76
|
+
case 'PageUp':
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
state.increment(state.pageStep);
|
|
79
|
+
break;
|
|
80
|
+
case 'PageDown':
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
state.decrement(state.pageStep);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
state.setDragging(false);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
63
88
|
|
|
64
|
-
let currentPosition = useRef<{x: number, y: number}>(null);
|
|
65
89
|
let moveHandler = {
|
|
66
90
|
onMoveStart() {
|
|
67
91
|
currentPosition.current = null;
|
|
68
92
|
state.setDragging(true);
|
|
69
93
|
},
|
|
70
|
-
onMove({deltaX, deltaY, pointerType}) {
|
|
94
|
+
onMove({deltaX, deltaY, pointerType, shiftKey}) {
|
|
71
95
|
if (currentPosition.current == null) {
|
|
72
|
-
currentPosition.current =
|
|
96
|
+
currentPosition.current = state.getThumbPosition(thumbRadius);
|
|
73
97
|
}
|
|
74
98
|
currentPosition.current.x += deltaX;
|
|
75
99
|
currentPosition.current.y += deltaY;
|
|
76
100
|
if (pointerType === 'keyboard') {
|
|
77
101
|
if (deltaX > 0 || deltaY < 0) {
|
|
78
|
-
state.increment();
|
|
102
|
+
state.increment(shiftKey ? state.pageStep : state.step);
|
|
79
103
|
} else if (deltaX < 0 || deltaY > 0) {
|
|
80
|
-
state.decrement();
|
|
104
|
+
state.decrement(shiftKey ? state.pageStep : state.step);
|
|
81
105
|
}
|
|
82
106
|
} else {
|
|
83
|
-
|
|
107
|
+
state.setHueFromPoint(currentPosition.current.x, currentPosition.current.y, thumbRadius);
|
|
84
108
|
}
|
|
85
109
|
},
|
|
86
110
|
onMoveEnd() {
|
|
87
|
-
isOnTrack.current =
|
|
111
|
+
isOnTrack.current = false;
|
|
88
112
|
state.setDragging(false);
|
|
89
113
|
focusInput();
|
|
90
114
|
}
|
|
@@ -111,14 +135,18 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
111
135
|
}
|
|
112
136
|
});
|
|
113
137
|
|
|
114
|
-
let onThumbDown = (id: number | null) => {
|
|
138
|
+
let onThumbDown = (id: number | null | undefined) => {
|
|
115
139
|
if (!state.isDragging) {
|
|
116
140
|
currentPointer.current = id;
|
|
117
141
|
focusInput();
|
|
118
142
|
state.setDragging(true);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
143
|
+
|
|
144
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
145
|
+
addGlobalListener(window, 'pointerup', onThumbUp, false);
|
|
146
|
+
} else {
|
|
147
|
+
addGlobalListener(window, 'mouseup', onThumbUp, false);
|
|
148
|
+
addGlobalListener(window, 'touchend', onThumbUp, false);
|
|
149
|
+
}
|
|
122
150
|
}
|
|
123
151
|
};
|
|
124
152
|
|
|
@@ -130,13 +158,16 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
130
158
|
currentPointer.current = undefined;
|
|
131
159
|
isOnTrack.current = false;
|
|
132
160
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
161
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
162
|
+
removeGlobalListener(window, 'pointerup', onThumbUp, false);
|
|
163
|
+
} else {
|
|
164
|
+
removeGlobalListener(window, 'mouseup', onThumbUp, false);
|
|
165
|
+
removeGlobalListener(window, 'touchend', onThumbUp, false);
|
|
166
|
+
}
|
|
136
167
|
}
|
|
137
168
|
};
|
|
138
169
|
|
|
139
|
-
let onTrackDown = (track: Element, id: number | null, pageX: number, pageY: number) => {
|
|
170
|
+
let onTrackDown = (track: Element, id: number | null | undefined, pageX: number, pageY: number) => {
|
|
140
171
|
let rect = track.getBoundingClientRect();
|
|
141
172
|
let x = pageX - rect.x - rect.width / 2;
|
|
142
173
|
let y = pageY - rect.y - rect.height / 2;
|
|
@@ -144,14 +175,17 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
144
175
|
if (innerRadius < radius && radius < outerRadius && !state.isDragging && currentPointer.current === undefined) {
|
|
145
176
|
isOnTrack.current = true;
|
|
146
177
|
currentPointer.current = id;
|
|
147
|
-
|
|
178
|
+
state.setHueFromPoint(x, y, radius);
|
|
148
179
|
|
|
149
180
|
focusInput();
|
|
150
181
|
state.setDragging(true);
|
|
151
182
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
183
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
184
|
+
addGlobalListener(window, 'pointerup', onTrackUp, false);
|
|
185
|
+
} else {
|
|
186
|
+
addGlobalListener(window, 'mouseup', onTrackUp, false);
|
|
187
|
+
addGlobalListener(window, 'touchend', onTrackUp, false);
|
|
188
|
+
}
|
|
155
189
|
}
|
|
156
190
|
};
|
|
157
191
|
|
|
@@ -163,43 +197,34 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
163
197
|
state.setDragging(false);
|
|
164
198
|
focusInput();
|
|
165
199
|
|
|
166
|
-
removeGlobalListener(window, 'mouseup', onTrackUp, false);
|
|
167
|
-
removeGlobalListener(window, 'touchend', onTrackUp, false);
|
|
168
|
-
removeGlobalListener(window, 'pointerup', onTrackUp, false);
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
200
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
state.increment(PAGE_MIN_STEP_SIZE);
|
|
178
|
-
break;
|
|
179
|
-
case 'PageDown':
|
|
180
|
-
e.preventDefault();
|
|
181
|
-
state.decrement(PAGE_MIN_STEP_SIZE);
|
|
182
|
-
break;
|
|
201
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
202
|
+
removeGlobalListener(window, 'pointerup', onTrackUp, false);
|
|
203
|
+
} else {
|
|
204
|
+
removeGlobalListener(window, 'mouseup', onTrackUp, false);
|
|
205
|
+
removeGlobalListener(window, 'touchend', onTrackUp, false);
|
|
183
206
|
}
|
|
184
207
|
}
|
|
185
|
-
}
|
|
208
|
+
};
|
|
186
209
|
|
|
187
210
|
let trackInteractions = isDisabled ? {} : mergeProps({
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
211
|
+
...(typeof PointerEvent !== 'undefined' ? {
|
|
212
|
+
onPointerDown: (e: React.PointerEvent) => {
|
|
213
|
+
if (e.pointerType === 'mouse' && (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey)) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
onTrackDown(e.currentTarget, e.pointerId, e.clientX, e.clientY);
|
|
217
|
+
}} : {
|
|
218
|
+
onMouseDown: (e: React.MouseEvent) => {
|
|
219
|
+
if (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
onTrackDown(e.currentTarget, undefined, e.clientX, e.clientY);
|
|
223
|
+
},
|
|
224
|
+
onTouchStart: (e: React.TouchEvent) => {
|
|
225
|
+
onTrackDown(e.currentTarget, e.changedTouches[0].identifier, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
|
|
226
|
+
}
|
|
227
|
+
})
|
|
203
228
|
}, movePropsContainer);
|
|
204
229
|
|
|
205
230
|
let thumbInteractions = isDisabled ? {} : mergeProps({
|
|
@@ -218,7 +243,7 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
218
243
|
onTouchStart: (e: React.TouchEvent) => {
|
|
219
244
|
onThumbDown(e.changedTouches[0].identifier);
|
|
220
245
|
}
|
|
221
|
-
},
|
|
246
|
+
}, keyboardProps, movePropsThumb);
|
|
222
247
|
let {x, y} = state.getThumbPosition(thumbRadius);
|
|
223
248
|
|
|
224
249
|
// Provide a default aria-label if none is given
|
|
@@ -232,6 +257,12 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
232
257
|
'aria-label': ariaLabel
|
|
233
258
|
});
|
|
234
259
|
|
|
260
|
+
let {minValue, maxValue, step} = state.value.getChannelRange('hue');
|
|
261
|
+
|
|
262
|
+
let forcedColorAdjustNoneStyle = {
|
|
263
|
+
forcedColorAdjust: 'none'
|
|
264
|
+
};
|
|
265
|
+
|
|
235
266
|
return {
|
|
236
267
|
trackProps: {
|
|
237
268
|
...trackInteractions,
|
|
@@ -258,7 +289,8 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
258
289
|
hsl(360, 100%, 50%)
|
|
259
290
|
)
|
|
260
291
|
`,
|
|
261
|
-
clipPath: `path(evenodd, "${circlePath(outerRadius, outerRadius, outerRadius)} ${circlePath(outerRadius, outerRadius, innerRadius)}")
|
|
292
|
+
clipPath: `path(evenodd, "${circlePath(outerRadius, outerRadius, outerRadius)} ${circlePath(outerRadius, outerRadius, innerRadius)}")`,
|
|
293
|
+
...forcedColorAdjustNoneStyle
|
|
262
294
|
}
|
|
263
295
|
},
|
|
264
296
|
thumbProps: {
|
|
@@ -268,19 +300,21 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
268
300
|
left: '50%',
|
|
269
301
|
top: '50%',
|
|
270
302
|
transform: `translate(calc(${x}px - 50%), calc(${y}px - 50%))`,
|
|
271
|
-
touchAction: 'none'
|
|
303
|
+
touchAction: 'none',
|
|
304
|
+
...forcedColorAdjustNoneStyle
|
|
272
305
|
}
|
|
273
306
|
},
|
|
274
307
|
inputProps: mergeProps(
|
|
275
308
|
inputLabellingProps,
|
|
276
309
|
{
|
|
277
310
|
type: 'range',
|
|
278
|
-
min:
|
|
279
|
-
max:
|
|
311
|
+
min: String(minValue),
|
|
312
|
+
max: String(maxValue),
|
|
280
313
|
step: String(step),
|
|
281
314
|
'aria-valuetext': state.value.formatChannelValue('hue', locale),
|
|
282
315
|
disabled: isDisabled,
|
|
283
316
|
value: `${state.value.getChannelValue('hue')}`,
|
|
317
|
+
name,
|
|
284
318
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
|
285
319
|
state.setHue(parseFloat(e.target.value));
|
|
286
320
|
}
|