downshift 5.4.3 → 5.4.7

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/README.md CHANGED
@@ -7,10 +7,11 @@
7
7
  <p align="center" style="font-size: 1.2rem;">Primitives to build simple, flexible, WAI-ARIA compliant React
8
8
  autocomplete, combobox or select dropdown components.</p>
9
9
 
10
- > See
11
- > [the intro blog post](https://kentcdodds.com/blog/introducing-downshift-for-react)
12
- > and
13
- > [Episode 79 of the Full Stack Radio podcast](https://simplecast.com/s/f2e65eaf)
10
+ > [Read the docs](https://downshift-js.com)
11
+ > |
12
+ > [See the intro blog post](https://kentcdodds.com/blog/introducing-downshift-for-react)
13
+ > |
14
+ > [Listen to the Episode 79 of the Full Stack Radio podcast](https://simplecast.com/s/f2e65eaf)
14
15
 
15
16
  <hr />
16
17
 
@@ -1419,12 +1420,13 @@ Thanks goes to these people ([emoji key][emojis]):
1419
1420
  <tr>
1420
1421
  <td align="center"><a href="https://github.com/mattleonowicz"><img src="https://avatars3.githubusercontent.com/u/9438872?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Leonowicz</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mattleonowicz" title="Code">💻</a></td>
1421
1422
  <td align="center"><a href="https://github.com/atomicpages"><img src="https://avatars2.githubusercontent.com/u/1824291?v=4" width="100px;" alt=""/><br /><sub><b>Dennis Thompson</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=atomicpages" title="Tests">⚠️</a></td>
1423
+ <td align="center"><a href="https://mayicodefuture.live"><img src="https://avatars1.githubusercontent.com/u/32408893?v=4" width="100px;" alt=""/><br /><sub><b>Maksym Boytsov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mayicodefuture" title="Code">💻</a></td>
1424
+ <td align="center"><a href="http://dataart.com"><img src="https://avatars1.githubusercontent.com/u/5685800?v=4" width="100px;" alt=""/><br /><sub><b>Sergey Skrynnikov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=IwalkAlone" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=IwalkAlone" title="Tests">⚠️</a></td>
1422
1425
  </tr>
1423
1426
  </table>
1424
1427
 
1425
1428
  <!-- markdownlint-enable -->
1426
1429
  <!-- prettier-ignore-end -->
1427
-
1428
1430
  <!-- ALL-CONTRIBUTORS-LIST:END -->
1429
1431
 
1430
1432
  This project follows the [all-contributors][all-contributors] specification.
@@ -356,7 +356,12 @@ function getNextWrappingIndex(moveAmount, baseIndex, itemCount, getItemNodeFromI
356
356
  }
357
357
 
358
358
  var nonDisabledNewIndex = getNextNonDisabledIndex(moveAmount, newIndex, itemCount, getItemNodeFromIndex, circular);
359
- return nonDisabledNewIndex === -1 ? baseIndex : nonDisabledNewIndex;
359
+
360
+ if (nonDisabledNewIndex === -1) {
361
+ return baseIndex >= itemCount ? -1 : baseIndex;
362
+ }
363
+
364
+ return nonDisabledNewIndex;
360
365
  }
361
366
  /**
362
367
  * Returns the next index in the list of an item that is not disabled.
@@ -635,7 +640,7 @@ function () {
635
640
  // See https://github.com/downshift-js/downshift/issues/217 for more info.
636
641
 
637
642
  if (!isStateToSetFunction && stateToSet.hasOwnProperty('inputValue')) {
638
- _this.props.onInputValueChange(stateToSet.inputValue, _extends(_extends({}, _this.getStateAndHelpers()), stateToSet));
643
+ _this.props.onInputValueChange(stateToSet.inputValue, _extends({}, _this.getStateAndHelpers(), stateToSet));
639
644
  }
640
645
 
641
646
  return _this.setState(function (state) {
@@ -685,7 +690,7 @@ function () {
685
690
  // earlier, so we'll call it now that we know what the inputValue state will be.
686
691
 
687
692
  if (isStateToSetFunction && newStateToSet.hasOwnProperty('inputValue')) {
688
- _this.props.onInputValueChange(newStateToSet.inputValue, _extends(_extends({}, _this.getStateAndHelpers()), newStateToSet));
693
+ _this.props.onInputValueChange(newStateToSet.inputValue, _extends({}, _this.getStateAndHelpers(), newStateToSet));
689
694
  }
690
695
 
691
696
  return nextState;
@@ -840,7 +845,7 @@ function () {
840
845
  });
841
846
  }
842
847
  };
843
- _this.buttonKeyDownHandlers = _extends(_extends({}, _this.keyDownHandlers), {}, {
848
+ _this.buttonKeyDownHandlers = _extends({}, _this.keyDownHandlers, {
844
849
  ' ': function _(event) {
845
850
  event.preventDefault();
846
851
  this.toggleMenu({
@@ -848,7 +853,7 @@ function () {
848
853
  });
849
854
  }
850
855
  });
851
- _this.inputKeyDownHandlers = _extends(_extends({}, _this.keyDownHandlers), {}, {
856
+ _this.inputKeyDownHandlers = _extends({}, _this.keyDownHandlers, {
852
857
  Home: function Home(event) {
853
858
  var _this4 = this;
854
859
 
@@ -912,13 +917,13 @@ function () {
912
917
  onBlur: callAllEventHandlers(onBlur, _this.buttonHandleBlur)
913
918
  };
914
919
  var eventHandlers = rest.disabled ? {} : enabledEventHandlers;
915
- return _extends(_extends({
920
+ return _extends({
916
921
  type: 'button',
917
922
  role: 'button',
918
923
  'aria-label': isOpen ? 'close menu' : 'open menu',
919
924
  'aria-haspopup': true,
920
925
  'data-toggle': true
921
- }, eventHandlers), rest);
926
+ }, eventHandlers, rest);
922
927
  };
923
928
 
924
929
  _this.buttonHandleKeyUp = function (event) {
@@ -1010,7 +1015,7 @@ function () {
1010
1015
  /* istanbul ignore if (react-native) */
1011
1016
 
1012
1017
 
1013
- return _extends(_extends({
1018
+ return _extends({
1014
1019
  'aria-autocomplete': 'list',
1015
1020
  'aria-activedescendant': isOpen && typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this.getItemId(highlightedIndex) : null,
1016
1021
  'aria-controls': isOpen ? _this.menuId : null,
@@ -1020,7 +1025,7 @@ function () {
1020
1025
  autoComplete: 'off',
1021
1026
  value: inputValue,
1022
1027
  id: _this.inputId
1023
- }, eventHandlers), rest);
1028
+ }, eventHandlers, rest);
1024
1029
  };
1025
1030
 
1026
1031
  _this.inputHandleKeyDown = function (event) {
@@ -1140,11 +1145,11 @@ function () {
1140
1145
  var eventHandlers = rest.disabled ? {
1141
1146
  onMouseDown: enabledEventHandlers.onMouseDown
1142
1147
  } : enabledEventHandlers;
1143
- return _extends(_extends({
1148
+ return _extends({
1144
1149
  id: _this.getItemId(index),
1145
1150
  role: 'option',
1146
1151
  'aria-selected': _this.getState().highlightedIndex === index
1147
- }, eventHandlers), rest);
1152
+ }, eventHandlers, rest);
1148
1153
  };
1149
1154
 
1150
1155
  _this.clearItems = function () {
@@ -1177,11 +1182,11 @@ function () {
1177
1182
 
1178
1183
  _this.internalSetState(function (_ref9) {
1179
1184
  var isOpen = _ref9.isOpen;
1180
- return _extends(_extends({
1185
+ return _extends({
1181
1186
  isOpen: !isOpen
1182
1187
  }, isOpen && {
1183
1188
  highlightedIndex: _this.props.defaultHighlightedIndex
1184
- }), otherStateToSet);
1189
+ }, otherStateToSet);
1185
1190
  }, function () {
1186
1191
  var _this$getState7 = _this.getState(),
1187
1192
  isOpen = _this$getState7.isOpen,
@@ -1829,7 +1834,7 @@ function useEnhancedReducer(reducer, initialState, props) {
1829
1834
  actionRef.current = action;
1830
1835
  state = getState(state, action.props);
1831
1836
  var changes = reducer(state, action);
1832
- var newState = action.props.stateReducer(state, _extends(_extends({}, action), {}, {
1837
+ var newState = action.props.stateReducer(state, _extends({}, action, {
1833
1838
  changes: changes
1834
1839
  }));
1835
1840
  return newState;
@@ -1918,7 +1923,7 @@ function getInitialState(props) {
1918
1923
  var highlightedIndex = getInitialValue(props, 'highlightedIndex');
1919
1924
  var inputValue = getInitialValue(props, 'inputValue');
1920
1925
  return {
1921
- highlightedIndex: highlightedIndex < 0 && selectedItem ? props.items.indexOf(selectedItem) : highlightedIndex,
1926
+ highlightedIndex: highlightedIndex < 0 && selectedItem && isOpen ? props.items.indexOf(selectedItem) : highlightedIndex,
1922
1927
  isOpen: isOpen,
1923
1928
  selectedItem: selectedItem,
1924
1929
  inputValue: inputValue
@@ -2029,6 +2034,9 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
2029
2034
  */
2030
2035
 
2031
2036
  function useGetterPropsCalledChecker() {
2037
+ var isNotProduction = process.env.NODE_ENV !== 'production';
2038
+ var isInitialMountRef = react.useRef(true);
2039
+
2032
2040
  for (var _len = arguments.length, propKeys = new Array(_len), _key = 0; _key < _len; _key++) {
2033
2041
  propKeys[_key] = arguments[_key];
2034
2042
  }
@@ -2037,33 +2045,32 @@ function useGetterPropsCalledChecker() {
2037
2045
  acc[propKey] = {};
2038
2046
  return acc;
2039
2047
  }, {}));
2048
+ react.useEffect(function () {
2049
+ if (!isNotProduction) {
2050
+ return;
2051
+ }
2040
2052
 
2041
- if (process.env.NODE_ENV !== 'production') {
2042
2053
  Object.keys(getterPropsCalledRef.current).forEach(function (propKey) {
2043
- getterPropsCalledRef.current[propKey] = null;
2044
- });
2045
- }
2054
+ var propCallInfo = getterPropsCalledRef.current[propKey];
2046
2055
 
2047
- react.useEffect(function () {
2048
- if (process.env.NODE_ENV !== 'production') {
2049
- Object.keys(getterPropsCalledRef.current).forEach(function (propKey) {
2050
- if (!getterPropsCalledRef.current[propKey]) {
2056
+ if (isInitialMountRef.current) {
2057
+ if (!Object.keys(propCallInfo).length) {
2051
2058
  // eslint-disable-next-line no-console
2052
2059
  console.error("downshift: You forgot to call the " + propKey + " getter function on your component / element.");
2053
2060
  return;
2054
2061
  }
2062
+ }
2055
2063
 
2056
- var _getterPropsCalledRef = getterPropsCalledRef.current[propKey],
2057
- suppressRefError = _getterPropsCalledRef.suppressRefError,
2058
- refKey = _getterPropsCalledRef.refKey,
2059
- elementRef = _getterPropsCalledRef.elementRef;
2064
+ var suppressRefError = propCallInfo.suppressRefError,
2065
+ refKey = propCallInfo.refKey,
2066
+ elementRef = propCallInfo.elementRef;
2060
2067
 
2061
- if ((!elementRef || !elementRef.current) && !suppressRefError) {
2062
- // eslint-disable-next-line no-console
2063
- console.error("downshift: The ref prop \"" + refKey + "\" from " + propKey + " was not applied correctly on your element.");
2064
- }
2065
- });
2066
- }
2068
+ if ((!elementRef || !elementRef.current) && !suppressRefError) {
2069
+ // eslint-disable-next-line no-console
2070
+ console.error("downshift: The ref prop \"" + refKey + "\" from " + propKey + " was not applied correctly on your element.");
2071
+ }
2072
+ });
2073
+ isInitialMountRef.current = false;
2067
2074
  });
2068
2075
  var setGetterPropCallInfo = react.useCallback(function (propKey, suppressRefError, refKey, elementRef) {
2069
2076
  if (process.env.NODE_ENV !== 'production') {
@@ -2171,7 +2178,7 @@ function getA11yStatusMessage$1(_ref) {
2171
2178
  return '';
2172
2179
  }
2173
2180
 
2174
- var defaultProps$1 = _extends(_extends({}, defaultProps), {}, {
2181
+ var defaultProps$1 = _extends({}, defaultProps, {
2175
2182
  getA11yStatusMessage: getA11yStatusMessage$1
2176
2183
  });
2177
2184
 
@@ -2397,7 +2404,7 @@ function downshiftSelectReducer(state, action) {
2397
2404
  throw new Error('Reducer called without proper action type.');
2398
2405
  }
2399
2406
 
2400
- return _extends(_extends({}, state), changes);
2407
+ return _extends({}, state, changes);
2401
2408
  }
2402
2409
  /* eslint-enable complexity */
2403
2410
 
@@ -2417,7 +2424,7 @@ function useSelect(userProps) {
2417
2424
  } // Props defaults and destructuring.
2418
2425
 
2419
2426
 
2420
- var props = _extends(_extends({}, defaultProps$1), userProps);
2427
+ var props = _extends({}, defaultProps$1, userProps);
2421
2428
 
2422
2429
  var items = props.items,
2423
2430
  scrollIntoView = props.scrollIntoView,
@@ -2733,11 +2740,11 @@ function useSelect(userProps) {
2733
2740
 
2734
2741
  var latestState = latest.current.state;
2735
2742
  setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
2736
- return _extends(_extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
2743
+ return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
2737
2744
  menuRef.current = menuNode;
2738
2745
  }), _extends2.id = elementIdsRef.current.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = elementIdsRef.current.labelId, _extends2.tabIndex = -1, _extends2), latestState.isOpen && latestState.highlightedIndex > -1 && {
2739
2746
  'aria-activedescendant': elementIdsRef.current.getItemId(latestState.highlightedIndex)
2740
- }), {}, {
2747
+ }, {
2741
2748
  onMouseLeave: callAllEventHandlers(onMouseLeave, function menuHandleMouseLeave() {
2742
2749
  dispatch({
2743
2750
  type: MenuMouseLeave
@@ -2968,7 +2975,7 @@ function getInitialState$1(props) {
2968
2975
  inputValue = props.itemToString(selectedItem);
2969
2976
  }
2970
2977
 
2971
- return _extends(_extends({}, initialState), {}, {
2978
+ return _extends({}, initialState, {
2972
2979
  inputValue: inputValue
2973
2980
  });
2974
2981
  }
@@ -3033,20 +3040,21 @@ function useControlledReducer$1(reducer, initialState, props) {
3033
3040
  dispatch = _useEnhancedReducer[1]; // ToDo: if needed, make same approach as selectedItemChanged from Downshift.
3034
3041
 
3035
3042
 
3036
- if (isControlledProp(props, 'selectedItem')) {
3037
- if (previousSelectedItemRef.current !== props.selectedItem) {
3038
- dispatch({
3039
- type: ControlledPropUpdatedSelectedItem,
3040
- inputValue: props.itemToString(props.selectedItem)
3041
- });
3042
- }
3043
-
3044
- previousSelectedItemRef.current = state.selectedItem === previousSelectedItemRef.current ? props.selectedItem : state.selectedItem;
3045
- }
3043
+ react.useEffect(function () {
3044
+ if (isControlledProp(props, 'selectedItem')) {
3045
+ if (previousSelectedItemRef.current !== props.selectedItem) {
3046
+ dispatch({
3047
+ type: ControlledPropUpdatedSelectedItem,
3048
+ inputValue: props.itemToString(props.selectedItem)
3049
+ });
3050
+ }
3046
3051
 
3052
+ previousSelectedItemRef.current = state.selectedItem === previousSelectedItemRef.current ? props.selectedItem : state.selectedItem;
3053
+ }
3054
+ });
3047
3055
  return [getState(state, props), dispatch];
3048
3056
  }
3049
- var defaultProps$2 = _extends(_extends({}, defaultProps), {}, {
3057
+ var defaultProps$2 = _extends({}, defaultProps, {
3050
3058
  getA11yStatusMessage: getA11yStatusMessage,
3051
3059
  circularNavigation: true
3052
3060
  });
@@ -3211,7 +3219,7 @@ function downshiftUseComboboxReducer(state, action) {
3211
3219
  throw new Error('Reducer called without proper action type.');
3212
3220
  }
3213
3221
 
3214
- return _extends(_extends({}, state), changes);
3222
+ return _extends({}, state, changes);
3215
3223
  }
3216
3224
  /* eslint-enable complexity */
3217
3225
 
@@ -3231,7 +3239,7 @@ function useCombobox(userProps) {
3231
3239
  } // Props defaults and destructuring.
3232
3240
 
3233
3241
 
3234
- var props = _extends(_extends({}, defaultProps$2), userProps);
3242
+ var props = _extends({}, defaultProps$2, userProps);
3235
3243
 
3236
3244
  var initialIsOpen = props.initialIsOpen,
3237
3245
  defaultIsOpen = props.defaultIsOpen,
@@ -3267,8 +3275,7 @@ function useCombobox(userProps) {
3267
3275
 
3268
3276
  var previousResultCountRef = react.useRef(); // used for checking when props are moving from controlled to uncontrolled.
3269
3277
 
3270
- var prevPropsRef = react.useRef(props); // used to store information about getter props being called on render.
3271
- // utility callback to get item element.
3278
+ var prevPropsRef = react.useRef(props); // utility callback to get item element.
3272
3279
 
3273
3280
  var latest = useLatestRef({
3274
3281
  state: state,
@@ -3484,7 +3491,7 @@ function useCombobox(userProps) {
3484
3491
 
3485
3492
  var onSelectKey = 'onClick';
3486
3493
  var customClickHandler = onClick;
3487
- return _extends(_extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (itemNode) {
3494
+ return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (itemNode) {
3488
3495
  if (itemNode) {
3489
3496
  itemRefs.current[elementIdsRef.current.getItemId(itemIndex)] = itemNode;
3490
3497
  }
@@ -3505,7 +3512,11 @@ function useCombobox(userProps) {
3505
3512
  type: ItemClick$1,
3506
3513
  index: index
3507
3514
  });
3508
- }), _ref4)), rest);
3515
+
3516
+ if (inputRef.current) {
3517
+ inputRef.current.focus();
3518
+ }
3519
+ }), _ref4), rest);
3509
3520
  }, [dispatch, latest]);
3510
3521
  var getToggleButtonProps = react.useCallback(function (_temp4) {
3511
3522
  var _extends4;
@@ -3528,11 +3539,11 @@ function useCombobox(userProps) {
3528
3539
  }
3529
3540
  };
3530
3541
 
3531
- return _extends(_extends((_extends4 = {}, _extends4[refKey] = handleRefs(ref, function (toggleButtonNode) {
3542
+ return _extends((_extends4 = {}, _extends4[refKey] = handleRefs(ref, function (toggleButtonNode) {
3532
3543
  toggleButtonRef.current = toggleButtonNode;
3533
3544
  }), _extends4.id = elementIdsRef.current.toggleButtonId, _extends4.tabIndex = -1, _extends4), !rest.disabled && _extends({}, {
3534
3545
  onClick: callAllEventHandlers(onClick, toggleButtonHandleClick)
3535
- })), rest);
3546
+ }), rest);
3536
3547
  }, [dispatch, latest]);
3537
3548
  var getInputProps = react.useCallback(function (_temp5, _temp6) {
3538
3549
  var _extends5;
@@ -3592,17 +3603,17 @@ function useCombobox(userProps) {
3592
3603
  /* istanbul ignore if (react-native) */
3593
3604
 
3594
3605
 
3595
- return _extends(_extends(_extends((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
3606
+ return _extends((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
3596
3607
  inputRef.current = inputNode;
3597
3608
  }), _extends5.id = elementIdsRef.current.inputId, _extends5['aria-autocomplete'] = 'list', _extends5['aria-controls'] = elementIdsRef.current.menuId, _extends5), latestState.isOpen && latestState.highlightedIndex > -1 && {
3598
3609
  'aria-activedescendant': elementIdsRef.current.getItemId(latestState.highlightedIndex)
3599
- }), {}, {
3610
+ }, {
3600
3611
  'aria-labelledby': elementIdsRef.current.labelId,
3601
3612
  // https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
3602
3613
  // revert back since autocomplete="nope" is ignored on latest Chrome and Opera
3603
3614
  autoComplete: 'off',
3604
3615
  value: latestState.inputValue
3605
- }, eventHandlers), rest);
3616
+ }, eventHandlers, rest);
3606
3617
  }, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo]);
3607
3618
  var getComboboxProps = react.useCallback(function (_temp7, _temp8) {
3608
3619
  var _extends6;
@@ -3955,7 +3966,7 @@ function downshiftMultipleSelectionReducer(state, action) {
3955
3966
  throw new Error('Reducer called without proper action type.');
3956
3967
  }
3957
3968
 
3958
- return _extends(_extends({}, state), changes);
3969
+ return _extends({}, state, changes);
3959
3970
  }
3960
3971
 
3961
3972
  useMultipleSelection.stateChangeTypes = stateChangeTypes$3;
@@ -3966,7 +3977,7 @@ function useMultipleSelection(userProps) {
3966
3977
  }
3967
3978
 
3968
3979
  // Props defaults and destructuring.
3969
- var props = _extends(_extends({}, defaultProps$3), userProps);
3980
+ var props = _extends({}, defaultProps$3, userProps);
3970
3981
 
3971
3982
  var getA11yRemovalMessage = props.getA11yRemovalMessage,
3972
3983
  itemToString = props.itemToString,
@@ -4135,7 +4146,7 @@ function useMultipleSelection(userProps) {
4135
4146
  suppressRefError = _ref5$suppressRefErro === void 0 ? false : _ref5$suppressRefErro;
4136
4147
 
4137
4148
  setGetterPropCallInfo('getDropdownProps', suppressRefError, refKey, dropdownRef);
4138
- return _extends(_extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (dropdownNode) {
4149
+ return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (dropdownNode) {
4139
4150
  if (dropdownNode) {
4140
4151
  dropdownRef.current = dropdownNode;
4141
4152
  }
@@ -4152,7 +4163,7 @@ function useMultipleSelection(userProps) {
4152
4163
  type: DropdownClick
4153
4164
  });
4154
4165
  })
4155
- }), rest);
4166
+ }, rest);
4156
4167
  }, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]); // returns
4157
4168
 
4158
4169
  var addSelectedItem = react.useCallback(function (selectedItem) {