@react-aria/color 3.0.0-beta.21 → 3.0.0-beta.23
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 +74 -62
- package/dist/main.js +72 -60
- package/dist/main.js.map +1 -1
- package/dist/module.js +74 -62
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/useColorArea.ts +55 -43
- package/src/useColorSlider.ts +2 -1
- package/src/useColorWheel.ts +14 -13
package/src/useColorArea.ts
CHANGED
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
import {AriaColorAreaProps, ColorChannel} from '@react-types/color';
|
|
14
14
|
import {ColorAreaState} from '@react-stately/color';
|
|
15
15
|
import {DOMAttributes} from '@react-types/shared';
|
|
16
|
-
import {focusWithoutScrolling, isAndroid, isIOS, mergeProps, useGlobalListeners, useLabels} from '@react-aria/utils';
|
|
16
|
+
import {focusWithoutScrolling, isAndroid, isIOS, mergeProps, useFormReset, useGlobalListeners, useLabels} from '@react-aria/utils';
|
|
17
17
|
// @ts-ignore
|
|
18
18
|
import intlMessages from '../intl/*.json';
|
|
19
|
-
import React, {ChangeEvent, InputHTMLAttributes, RefObject, useCallback, useRef} from 'react';
|
|
19
|
+
import React, {ChangeEvent, InputHTMLAttributes, RefObject, useCallback, useRef, useState} from 'react';
|
|
20
20
|
import {useColorAreaGradient} from './useColorAreaGradient';
|
|
21
21
|
import {useFocus, useFocusWithin, useKeyboard, useMove} from '@react-aria/interactions';
|
|
22
22
|
import {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';
|
|
@@ -54,7 +54,9 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
54
54
|
inputXRef,
|
|
55
55
|
inputYRef,
|
|
56
56
|
containerRef,
|
|
57
|
-
'aria-label': ariaLabel
|
|
57
|
+
'aria-label': ariaLabel,
|
|
58
|
+
xName,
|
|
59
|
+
yName
|
|
58
60
|
} = props;
|
|
59
61
|
let stringFormatter = useLocalizedStringFormatter(intlMessages);
|
|
60
62
|
|
|
@@ -62,19 +64,24 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
62
64
|
|
|
63
65
|
let {direction, locale} = useLocale();
|
|
64
66
|
|
|
65
|
-
let
|
|
66
|
-
|
|
67
|
+
let [focusedInput, setFocusedInput] = useState<'x' | 'y' | null>(null);
|
|
67
68
|
let focusInput = useCallback((inputRef:RefObject<HTMLInputElement> = inputXRef) => {
|
|
68
69
|
if (inputRef.current) {
|
|
69
70
|
focusWithoutScrolling(inputRef.current);
|
|
70
71
|
}
|
|
71
72
|
}, [inputXRef]);
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
useFormReset(inputXRef, [state.xValue, state.yValue], ([x, y]) => {
|
|
75
|
+
let newColor = state.value
|
|
76
|
+
.withChannelValue(state.channels.xChannel, x)
|
|
77
|
+
.withChannelValue(state.channels.yChannel, y);
|
|
78
|
+
state.setValue(newColor);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
let [valueChangedViaKeyboard, setValueChangedViaKeyboard] = useState(false);
|
|
82
|
+
let {xChannel, yChannel, zChannel} = state.channels;
|
|
83
|
+
let xChannelStep = state.xChannelStep;
|
|
84
|
+
let yChannelStep = state.yChannelStep;
|
|
78
85
|
|
|
79
86
|
let currentPosition = useRef<{x: number, y: number}>(null);
|
|
80
87
|
|
|
@@ -88,29 +95,32 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
88
95
|
// same handling as useMove, don't need to stop propagation, useKeyboard will do that for us
|
|
89
96
|
e.preventDefault();
|
|
90
97
|
// remember to set this and unset it so that onChangeEnd is fired
|
|
91
|
-
|
|
92
|
-
|
|
98
|
+
state.setDragging(true);
|
|
99
|
+
setValueChangedViaKeyboard(true);
|
|
100
|
+
let dir;
|
|
93
101
|
switch (e.key) {
|
|
94
102
|
case 'PageUp':
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
state.incrementY(state.yChannelPageStep);
|
|
104
|
+
dir = 'y';
|
|
97
105
|
break;
|
|
98
106
|
case 'PageDown':
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
state.decrementY(state.yChannelPageStep);
|
|
108
|
+
dir = 'y';
|
|
101
109
|
break;
|
|
102
110
|
case 'Home':
|
|
103
|
-
direction === 'rtl' ?
|
|
104
|
-
|
|
111
|
+
direction === 'rtl' ? state.incrementX(state.xChannelPageStep) : state.decrementX(state.xChannelPageStep);
|
|
112
|
+
dir = 'x';
|
|
105
113
|
break;
|
|
106
114
|
case 'End':
|
|
107
|
-
direction === 'rtl' ?
|
|
108
|
-
|
|
115
|
+
direction === 'rtl' ? state.decrementX(state.xChannelPageStep) : state.incrementX(state.xChannelPageStep);
|
|
116
|
+
dir = 'x';
|
|
109
117
|
break;
|
|
110
118
|
}
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
119
|
+
state.setDragging(false);
|
|
120
|
+
if (dir) {
|
|
121
|
+
let input = dir === 'x' ? inputXRef : inputYRef;
|
|
122
|
+
focusInput(input);
|
|
123
|
+
setFocusedInput(dir);
|
|
114
124
|
}
|
|
115
125
|
}
|
|
116
126
|
});
|
|
@@ -118,7 +128,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
118
128
|
let moveHandler = {
|
|
119
129
|
onMoveStart() {
|
|
120
130
|
currentPosition.current = null;
|
|
121
|
-
|
|
131
|
+
state.setDragging(true);
|
|
122
132
|
},
|
|
123
133
|
onMove({deltaX, deltaY, pointerType, shiftKey}) {
|
|
124
134
|
let {
|
|
@@ -132,7 +142,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
132
142
|
yChannelStep,
|
|
133
143
|
getThumbPosition,
|
|
134
144
|
setColorFromPoint
|
|
135
|
-
} =
|
|
145
|
+
} = state;
|
|
136
146
|
if (currentPosition.current == null) {
|
|
137
147
|
currentPosition.current = getThumbPosition();
|
|
138
148
|
}
|
|
@@ -150,9 +160,10 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
150
160
|
} else if (deltaY < 0) {
|
|
151
161
|
incrementY(deltaYValue);
|
|
152
162
|
}
|
|
153
|
-
|
|
163
|
+
setValueChangedViaKeyboard(valueChanged);
|
|
154
164
|
// set the focused input based on which axis has the greater delta
|
|
155
|
-
|
|
165
|
+
focusedInput = valueChanged && Math.abs(deltaY) > Math.abs(deltaX) ? 'y' : 'x';
|
|
166
|
+
setFocusedInput(focusedInput);
|
|
156
167
|
} else {
|
|
157
168
|
currentPosition.current.x += (direction === 'rtl' ? -1 : 1) * deltaX / width ;
|
|
158
169
|
currentPosition.current.y += deltaY / height;
|
|
@@ -161,18 +172,17 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
161
172
|
},
|
|
162
173
|
onMoveEnd() {
|
|
163
174
|
isOnColorArea.current = undefined;
|
|
164
|
-
|
|
165
|
-
|
|
175
|
+
state.setDragging(false);
|
|
176
|
+
let input = focusedInput === 'x' ? inputXRef : inputYRef;
|
|
177
|
+
focusInput(input);
|
|
166
178
|
}
|
|
167
179
|
};
|
|
168
180
|
let {moveProps: movePropsThumb} = useMove(moveHandler);
|
|
169
181
|
|
|
170
|
-
let valueChangedViaKeyboard = useRef<boolean>(false);
|
|
171
182
|
let {focusWithinProps} = useFocusWithin({
|
|
172
183
|
onFocusWithinChange: (focusWithin:boolean) => {
|
|
173
184
|
if (!focusWithin) {
|
|
174
|
-
|
|
175
|
-
focusedInputRef.current === undefined;
|
|
185
|
+
setValueChangedViaKeyboard(false);
|
|
176
186
|
}
|
|
177
187
|
}
|
|
178
188
|
});
|
|
@@ -200,7 +210,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
200
210
|
let onThumbDown = (id: number | null) => {
|
|
201
211
|
if (!state.isDragging) {
|
|
202
212
|
currentPointer.current = id;
|
|
203
|
-
|
|
213
|
+
setValueChangedViaKeyboard(false);
|
|
204
214
|
focusInput();
|
|
205
215
|
state.setDragging(true);
|
|
206
216
|
if (typeof PointerEvent !== 'undefined') {
|
|
@@ -215,7 +225,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
215
225
|
let onThumbUp = (e) => {
|
|
216
226
|
let id = e.pointerId ?? e.changedTouches?.[0].identifier;
|
|
217
227
|
if (id === currentPointer.current) {
|
|
218
|
-
|
|
228
|
+
setValueChangedViaKeyboard(false);
|
|
219
229
|
focusInput();
|
|
220
230
|
state.setDragging(false);
|
|
221
231
|
currentPointer.current = undefined;
|
|
@@ -240,7 +250,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
240
250
|
}
|
|
241
251
|
if (x >= 0 && x <= 1 && y >= 0 && y <= 1 && !state.isDragging && currentPointer.current === undefined) {
|
|
242
252
|
isOnColorArea.current = true;
|
|
243
|
-
|
|
253
|
+
setValueChangedViaKeyboard(false);
|
|
244
254
|
currentPointer.current = id;
|
|
245
255
|
state.setColorFromPoint(x, y);
|
|
246
256
|
|
|
@@ -260,7 +270,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
260
270
|
let id = e.pointerId ?? e.changedTouches?.[0].identifier;
|
|
261
271
|
if (isOnColorArea.current && id === currentPointer.current) {
|
|
262
272
|
isOnColorArea.current = false;
|
|
263
|
-
|
|
273
|
+
setValueChangedViaKeyboard(false);
|
|
264
274
|
currentPointer.current = undefined;
|
|
265
275
|
state.setDragging(false);
|
|
266
276
|
focusInput();
|
|
@@ -316,13 +326,13 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
316
326
|
|
|
317
327
|
let {focusProps: xInputFocusProps} = useFocus({
|
|
318
328
|
onFocus: () => {
|
|
319
|
-
|
|
329
|
+
setFocusedInput('x');
|
|
320
330
|
}
|
|
321
331
|
});
|
|
322
332
|
|
|
323
333
|
let {focusProps: yInputFocusProps} = useFocus({
|
|
324
334
|
onFocus: () => {
|
|
325
|
-
|
|
335
|
+
setFocusedInput('y');
|
|
326
336
|
}
|
|
327
337
|
});
|
|
328
338
|
|
|
@@ -330,7 +340,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
330
340
|
|
|
331
341
|
function getAriaValueTextForChannel(channel:ColorChannel) {
|
|
332
342
|
return (
|
|
333
|
-
valueChangedViaKeyboard
|
|
343
|
+
valueChangedViaKeyboard ?
|
|
334
344
|
stringFormatter.format('colorNameAndValue', {name: state.value.getChannelName(channel, locale), value: state.value.formatChannelValue(channel, locale)})
|
|
335
345
|
:
|
|
336
346
|
[
|
|
@@ -409,13 +419,14 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
409
419
|
'aria-valuetext': getAriaValueTextForChannel(xChannel),
|
|
410
420
|
disabled: isDisabled,
|
|
411
421
|
value: state.value.getChannelValue(xChannel),
|
|
412
|
-
|
|
422
|
+
name: xName,
|
|
423
|
+
tabIndex: (isMobile || !focusedInput || focusedInput === 'x' ? undefined : -1),
|
|
413
424
|
/*
|
|
414
425
|
So that only a single "2d slider" control shows up when listing form elements for screen readers,
|
|
415
426
|
add aria-hidden="true" to the unfocused control when the value has not changed via the keyboard,
|
|
416
427
|
but remove aria-hidden to reveal the input for each channel when the value has changed with the keyboard.
|
|
417
428
|
*/
|
|
418
|
-
'aria-hidden': (isMobile || !
|
|
429
|
+
'aria-hidden': (isMobile || !focusedInput || focusedInput === 'x' || valueChangedViaKeyboard ? undefined : 'true'),
|
|
419
430
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
|
420
431
|
state.setXValue(parseFloat(e.target.value));
|
|
421
432
|
}
|
|
@@ -433,13 +444,14 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
|
|
|
433
444
|
'aria-orientation': 'vertical',
|
|
434
445
|
disabled: isDisabled,
|
|
435
446
|
value: state.value.getChannelValue(yChannel),
|
|
436
|
-
|
|
447
|
+
name: yName,
|
|
448
|
+
tabIndex: (isMobile || focusedInput === 'y' ? undefined : -1),
|
|
437
449
|
/*
|
|
438
450
|
So that only a single "2d slider" control shows up when listing form elements for screen readers,
|
|
439
451
|
add aria-hidden="true" to the unfocused input when the value has not changed via the keyboard,
|
|
440
452
|
but remove aria-hidden to reveal the input for each channel when the value has changed with the keyboard.
|
|
441
453
|
*/
|
|
442
|
-
'aria-hidden': (isMobile ||
|
|
454
|
+
'aria-hidden': (isMobile || focusedInput === 'y' || valueChangedViaKeyboard ? undefined : 'true'),
|
|
443
455
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
|
444
456
|
state.setYValue(parseFloat(e.target.value));
|
|
445
457
|
}
|
package/src/useColorSlider.ts
CHANGED
|
@@ -43,7 +43,7 @@ export interface ColorSliderAria {
|
|
|
43
43
|
* Color sliders allow users to adjust an individual channel of a color value.
|
|
44
44
|
*/
|
|
45
45
|
export function useColorSlider(props: AriaColorSliderOptions, state: ColorSliderState): ColorSliderAria {
|
|
46
|
-
let {trackRef, inputRef, orientation, channel, 'aria-label': ariaLabel} = props;
|
|
46
|
+
let {trackRef, inputRef, orientation, channel, 'aria-label': ariaLabel, name} = props;
|
|
47
47
|
|
|
48
48
|
let {locale, direction} = useLocale();
|
|
49
49
|
|
|
@@ -58,6 +58,7 @@ export function useColorSlider(props: AriaColorSliderOptions, state: ColorSlider
|
|
|
58
58
|
index: 0,
|
|
59
59
|
orientation,
|
|
60
60
|
isDisabled: props.isDisabled,
|
|
61
|
+
name,
|
|
61
62
|
trackRef,
|
|
62
63
|
inputRef
|
|
63
64
|
}, state);
|
package/src/useColorWheel.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import {AriaColorWheelProps} from '@react-types/color';
|
|
14
14
|
import {ColorWheelState} from '@react-stately/color';
|
|
15
15
|
import {DOMAttributes} from '@react-types/shared';
|
|
16
|
-
import {focusWithoutScrolling, mergeProps, useGlobalListeners, useLabels} from '@react-aria/utils';
|
|
16
|
+
import {focusWithoutScrolling, mergeProps, useFormReset, useGlobalListeners, useLabels} from '@react-aria/utils';
|
|
17
17
|
import React, {ChangeEvent, InputHTMLAttributes, RefObject, useCallback, useRef} from 'react';
|
|
18
18
|
import {useKeyboard, useMove} from '@react-aria/interactions';
|
|
19
19
|
import {useLocale} from '@react-aria/i18n';
|
|
@@ -43,7 +43,8 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
|
|
|
43
43
|
isDisabled,
|
|
44
44
|
innerRadius,
|
|
45
45
|
outerRadius,
|
|
46
|
-
'aria-label': ariaLabel
|
|
46
|
+
'aria-label': ariaLabel,
|
|
47
|
+
name
|
|
47
48
|
} = props;
|
|
48
49
|
|
|
49
50
|
let {addGlobalListener, removeGlobalListener} = useGlobalListeners();
|
|
@@ -56,8 +57,7 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
|
|
|
56
57
|
}
|
|
57
58
|
}, [inputRef]);
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
stateRef.current = state;
|
|
60
|
+
useFormReset(inputRef, state.hue, state.setHue);
|
|
61
61
|
|
|
62
62
|
let currentPosition = useRef<{x: number, y: number}>(null);
|
|
63
63
|
|
|
@@ -71,18 +71,18 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
|
|
|
71
71
|
// same handling as useMove, don't need to stop propagation, useKeyboard will do that for us
|
|
72
72
|
e.preventDefault();
|
|
73
73
|
// remember to set this and unset it so that onChangeEnd is fired
|
|
74
|
-
|
|
74
|
+
state.setDragging(true);
|
|
75
75
|
switch (e.key) {
|
|
76
76
|
case 'PageUp':
|
|
77
77
|
e.preventDefault();
|
|
78
|
-
state.increment(
|
|
78
|
+
state.increment(state.pageStep);
|
|
79
79
|
break;
|
|
80
80
|
case 'PageDown':
|
|
81
81
|
e.preventDefault();
|
|
82
|
-
state.decrement(
|
|
82
|
+
state.decrement(state.pageStep);
|
|
83
83
|
break;
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
state.setDragging(false);
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
|
|
@@ -93,18 +93,18 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
|
|
|
93
93
|
},
|
|
94
94
|
onMove({deltaX, deltaY, pointerType, shiftKey}) {
|
|
95
95
|
if (currentPosition.current == null) {
|
|
96
|
-
currentPosition.current =
|
|
96
|
+
currentPosition.current = state.getThumbPosition(thumbRadius);
|
|
97
97
|
}
|
|
98
98
|
currentPosition.current.x += deltaX;
|
|
99
99
|
currentPosition.current.y += deltaY;
|
|
100
100
|
if (pointerType === 'keyboard') {
|
|
101
101
|
if (deltaX > 0 || deltaY < 0) {
|
|
102
|
-
state.increment(shiftKey ?
|
|
102
|
+
state.increment(shiftKey ? state.pageStep : state.step);
|
|
103
103
|
} else if (deltaX < 0 || deltaY > 0) {
|
|
104
|
-
state.decrement(shiftKey ?
|
|
104
|
+
state.decrement(shiftKey ? state.pageStep : state.step);
|
|
105
105
|
}
|
|
106
106
|
} else {
|
|
107
|
-
|
|
107
|
+
state.setHueFromPoint(currentPosition.current.x, currentPosition.current.y, thumbRadius);
|
|
108
108
|
}
|
|
109
109
|
},
|
|
110
110
|
onMoveEnd() {
|
|
@@ -175,7 +175,7 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
|
|
|
175
175
|
if (innerRadius < radius && radius < outerRadius && !state.isDragging && currentPointer.current === undefined) {
|
|
176
176
|
isOnTrack.current = true;
|
|
177
177
|
currentPointer.current = id;
|
|
178
|
-
|
|
178
|
+
state.setHueFromPoint(x, y, radius);
|
|
179
179
|
|
|
180
180
|
focusInput();
|
|
181
181
|
state.setDragging(true);
|
|
@@ -314,6 +314,7 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
|
|
|
314
314
|
'aria-valuetext': state.value.formatChannelValue('hue', locale),
|
|
315
315
|
disabled: isDisabled,
|
|
316
316
|
value: `${state.value.getChannelValue('hue')}`,
|
|
317
|
+
name,
|
|
317
318
|
onChange: (e: ChangeEvent<HTMLInputElement>) => {
|
|
318
319
|
state.setHue(parseFloat(e.target.value));
|
|
319
320
|
}
|