@react-aria/color 3.0.0-beta.2 → 3.0.0-beta.20
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 +1354 -0
- package/dist/main.js +1336 -492
- package/dist/main.js.map +1 -1
- package/dist/module.js +1336 -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 -14
- package/src/index.ts +9 -4
- package/src/useColorArea.ts +448 -0
- package/src/useColorAreaGradient.ts +254 -0
- package/src/useColorField.ts +4 -2
- package/src/useColorSlider.ts +16 -20
- package/src/useColorWheel.ts +91 -58
package/src/useColorField.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {useFocusWithin, useScrollWheel} from '@react-aria/interactions';
|
|
|
24
24
|
import {useFormattedTextField} from '@react-aria/textfield';
|
|
25
25
|
import {useSpinButton} from '@react-aria/spinbutton';
|
|
26
26
|
|
|
27
|
-
interface ColorFieldAria {
|
|
27
|
+
export interface ColorFieldAria {
|
|
28
28
|
/** Props for the label element. */
|
|
29
29
|
labelProps: LabelHTMLAttributes<HTMLLabelElement>,
|
|
30
30
|
/** Props for the input element. */
|
|
@@ -85,7 +85,7 @@ export function useColorField(
|
|
|
85
85
|
} else if (e.deltaY < 0) {
|
|
86
86
|
decrement();
|
|
87
87
|
}
|
|
88
|
-
}, [
|
|
88
|
+
}, [decrement, increment]);
|
|
89
89
|
// If the input isn't supposed to receive input, disable scrolling.
|
|
90
90
|
let scrollingDisabled = isDisabled || isReadOnly || !focusWithin;
|
|
91
91
|
useScrollWheel({onScroll: onWheel, isDisabled: scrollingDisabled}, ref);
|
|
@@ -98,6 +98,7 @@ export function useColorField(
|
|
|
98
98
|
mergeProps(props, {
|
|
99
99
|
id: inputId,
|
|
100
100
|
value: inputValue,
|
|
101
|
+
defaultValue: undefined,
|
|
101
102
|
type: 'text',
|
|
102
103
|
autoComplete: 'off',
|
|
103
104
|
onChange
|
|
@@ -112,6 +113,7 @@ export function useColorField(
|
|
|
112
113
|
'aria-valuenow': null,
|
|
113
114
|
'aria-valuetext': null,
|
|
114
115
|
autoCorrect: 'off',
|
|
116
|
+
spellCheck: 'false',
|
|
115
117
|
onBlur: commit
|
|
116
118
|
})
|
|
117
119
|
};
|
package/src/useColorSlider.ts
CHANGED
|
@@ -12,36 +12,37 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaColorSliderProps} from '@react-types/color';
|
|
14
14
|
import {ColorSliderState} from '@react-stately/color';
|
|
15
|
-
import {
|
|
15
|
+
import {DOMAttributes} from '@react-types/shared';
|
|
16
|
+
import {InputHTMLAttributes, RefObject} from 'react';
|
|
16
17
|
import {mergeProps} from '@react-aria/utils';
|
|
17
18
|
import {useLocale} from '@react-aria/i18n';
|
|
18
19
|
import {useSlider, useSliderThumb} from '@react-aria/slider';
|
|
19
20
|
|
|
20
|
-
interface
|
|
21
|
+
export interface AriaColorSliderOptions extends AriaColorSliderProps {
|
|
21
22
|
/** A ref for the track element. */
|
|
22
|
-
trackRef: RefObject<
|
|
23
|
+
trackRef: RefObject<Element>,
|
|
23
24
|
/** A ref for the input element. */
|
|
24
25
|
inputRef: RefObject<HTMLInputElement>
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
interface ColorSliderAria {
|
|
28
|
+
export interface ColorSliderAria {
|
|
28
29
|
/** Props for the label element. */
|
|
29
|
-
labelProps:
|
|
30
|
+
labelProps: DOMAttributes,
|
|
30
31
|
/** Props for the track element. */
|
|
31
|
-
trackProps:
|
|
32
|
+
trackProps: DOMAttributes,
|
|
32
33
|
/** Props for the thumb element. */
|
|
33
|
-
thumbProps:
|
|
34
|
+
thumbProps: DOMAttributes,
|
|
34
35
|
/** Props for the visually hidden range input element. */
|
|
35
|
-
inputProps:
|
|
36
|
+
inputProps: InputHTMLAttributes<HTMLInputElement>,
|
|
36
37
|
/** Props for the output element, displaying the value of the color slider. */
|
|
37
|
-
outputProps:
|
|
38
|
+
outputProps: DOMAttributes
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Provides the behavior and accessibility implementation for a color slider component.
|
|
42
43
|
* Color sliders allow users to adjust an individual channel of a color value.
|
|
43
44
|
*/
|
|
44
|
-
export function useColorSlider(props:
|
|
45
|
+
export function useColorSlider(props: AriaColorSliderOptions, state: ColorSliderState): ColorSliderAria {
|
|
45
46
|
let {trackRef, inputRef, orientation, channel, 'aria-label': ariaLabel} = props;
|
|
46
47
|
|
|
47
48
|
let {locale, direction} = useLocale();
|
|
@@ -99,17 +100,14 @@ export function useColorSlider(props: ColorSliderAriaOptions, state: ColorSlider
|
|
|
99
100
|
}
|
|
100
101
|
};
|
|
101
102
|
|
|
102
|
-
let
|
|
103
|
-
if (orientation === 'vertical' || direction === 'rtl') {
|
|
104
|
-
thumbPosition = 1 - thumbPosition;
|
|
105
|
-
}
|
|
103
|
+
let forcedColorAdjustNoneStyle = {forcedColorAdjust: 'none'};
|
|
106
104
|
|
|
107
105
|
return {
|
|
108
106
|
trackProps: {
|
|
109
107
|
...mergeProps(groupProps, trackProps),
|
|
110
108
|
style: {
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
...trackProps.style,
|
|
110
|
+
...forcedColorAdjustNoneStyle,
|
|
113
111
|
background: generateBackground()
|
|
114
112
|
}
|
|
115
113
|
},
|
|
@@ -117,10 +115,8 @@ export function useColorSlider(props: ColorSliderAriaOptions, state: ColorSlider
|
|
|
117
115
|
thumbProps: {
|
|
118
116
|
...thumbProps,
|
|
119
117
|
style: {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
[orientation === 'vertical' ? 'top' : 'left']: `${thumbPosition * 100}%`,
|
|
123
|
-
transform: 'translate(-50%, -50%)'
|
|
118
|
+
...thumbProps.style,
|
|
119
|
+
...forcedColorAdjustNoneStyle
|
|
124
120
|
}
|
|
125
121
|
},
|
|
126
122
|
labelProps,
|
package/src/useColorWheel.ts
CHANGED
|
@@ -12,37 +12,35 @@
|
|
|
12
12
|
|
|
13
13
|
import {AriaColorWheelProps} from '@react-types/color';
|
|
14
14
|
import {ColorWheelState} from '@react-stately/color';
|
|
15
|
+
import {DOMAttributes} from '@react-types/shared';
|
|
15
16
|
import {focusWithoutScrolling, mergeProps, useGlobalListeners, useLabels} from '@react-aria/utils';
|
|
16
|
-
import React, {ChangeEvent,
|
|
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
46
|
'aria-label': ariaLabel
|
|
@@ -62,12 +60,38 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
62
60
|
stateRef.current = state;
|
|
63
61
|
|
|
64
62
|
let currentPosition = useRef<{x: number, y: number}>(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
|
+
stateRef.current.setDragging(true);
|
|
75
|
+
switch (e.key) {
|
|
76
|
+
case 'PageUp':
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
state.increment(stateRef.current.pageStep);
|
|
79
|
+
break;
|
|
80
|
+
case 'PageDown':
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
state.decrement(stateRef.current.pageStep);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
stateRef.current.setDragging(false);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
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
96
|
currentPosition.current = stateRef.current.getThumbPosition(thumbRadius);
|
|
73
97
|
}
|
|
@@ -75,9 +99,9 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
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 ? stateRef.current.pageStep : stateRef.current.step);
|
|
79
103
|
} else if (deltaX < 0 || deltaY > 0) {
|
|
80
|
-
state.decrement();
|
|
104
|
+
state.decrement(shiftKey ? stateRef.current.pageStep : stateRef.current.step);
|
|
81
105
|
}
|
|
82
106
|
} else {
|
|
83
107
|
stateRef.current.setHueFromPoint(currentPosition.current.x, currentPosition.current.y, thumbRadius);
|
|
@@ -116,9 +140,13 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
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,9 +158,12 @@ 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
|
|
|
@@ -149,9 +180,12 @@ export function useColorWheel(props: ColorWheelAriaProps, state: ColorWheelState
|
|
|
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,15 +300,16 @@ 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,
|