@react-aria/color 3.0.0-beta.21 → 3.0.0-beta.22

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.
@@ -16,7 +16,7 @@ import {DOMAttributes} from '@react-types/shared';
16
16
  import {focusWithoutScrolling, isAndroid, isIOS, mergeProps, 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';
@@ -62,19 +62,17 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
62
62
 
63
63
  let {direction, locale} = useLocale();
64
64
 
65
- let focusedInputRef = useRef<HTMLInputElement>(null);
66
-
65
+ let [focusedInput, setFocusedInput] = useState<'x' | 'y' | null>(null);
67
66
  let focusInput = useCallback((inputRef:RefObject<HTMLInputElement> = inputXRef) => {
68
67
  if (inputRef.current) {
69
68
  focusWithoutScrolling(inputRef.current);
70
69
  }
71
70
  }, [inputXRef]);
71
+ let [valueChangedViaKeyboard, setValueChangedViaKeyboard] = useState(false);
72
72
 
73
- let stateRef = useRef<ColorAreaState>(null);
74
- stateRef.current = state;
75
- let {xChannel, yChannel, zChannel} = stateRef.current.channels;
76
- let xChannelStep = stateRef.current.xChannelStep;
77
- let yChannelStep = stateRef.current.yChannelStep;
73
+ let {xChannel, yChannel, zChannel} = state.channels;
74
+ let xChannelStep = state.xChannelStep;
75
+ let yChannelStep = state.yChannelStep;
78
76
 
79
77
  let currentPosition = useRef<{x: number, y: number}>(null);
80
78
 
@@ -88,29 +86,32 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
88
86
  // same handling as useMove, don't need to stop propagation, useKeyboard will do that for us
89
87
  e.preventDefault();
90
88
  // remember to set this and unset it so that onChangeEnd is fired
91
- stateRef.current.setDragging(true);
92
- valueChangedViaKeyboard.current = true;
89
+ state.setDragging(true);
90
+ setValueChangedViaKeyboard(true);
91
+ let dir;
93
92
  switch (e.key) {
94
93
  case 'PageUp':
95
- stateRef.current.incrementY(stateRef.current.yChannelPageStep);
96
- focusedInputRef.current = inputYRef.current;
94
+ state.incrementY(state.yChannelPageStep);
95
+ dir = 'y';
97
96
  break;
98
97
  case 'PageDown':
99
- stateRef.current.decrementY(stateRef.current.yChannelPageStep);
100
- focusedInputRef.current = inputYRef.current;
98
+ state.decrementY(state.yChannelPageStep);
99
+ dir = 'y';
101
100
  break;
102
101
  case 'Home':
103
- direction === 'rtl' ? stateRef.current.incrementX(stateRef.current.xChannelPageStep) : stateRef.current.decrementX(stateRef.current.xChannelPageStep);
104
- focusedInputRef.current = inputXRef.current;
102
+ direction === 'rtl' ? state.incrementX(state.xChannelPageStep) : state.decrementX(state.xChannelPageStep);
103
+ dir = 'x';
105
104
  break;
106
105
  case 'End':
107
- direction === 'rtl' ? stateRef.current.decrementX(stateRef.current.xChannelPageStep) : stateRef.current.incrementX(stateRef.current.xChannelPageStep);
108
- focusedInputRef.current = inputXRef.current;
106
+ direction === 'rtl' ? state.decrementX(state.xChannelPageStep) : state.incrementX(state.xChannelPageStep);
107
+ dir = 'x';
109
108
  break;
110
109
  }
111
- stateRef.current.setDragging(false);
112
- if (focusedInputRef.current) {
113
- focusInput(focusedInputRef.current ? focusedInputRef : inputXRef);
110
+ state.setDragging(false);
111
+ if (dir) {
112
+ let input = dir === 'x' ? inputXRef : inputYRef;
113
+ focusInput(input);
114
+ setFocusedInput(dir);
114
115
  }
115
116
  }
116
117
  });
@@ -118,7 +119,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
118
119
  let moveHandler = {
119
120
  onMoveStart() {
120
121
  currentPosition.current = null;
121
- stateRef.current.setDragging(true);
122
+ state.setDragging(true);
122
123
  },
123
124
  onMove({deltaX, deltaY, pointerType, shiftKey}) {
124
125
  let {
@@ -132,7 +133,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
132
133
  yChannelStep,
133
134
  getThumbPosition,
134
135
  setColorFromPoint
135
- } = stateRef.current;
136
+ } = state;
136
137
  if (currentPosition.current == null) {
137
138
  currentPosition.current = getThumbPosition();
138
139
  }
@@ -150,9 +151,10 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
150
151
  } else if (deltaY < 0) {
151
152
  incrementY(deltaYValue);
152
153
  }
153
- valueChangedViaKeyboard.current = valueChanged;
154
+ setValueChangedViaKeyboard(valueChanged);
154
155
  // set the focused input based on which axis has the greater delta
155
- focusedInputRef.current = valueChanged && Math.abs(deltaY) > Math.abs(deltaX) ? inputYRef.current : inputXRef.current;
156
+ focusedInput = valueChanged && Math.abs(deltaY) > Math.abs(deltaX) ? 'y' : 'x';
157
+ setFocusedInput(focusedInput);
156
158
  } else {
157
159
  currentPosition.current.x += (direction === 'rtl' ? -1 : 1) * deltaX / width ;
158
160
  currentPosition.current.y += deltaY / height;
@@ -161,18 +163,17 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
161
163
  },
162
164
  onMoveEnd() {
163
165
  isOnColorArea.current = undefined;
164
- stateRef.current.setDragging(false);
165
- focusInput(focusedInputRef.current ? focusedInputRef : inputXRef);
166
+ state.setDragging(false);
167
+ let input = focusedInput === 'x' ? inputXRef : inputYRef;
168
+ focusInput(input);
166
169
  }
167
170
  };
168
171
  let {moveProps: movePropsThumb} = useMove(moveHandler);
169
172
 
170
- let valueChangedViaKeyboard = useRef<boolean>(false);
171
173
  let {focusWithinProps} = useFocusWithin({
172
174
  onFocusWithinChange: (focusWithin:boolean) => {
173
175
  if (!focusWithin) {
174
- valueChangedViaKeyboard.current = false;
175
- focusedInputRef.current === undefined;
176
+ setValueChangedViaKeyboard(false);
176
177
  }
177
178
  }
178
179
  });
@@ -200,7 +201,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
200
201
  let onThumbDown = (id: number | null) => {
201
202
  if (!state.isDragging) {
202
203
  currentPointer.current = id;
203
- valueChangedViaKeyboard.current = false;
204
+ setValueChangedViaKeyboard(false);
204
205
  focusInput();
205
206
  state.setDragging(true);
206
207
  if (typeof PointerEvent !== 'undefined') {
@@ -215,7 +216,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
215
216
  let onThumbUp = (e) => {
216
217
  let id = e.pointerId ?? e.changedTouches?.[0].identifier;
217
218
  if (id === currentPointer.current) {
218
- valueChangedViaKeyboard.current = false;
219
+ setValueChangedViaKeyboard(false);
219
220
  focusInput();
220
221
  state.setDragging(false);
221
222
  currentPointer.current = undefined;
@@ -240,7 +241,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
240
241
  }
241
242
  if (x >= 0 && x <= 1 && y >= 0 && y <= 1 && !state.isDragging && currentPointer.current === undefined) {
242
243
  isOnColorArea.current = true;
243
- valueChangedViaKeyboard.current = false;
244
+ setValueChangedViaKeyboard(false);
244
245
  currentPointer.current = id;
245
246
  state.setColorFromPoint(x, y);
246
247
 
@@ -260,7 +261,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
260
261
  let id = e.pointerId ?? e.changedTouches?.[0].identifier;
261
262
  if (isOnColorArea.current && id === currentPointer.current) {
262
263
  isOnColorArea.current = false;
263
- valueChangedViaKeyboard.current = false;
264
+ setValueChangedViaKeyboard(false);
264
265
  currentPointer.current = undefined;
265
266
  state.setDragging(false);
266
267
  focusInput();
@@ -316,13 +317,13 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
316
317
 
317
318
  let {focusProps: xInputFocusProps} = useFocus({
318
319
  onFocus: () => {
319
- focusedInputRef.current = inputXRef.current;
320
+ setFocusedInput('x');
320
321
  }
321
322
  });
322
323
 
323
324
  let {focusProps: yInputFocusProps} = useFocus({
324
325
  onFocus: () => {
325
- focusedInputRef.current = inputYRef.current;
326
+ setFocusedInput('y');
326
327
  }
327
328
  });
328
329
 
@@ -330,7 +331,7 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
330
331
 
331
332
  function getAriaValueTextForChannel(channel:ColorChannel) {
332
333
  return (
333
- valueChangedViaKeyboard.current ?
334
+ valueChangedViaKeyboard ?
334
335
  stringFormatter.format('colorNameAndValue', {name: state.value.getChannelName(channel, locale), value: state.value.formatChannelValue(channel, locale)})
335
336
  :
336
337
  [
@@ -409,13 +410,13 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
409
410
  'aria-valuetext': getAriaValueTextForChannel(xChannel),
410
411
  disabled: isDisabled,
411
412
  value: state.value.getChannelValue(xChannel),
412
- tabIndex: (isMobile || !focusedInputRef.current || focusedInputRef.current === inputXRef.current ? undefined : -1),
413
+ tabIndex: (isMobile || !focusedInput || focusedInput === 'x' ? undefined : -1),
413
414
  /*
414
415
  So that only a single "2d slider" control shows up when listing form elements for screen readers,
415
416
  add aria-hidden="true" to the unfocused control when the value has not changed via the keyboard,
416
417
  but remove aria-hidden to reveal the input for each channel when the value has changed with the keyboard.
417
418
  */
418
- 'aria-hidden': (isMobile || !focusedInputRef.current || focusedInputRef.current === inputXRef.current || valueChangedViaKeyboard.current ? undefined : 'true'),
419
+ 'aria-hidden': (isMobile || !focusedInput || focusedInput === 'x' || valueChangedViaKeyboard ? undefined : 'true'),
419
420
  onChange: (e: ChangeEvent<HTMLInputElement>) => {
420
421
  state.setXValue(parseFloat(e.target.value));
421
422
  }
@@ -433,13 +434,13 @@ export function useColorArea(props: AriaColorAreaOptions, state: ColorAreaState)
433
434
  'aria-orientation': 'vertical',
434
435
  disabled: isDisabled,
435
436
  value: state.value.getChannelValue(yChannel),
436
- tabIndex: (isMobile || (focusedInputRef.current && focusedInputRef.current === inputYRef.current) ? undefined : -1),
437
+ tabIndex: (isMobile || focusedInput === 'y' ? undefined : -1),
437
438
  /*
438
439
  So that only a single "2d slider" control shows up when listing form elements for screen readers,
439
440
  add aria-hidden="true" to the unfocused input when the value has not changed via the keyboard,
440
441
  but remove aria-hidden to reveal the input for each channel when the value has changed with the keyboard.
441
442
  */
442
- 'aria-hidden': (isMobile || (focusedInputRef.current && focusedInputRef.current === inputYRef.current) || valueChangedViaKeyboard.current ? undefined : 'true'),
443
+ 'aria-hidden': (isMobile || focusedInput === 'y' || valueChangedViaKeyboard ? undefined : 'true'),
443
444
  onChange: (e: ChangeEvent<HTMLInputElement>) => {
444
445
  state.setYValue(parseFloat(e.target.value));
445
446
  }
@@ -56,9 +56,6 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
56
56
  }
57
57
  }, [inputRef]);
58
58
 
59
- let stateRef = useRef<ColorWheelState>(null);
60
- stateRef.current = state;
61
-
62
59
  let currentPosition = useRef<{x: number, y: number}>(null);
63
60
 
64
61
  let {keyboardProps} = useKeyboard({
@@ -71,18 +68,18 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
71
68
  // same handling as useMove, don't need to stop propagation, useKeyboard will do that for us
72
69
  e.preventDefault();
73
70
  // remember to set this and unset it so that onChangeEnd is fired
74
- stateRef.current.setDragging(true);
71
+ state.setDragging(true);
75
72
  switch (e.key) {
76
73
  case 'PageUp':
77
74
  e.preventDefault();
78
- state.increment(stateRef.current.pageStep);
75
+ state.increment(state.pageStep);
79
76
  break;
80
77
  case 'PageDown':
81
78
  e.preventDefault();
82
- state.decrement(stateRef.current.pageStep);
79
+ state.decrement(state.pageStep);
83
80
  break;
84
81
  }
85
- stateRef.current.setDragging(false);
82
+ state.setDragging(false);
86
83
  }
87
84
  });
88
85
 
@@ -93,18 +90,18 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
93
90
  },
94
91
  onMove({deltaX, deltaY, pointerType, shiftKey}) {
95
92
  if (currentPosition.current == null) {
96
- currentPosition.current = stateRef.current.getThumbPosition(thumbRadius);
93
+ currentPosition.current = state.getThumbPosition(thumbRadius);
97
94
  }
98
95
  currentPosition.current.x += deltaX;
99
96
  currentPosition.current.y += deltaY;
100
97
  if (pointerType === 'keyboard') {
101
98
  if (deltaX > 0 || deltaY < 0) {
102
- state.increment(shiftKey ? stateRef.current.pageStep : stateRef.current.step);
99
+ state.increment(shiftKey ? state.pageStep : state.step);
103
100
  } else if (deltaX < 0 || deltaY > 0) {
104
- state.decrement(shiftKey ? stateRef.current.pageStep : stateRef.current.step);
101
+ state.decrement(shiftKey ? state.pageStep : state.step);
105
102
  }
106
103
  } else {
107
- stateRef.current.setHueFromPoint(currentPosition.current.x, currentPosition.current.y, thumbRadius);
104
+ state.setHueFromPoint(currentPosition.current.x, currentPosition.current.y, thumbRadius);
108
105
  }
109
106
  },
110
107
  onMoveEnd() {
@@ -175,7 +172,7 @@ export function useColorWheel(props: AriaColorWheelOptions, state: ColorWheelSta
175
172
  if (innerRadius < radius && radius < outerRadius && !state.isDragging && currentPointer.current === undefined) {
176
173
  isOnTrack.current = true;
177
174
  currentPointer.current = id;
178
- stateRef.current.setHueFromPoint(x, y, radius);
175
+ state.setHueFromPoint(x, y, radius);
179
176
 
180
177
  focusInput();
181
178
  state.setDragging(true);