@react-aria/color 3.0.0-beta.0 → 3.0.0-beta.11
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/main.js +1120 -460
- package/dist/main.js.map +1 -1
- package/dist/module.js +1123 -443
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +28 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -13
- package/src/index.ts +1 -0
- package/src/useColorArea.ts +447 -0
- package/src/useColorAreaGradient.ts +249 -0
- package/src/useColorField.ts +26 -13
- package/src/useColorWheel.ts +75 -50
package/src/useColorField.ts
CHANGED
|
@@ -15,11 +15,14 @@ import {ColorFieldState} from '@react-stately/color';
|
|
|
15
15
|
import {
|
|
16
16
|
HTMLAttributes,
|
|
17
17
|
LabelHTMLAttributes,
|
|
18
|
-
RefObject
|
|
18
|
+
RefObject,
|
|
19
|
+
useCallback,
|
|
20
|
+
useState
|
|
19
21
|
} from 'react';
|
|
20
22
|
import {mergeProps, useId} from '@react-aria/utils';
|
|
23
|
+
import {useFocusWithin, useScrollWheel} from '@react-aria/interactions';
|
|
24
|
+
import {useFormattedTextField} from '@react-aria/textfield';
|
|
21
25
|
import {useSpinButton} from '@react-aria/spinbutton';
|
|
22
|
-
import {useTextField} from '@react-aria/textfield';
|
|
23
26
|
|
|
24
27
|
interface ColorFieldAria {
|
|
25
28
|
/** Props for the label element. */
|
|
@@ -46,7 +49,6 @@ export function useColorField(
|
|
|
46
49
|
let {
|
|
47
50
|
colorValue,
|
|
48
51
|
inputValue,
|
|
49
|
-
setInputValue,
|
|
50
52
|
commit,
|
|
51
53
|
increment,
|
|
52
54
|
decrement,
|
|
@@ -71,37 +73,48 @@ export function useColorField(
|
|
|
71
73
|
}
|
|
72
74
|
);
|
|
73
75
|
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
+
let [focusWithin, setFocusWithin] = useState(false);
|
|
77
|
+
let {focusWithinProps} = useFocusWithin({isDisabled, onFocusWithinChange: setFocusWithin});
|
|
78
|
+
|
|
79
|
+
let onWheel = useCallback((e) => {
|
|
80
|
+
if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) {
|
|
76
81
|
return;
|
|
77
82
|
}
|
|
78
|
-
if (e.deltaY
|
|
83
|
+
if (e.deltaY > 0) {
|
|
79
84
|
increment();
|
|
80
|
-
} else {
|
|
85
|
+
} else if (e.deltaY < 0) {
|
|
81
86
|
decrement();
|
|
82
87
|
}
|
|
88
|
+
}, [decrement, increment]);
|
|
89
|
+
// If the input isn't supposed to receive input, disable scrolling.
|
|
90
|
+
let scrollingDisabled = isDisabled || isReadOnly || !focusWithin;
|
|
91
|
+
useScrollWheel({onScroll: onWheel, isDisabled: scrollingDisabled}, ref);
|
|
92
|
+
|
|
93
|
+
let onChange = value => {
|
|
94
|
+
state.setInputValue(value);
|
|
83
95
|
};
|
|
84
96
|
|
|
85
|
-
let {labelProps, inputProps} =
|
|
97
|
+
let {labelProps, inputProps} = useFormattedTextField(
|
|
86
98
|
mergeProps(props, {
|
|
87
99
|
id: inputId,
|
|
88
100
|
value: inputValue,
|
|
101
|
+
defaultValue: undefined,
|
|
89
102
|
type: 'text',
|
|
90
103
|
autoComplete: 'off',
|
|
91
|
-
onChange
|
|
92
|
-
}), ref);
|
|
104
|
+
onChange
|
|
105
|
+
}), state, ref);
|
|
93
106
|
|
|
94
107
|
return {
|
|
95
108
|
labelProps,
|
|
96
|
-
inputProps: mergeProps(inputProps, spinButtonProps, {
|
|
109
|
+
inputProps: mergeProps(inputProps, spinButtonProps, focusWithinProps, {
|
|
97
110
|
role: 'textbox',
|
|
98
111
|
'aria-valuemax': null,
|
|
99
112
|
'aria-valuemin': null,
|
|
100
113
|
'aria-valuenow': null,
|
|
101
114
|
'aria-valuetext': null,
|
|
102
115
|
autoCorrect: 'off',
|
|
103
|
-
|
|
104
|
-
|
|
116
|
+
spellCheck: 'false',
|
|
117
|
+
onBlur: commit
|
|
105
118
|
})
|
|
106
119
|
};
|
|
107
120
|
}
|
package/src/useColorWheel.ts
CHANGED
|
@@ -33,8 +33,6 @@ interface ColorWheelAria {
|
|
|
33
33
|
inputProps: InputHTMLAttributes<HTMLInputElement>
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const PAGE_MIN_STEP_SIZE = 6;
|
|
37
|
-
|
|
38
36
|
/**
|
|
39
37
|
* Provides the behavior and accessibility implementation for a color wheel component.
|
|
40
38
|
* Color wheels allow users to adjust the hue of an HSL or HSB color value on a circular track.
|
|
@@ -42,7 +40,6 @@ const PAGE_MIN_STEP_SIZE = 6;
|
|
|
42
40
|
export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState, inputRef: RefObject<HTMLElement>): ColorWheelAria {
|
|
43
41
|
let {
|
|
44
42
|
isDisabled,
|
|
45
|
-
step = 1,
|
|
46
43
|
innerRadius,
|
|
47
44
|
outerRadius,
|
|
48
45
|
'aria-label': ariaLabel
|
|
@@ -62,12 +59,38 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
62
59
|
stateRef.current = state;
|
|
63
60
|
|
|
64
61
|
let currentPosition = useRef<{x: number, y: number}>(null);
|
|
62
|
+
|
|
63
|
+
let {keyboardProps} = useKeyboard({
|
|
64
|
+
onKeyDown(e) {
|
|
65
|
+
// these are the cases that useMove doesn't handle
|
|
66
|
+
if (!/^(PageUp|PageDown)$/.test(e.key)) {
|
|
67
|
+
e.continuePropagation();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// same handling as useMove, don't need to stop propagation, useKeyboard will do that for us
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
// remember to set this and unset it so that onChangeEnd is fired
|
|
73
|
+
stateRef.current.setDragging(true);
|
|
74
|
+
switch (e.key) {
|
|
75
|
+
case 'PageUp':
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
state.increment(stateRef.current.pageStep);
|
|
78
|
+
break;
|
|
79
|
+
case 'PageDown':
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
state.decrement(stateRef.current.pageStep);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
stateRef.current.setDragging(false);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
65
88
|
let moveHandler = {
|
|
66
89
|
onMoveStart() {
|
|
67
90
|
currentPosition.current = null;
|
|
68
91
|
state.setDragging(true);
|
|
69
92
|
},
|
|
70
|
-
onMove({deltaX, deltaY, pointerType}) {
|
|
93
|
+
onMove({deltaX, deltaY, pointerType, shiftKey}) {
|
|
71
94
|
if (currentPosition.current == null) {
|
|
72
95
|
currentPosition.current = stateRef.current.getThumbPosition(thumbRadius);
|
|
73
96
|
}
|
|
@@ -75,9 +98,9 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
75
98
|
currentPosition.current.y += deltaY;
|
|
76
99
|
if (pointerType === 'keyboard') {
|
|
77
100
|
if (deltaX > 0 || deltaY < 0) {
|
|
78
|
-
state.increment();
|
|
101
|
+
state.increment(shiftKey ? stateRef.current.pageStep : stateRef.current.step);
|
|
79
102
|
} else if (deltaX < 0 || deltaY > 0) {
|
|
80
|
-
state.decrement();
|
|
103
|
+
state.decrement(shiftKey ? stateRef.current.pageStep : stateRef.current.step);
|
|
81
104
|
}
|
|
82
105
|
} else {
|
|
83
106
|
stateRef.current.setHueFromPoint(currentPosition.current.x, currentPosition.current.y, thumbRadius);
|
|
@@ -116,9 +139,13 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
116
139
|
currentPointer.current = id;
|
|
117
140
|
focusInput();
|
|
118
141
|
state.setDragging(true);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
142
|
+
|
|
143
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
144
|
+
addGlobalListener(window, 'pointerup', onThumbUp, false);
|
|
145
|
+
} else {
|
|
146
|
+
addGlobalListener(window, 'mouseup', onThumbUp, false);
|
|
147
|
+
addGlobalListener(window, 'touchend', onThumbUp, false);
|
|
148
|
+
}
|
|
122
149
|
}
|
|
123
150
|
};
|
|
124
151
|
|
|
@@ -130,9 +157,12 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
130
157
|
currentPointer.current = undefined;
|
|
131
158
|
isOnTrack.current = false;
|
|
132
159
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
160
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
161
|
+
removeGlobalListener(window, 'pointerup', onThumbUp, false);
|
|
162
|
+
} else {
|
|
163
|
+
removeGlobalListener(window, 'mouseup', onThumbUp, false);
|
|
164
|
+
removeGlobalListener(window, 'touchend', onThumbUp, false);
|
|
165
|
+
}
|
|
136
166
|
}
|
|
137
167
|
};
|
|
138
168
|
|
|
@@ -149,9 +179,12 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
149
179
|
focusInput();
|
|
150
180
|
state.setDragging(true);
|
|
151
181
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
182
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
183
|
+
addGlobalListener(window, 'pointerup', onTrackUp, false);
|
|
184
|
+
} else {
|
|
185
|
+
addGlobalListener(window, 'mouseup', onTrackUp, false);
|
|
186
|
+
addGlobalListener(window, 'touchend', onTrackUp, false);
|
|
187
|
+
}
|
|
155
188
|
}
|
|
156
189
|
};
|
|
157
190
|
|
|
@@ -163,43 +196,34 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
163
196
|
state.setDragging(false);
|
|
164
197
|
focusInput();
|
|
165
198
|
|
|
166
|
-
removeGlobalListener(window, 'mouseup', onTrackUp, false);
|
|
167
|
-
removeGlobalListener(window, 'touchend', onTrackUp, false);
|
|
168
|
-
removeGlobalListener(window, 'pointerup', onTrackUp, false);
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
199
|
|
|
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;
|
|
200
|
+
if (typeof PointerEvent !== 'undefined') {
|
|
201
|
+
removeGlobalListener(window, 'pointerup', onTrackUp, false);
|
|
202
|
+
} else {
|
|
203
|
+
removeGlobalListener(window, 'mouseup', onTrackUp, false);
|
|
204
|
+
removeGlobalListener(window, 'touchend', onTrackUp, false);
|
|
183
205
|
}
|
|
184
206
|
}
|
|
185
|
-
}
|
|
207
|
+
};
|
|
186
208
|
|
|
187
209
|
let trackInteractions = isDisabled ? {} : mergeProps({
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
210
|
+
...(typeof PointerEvent !== 'undefined' ? {
|
|
211
|
+
onPointerDown: (e: React.PointerEvent) => {
|
|
212
|
+
if (e.pointerType === 'mouse' && (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
onTrackDown(e.currentTarget, e.pointerId, e.clientX, e.clientY);
|
|
216
|
+
}} : {
|
|
217
|
+
onMouseDown: (e: React.MouseEvent) => {
|
|
218
|
+
if (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
onTrackDown(e.currentTarget, undefined, e.clientX, e.clientY);
|
|
222
|
+
},
|
|
223
|
+
onTouchStart: (e: React.TouchEvent) => {
|
|
224
|
+
onTrackDown(e.currentTarget, e.changedTouches[0].identifier, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
|
|
225
|
+
}
|
|
226
|
+
})
|
|
203
227
|
}, movePropsContainer);
|
|
204
228
|
|
|
205
229
|
let thumbInteractions = isDisabled ? {} : mergeProps({
|
|
@@ -218,7 +242,7 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
218
242
|
onTouchStart: (e: React.TouchEvent) => {
|
|
219
243
|
onThumbDown(e.changedTouches[0].identifier);
|
|
220
244
|
}
|
|
221
|
-
},
|
|
245
|
+
}, keyboardProps, movePropsThumb);
|
|
222
246
|
let {x, y} = state.getThumbPosition(thumbRadius);
|
|
223
247
|
|
|
224
248
|
// Provide a default aria-label if none is given
|
|
@@ -232,6 +256,7 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
232
256
|
'aria-label': ariaLabel
|
|
233
257
|
});
|
|
234
258
|
|
|
259
|
+
let {minValue, maxValue, step} = state.value.getChannelRange('hue');
|
|
235
260
|
return {
|
|
236
261
|
trackProps: {
|
|
237
262
|
...trackInteractions,
|
|
@@ -275,8 +300,8 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
275
300
|
inputLabellingProps,
|
|
276
301
|
{
|
|
277
302
|
type: 'range',
|
|
278
|
-
min:
|
|
279
|
-
max:
|
|
303
|
+
min: String(minValue),
|
|
304
|
+
max: String(maxValue),
|
|
280
305
|
step: String(step),
|
|
281
306
|
'aria-valuetext': state.value.formatChannelValue('hue', locale),
|
|
282
307
|
disabled: isDisabled,
|