downshift 5.1.0-beta.0 → 5.2.1

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.
@@ -3,7 +3,7 @@ import _extends from '@babel/runtime/helpers/esm/extends';
3
3
  import _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';
4
4
  import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';
5
5
  import PropTypes from 'prop-types';
6
- import { cloneElement, Component, useCallback, useReducer, useRef, useEffect } from 'react';
6
+ import { cloneElement, Component, useState, useRef, useEffect } from 'react';
7
7
  import { isForwardRef } from 'react-is';
8
8
  import computeScrollIntoView from 'compute-scroll-into-view';
9
9
 
@@ -164,7 +164,8 @@ function resetIdCounter() {
164
164
 
165
165
  function getA11yStatusMessage(_ref2) {
166
166
  var isOpen = _ref2.isOpen,
167
- resultCount = _ref2.resultCount;
167
+ resultCount = _ref2.resultCount,
168
+ previousResultCount = _ref2.previousResultCount;
168
169
 
169
170
  if (!isOpen) {
170
171
  return '';
@@ -174,7 +175,11 @@ function getA11yStatusMessage(_ref2) {
174
175
  return 'No results are available.';
175
176
  }
176
177
 
177
- return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter key to select.";
178
+ if (resultCount !== previousResultCount) {
179
+ return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter key to select.";
180
+ }
181
+
182
+ return '';
178
183
  }
179
184
  /**
180
185
  * Takes an argument and if it's an array, returns the first item in the array
@@ -498,8 +503,12 @@ var stateChangeTypes = /*#__PURE__*/Object.freeze({
498
503
  touchEnd: touchEnd
499
504
  });
500
505
 
501
- var Downshift = /*#__PURE__*/function () {
502
- var Downshift = /*#__PURE__*/function (_Component) {
506
+ var Downshift =
507
+ /*#__PURE__*/
508
+ function () {
509
+ var Downshift =
510
+ /*#__PURE__*/
511
+ function (_Component) {
503
512
  _inheritsLoose(Downshift, _Component);
504
513
 
505
514
  function Downshift(_props) {
@@ -773,6 +782,10 @@ var Downshift = /*#__PURE__*/function () {
773
782
  }
774
783
  },
775
784
  Enter: function Enter(event) {
785
+ if (event.which === 229) {
786
+ return;
787
+ }
788
+
776
789
  var _this$getState2 = this.getState(),
777
790
  isOpen = _this$getState2.isOpen,
778
791
  highlightedIndex = _this$getState2.highlightedIndex;
@@ -1665,6 +1678,65 @@ var dropdownDefaultStateValues = {
1665
1678
  inputValue: ''
1666
1679
  };
1667
1680
 
1681
+ function callOnChangeProps(action, state, newState) {
1682
+ var props = action.props,
1683
+ type = action.type;
1684
+ var changes = {};
1685
+ Object.keys(state).forEach(function (key) {
1686
+ invokeOnChangeHandler(key, props, state, newState);
1687
+
1688
+ if (newState[key] !== state[key]) {
1689
+ changes[key] = newState[key];
1690
+ }
1691
+ });
1692
+
1693
+ if (props.onStateChange && Object.keys(changes).length) {
1694
+ props.onStateChange(_extends({
1695
+ type: type
1696
+ }, changes));
1697
+ }
1698
+ }
1699
+
1700
+ function invokeOnChangeHandler(key, props, state, newState) {
1701
+ var handler = "on" + capitalizeString(key) + "Change";
1702
+
1703
+ if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1704
+ props[handler](newState);
1705
+ }
1706
+ }
1707
+ /**
1708
+ * Default state reducer that returns the changes.
1709
+ *
1710
+ * @param {Object} s state.
1711
+ * @param {Object} a action with changes.
1712
+ * @returns {Object} changes.
1713
+ */
1714
+
1715
+
1716
+ function stateReducer(s, a) {
1717
+ return a.changes;
1718
+ }
1719
+ /**
1720
+ * Returns a message to be added to aria-live region when item is selected.
1721
+ *
1722
+ * @param {Object} selectionParameters Parameters required to build the message.
1723
+ * @returns {string} The a11y message.
1724
+ */
1725
+
1726
+
1727
+ function getA11ySelectionMessage(selectionParameters) {
1728
+ var selectedItem = selectionParameters.selectedItem,
1729
+ itemToStringLocal = selectionParameters.itemToString;
1730
+ return selectedItem ? itemToStringLocal(selectedItem) + " has been selected." : '';
1731
+ }
1732
+ /**
1733
+ * Debounced call for updating the a11y message.
1734
+ */
1735
+
1736
+
1737
+ var updateA11yStatus = debounce(function (getA11yMessage, document) {
1738
+ setStatus(getA11yMessage(), document);
1739
+ }, 200);
1668
1740
  function getElementIds(_ref) {
1669
1741
  var id = _ref.id,
1670
1742
  labelId = _ref.labelId,
@@ -1681,7 +1753,6 @@ function getElementIds(_ref) {
1681
1753
  toggleButtonId: toggleButtonId || uniqueId + "-toggle-button"
1682
1754
  };
1683
1755
  }
1684
-
1685
1756
  function getItemIndex(index, item, items) {
1686
1757
  if (index !== undefined) {
1687
1758
  return index;
@@ -1710,57 +1781,39 @@ function getPropTypesValidator(caller, propTypes) {
1710
1781
  });
1711
1782
  };
1712
1783
  }
1713
-
1714
1784
  function isAcceptedCharacterKey(key) {
1715
1785
  return /^\S{1}$/.test(key);
1716
1786
  }
1717
-
1718
1787
  function capitalizeString(string) {
1719
1788
  return "" + string.slice(0, 1).toUpperCase() + string.slice(1);
1720
1789
  }
1790
+ /**
1791
+ * Computes the controlled state using a the previous state, props,
1792
+ * two reducers, one from downshift and an optional one from the user.
1793
+ * Also calls the onChange handlers for state values that have changed.
1794
+ *
1795
+ * @param {Function} reducer Reducer function from downshift.
1796
+ * @param {Object} initialState Initial state of the hook.
1797
+ * @param {Object} props The hook props.
1798
+ * @returns {Array} An array with the state and an action dispatcher.
1799
+ */
1721
1800
 
1722
- function invokeOnChangeHandler(key, props, state, newState) {
1723
- var handler = "on" + capitalizeString(key) + "Change";
1724
-
1725
- if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1726
- props[handler](newState);
1727
- }
1728
- }
1729
-
1730
- function callOnChangeProps(action, state, newState) {
1731
- var props = action.props,
1732
- type = action.type;
1733
- var changes = {};
1734
- Object.keys(state).forEach(function (key) {
1735
- invokeOnChangeHandler(key, props, state, newState);
1801
+ function useControlledState(reducer, initialState, props) {
1802
+ var _useState = useState(initialState),
1803
+ uncontrolledState = _useState[0],
1804
+ setState = _useState[1];
1736
1805
 
1737
- if (newState[key] !== state[key]) {
1738
- changes[key] = newState[key];
1739
- }
1740
- });
1806
+ var state = getState(uncontrolledState, props);
1741
1807
 
1742
- if (props.onStateChange && Object.keys(changes).length) {
1743
- props.onStateChange(_extends({
1744
- type: type
1745
- }, changes));
1746
- }
1747
- }
1748
-
1749
- function useEnhancedReducer(reducer, initialState, props) {
1750
- var enhancedReducer = useCallback(function (state, action) {
1751
- state = getState(state, action.props);
1752
- var stateReduceLocal = action.props.stateReducer;
1808
+ var dispatch = function (action) {
1809
+ var stateReducerFromProps = action.props.stateReducer;
1753
1810
  var changes = reducer(state, action);
1754
- var newState = stateReduceLocal(state, _extends({}, action, {
1811
+ var newState = stateReducerFromProps(state, _extends({}, action, {
1755
1812
  changes: changes
1756
1813
  }));
1757
1814
  callOnChangeProps(action, state, newState);
1758
- return newState;
1759
- }, [reducer]);
1760
-
1761
- var _useReducer = useReducer(enhancedReducer, initialState),
1762
- state = _useReducer[0],
1763
- dispatch = _useReducer[1];
1815
+ setState(newState);
1816
+ };
1764
1817
 
1765
1818
  return [getState(state, props), function dispatchWithProps(action) {
1766
1819
  return dispatch(_extends({
@@ -1768,32 +1821,6 @@ function useEnhancedReducer(reducer, initialState, props) {
1768
1821
  }, action));
1769
1822
  }];
1770
1823
  }
1771
- /**
1772
- * Default state reducer that returns the changes.
1773
- *
1774
- * @param {Object} s state.
1775
- * @param {Object} a action with changes.
1776
- * @returns {Object} changes.
1777
- */
1778
-
1779
-
1780
- function stateReducer(s, a) {
1781
- return a.changes;
1782
- }
1783
- /**
1784
- * Returns a message to be added to aria-live region when item is selected.
1785
- *
1786
- * @param {Object} selectionParameters Parameters required to build the message.
1787
- * @returns {string} The a11y message.
1788
- */
1789
-
1790
-
1791
- function getA11ySelectionMessage(selectionParameters) {
1792
- var selectedItem = selectionParameters.selectedItem,
1793
- itemToStringLocal = selectionParameters.itemToString;
1794
- return itemToStringLocal(selectedItem) + " has been selected.";
1795
- }
1796
-
1797
1824
  var defaultProps = {
1798
1825
  itemToString: itemToString,
1799
1826
  stateReducer: stateReducer,
@@ -1804,7 +1831,6 @@ var defaultProps = {
1804
1831
  /* istanbul ignore next (ssr) */
1805
1832
  ? {} : window
1806
1833
  };
1807
-
1808
1834
  function getDefaultValue(props, propKey, defaultStateValues) {
1809
1835
  if (defaultStateValues === void 0) {
1810
1836
  defaultStateValues = dropdownDefaultStateValues;
@@ -1818,7 +1844,6 @@ function getDefaultValue(props, propKey, defaultStateValues) {
1818
1844
 
1819
1845
  return defaultStateValues[propKey];
1820
1846
  }
1821
-
1822
1847
  function getInitialValue(props, propKey, defaultStateValues) {
1823
1848
  if (defaultStateValues === void 0) {
1824
1849
  defaultStateValues = dropdownDefaultStateValues;
@@ -1836,7 +1861,6 @@ function getInitialValue(props, propKey, defaultStateValues) {
1836
1861
 
1837
1862
  return getDefaultValue(props, propKey, defaultStateValues);
1838
1863
  }
1839
-
1840
1864
  function getInitialState(props) {
1841
1865
  var selectedItem = getInitialValue(props, 'selectedItem');
1842
1866
  var isOpen = getInitialValue(props, 'isOpen');
@@ -1849,7 +1873,6 @@ function getInitialState(props) {
1849
1873
  inputValue: inputValue
1850
1874
  };
1851
1875
  }
1852
-
1853
1876
  function getHighlightedIndexOnOpen(props, state, offset, getItemNodeFromIndex) {
1854
1877
  var items = props.items,
1855
1878
  initialHighlightedIndex = props.initialHighlightedIndex,
@@ -1956,7 +1979,8 @@ var propTypes = {
1956
1979
 
1957
1980
  function getA11yStatusMessage$1(_ref) {
1958
1981
  var isOpen = _ref.isOpen,
1959
- resultCount = _ref.resultCount;
1982
+ resultCount = _ref.resultCount,
1983
+ previousResultCount = _ref.previousResultCount;
1960
1984
 
1961
1985
  if (!isOpen) {
1962
1986
  return '';
@@ -1966,7 +1990,11 @@ function getA11yStatusMessage$1(_ref) {
1966
1990
  return 'No results are available.';
1967
1991
  }
1968
1992
 
1969
- return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter or Space Bar keys to select.";
1993
+ if (resultCount !== previousResultCount) {
1994
+ return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter or Space Bar keys to select.";
1995
+ }
1996
+
1997
+ return '';
1970
1998
  }
1971
1999
 
1972
2000
  var defaultProps$1 = _extends({}, defaultProps, {
@@ -2218,24 +2246,23 @@ function useSelect(userProps) {
2218
2246
  var props = _extends({}, defaultProps$1, {}, userProps);
2219
2247
 
2220
2248
  var items = props.items,
2221
- itemToString = props.itemToString,
2222
- getA11yStatusMessage = props.getA11yStatusMessage,
2223
- getA11ySelectionMessage = props.getA11ySelectionMessage,
2224
2249
  scrollIntoView = props.scrollIntoView,
2225
2250
  environment = props.environment,
2226
2251
  initialIsOpen = props.initialIsOpen,
2227
- defaultIsOpen = props.defaultIsOpen; // Initial state depending on controlled props.
2252
+ defaultIsOpen = props.defaultIsOpen,
2253
+ itemToString = props.itemToString,
2254
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
2255
+ getA11yStatusMessage = props.getA11yStatusMessage; // Initial state depending on controlled props.
2228
2256
 
2229
2257
  var initialState = getInitialState(props); // Reducer init.
2230
2258
 
2231
- var _useEnhancedReducer = useEnhancedReducer(downshiftSelectReducer, initialState, props),
2232
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2233
- isOpen = _useEnhancedReducer$.isOpen,
2234
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2235
- selectedItem = _useEnhancedReducer$.selectedItem,
2236
- inputValue = _useEnhancedReducer$.inputValue,
2237
- dispatch = _useEnhancedReducer[1];
2238
- /* Refs */
2259
+ var _useControlledState = useControlledState(downshiftSelectReducer, initialState, props),
2260
+ _useControlledState$ = _useControlledState[0],
2261
+ isOpen = _useControlledState$.isOpen,
2262
+ highlightedIndex = _useControlledState$.highlightedIndex,
2263
+ selectedItem = _useControlledState$.selectedItem,
2264
+ inputValue = _useControlledState$.inputValue,
2265
+ dispatch = _useControlledState[1]; // Refs
2239
2266
 
2240
2267
 
2241
2268
  var toggleButtonRef = useRef(null);
@@ -2247,13 +2274,14 @@ function useSelect(userProps) {
2247
2274
  isMouseDown: false,
2248
2275
  isTouchMove: false
2249
2276
  });
2250
- var elementIds = useRef(getElementIds(props)); // Some utils.
2277
+ var elementIds = useRef(getElementIds(props));
2278
+ var previousResultCountRef = useRef(); // Some utils.
2251
2279
 
2252
2280
  var getItemNodeFromIndex = function (index) {
2253
2281
  return environment.document.getElementById(elementIds.current.getItemId(index));
2254
2282
  }; // Effects.
2255
2283
 
2256
- /* Sets a11y status message on changes in isOpen. */
2284
+ /* Sets a11y status message on changes in state. */
2257
2285
 
2258
2286
 
2259
2287
  useEffect(function () {
@@ -2261,16 +2289,20 @@ function useSelect(userProps) {
2261
2289
  return;
2262
2290
  }
2263
2291
 
2264
- setStatus(getA11yStatusMessage({
2265
- highlightedIndex: highlightedIndex,
2266
- inputValue: inputValue,
2267
- isOpen: isOpen,
2268
- itemToString: itemToString,
2269
- resultCount: items.length,
2270
- highlightedItem: items[highlightedIndex],
2271
- selectedItem: selectedItem
2272
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2273
- }, [isOpen]);
2292
+ var previousResultCount = previousResultCountRef.current;
2293
+ updateA11yStatus(function () {
2294
+ return getA11yStatusMessage({
2295
+ isOpen: isOpen,
2296
+ highlightedIndex: highlightedIndex,
2297
+ selectedItem: selectedItem,
2298
+ inputValue: inputValue,
2299
+ highlightedItem: items[highlightedIndex],
2300
+ resultCount: items.length,
2301
+ itemToString: itemToString,
2302
+ previousResultCount: previousResultCount
2303
+ });
2304
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2305
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
2274
2306
  /* Sets a11y status message on changes in selectedItem. */
2275
2307
 
2276
2308
  useEffect(function () {
@@ -2278,15 +2310,19 @@ function useSelect(userProps) {
2278
2310
  return;
2279
2311
  }
2280
2312
 
2281
- setStatus(getA11ySelectionMessage({
2282
- highlightedIndex: highlightedIndex,
2283
- inputValue: inputValue,
2284
- isOpen: isOpen,
2285
- itemToString: itemToString,
2286
- resultCount: items.length,
2287
- highlightedItem: items[highlightedIndex],
2288
- selectedItem: selectedItem
2289
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2313
+ var previousResultCount = previousResultCountRef.current;
2314
+ updateA11yStatus(function () {
2315
+ return getA11ySelectionMessage({
2316
+ isOpen: isOpen,
2317
+ highlightedIndex: highlightedIndex,
2318
+ selectedItem: selectedItem,
2319
+ inputValue: inputValue,
2320
+ highlightedItem: items[highlightedIndex],
2321
+ resultCount: items.length,
2322
+ itemToString: itemToString,
2323
+ previousResultCount: previousResultCount
2324
+ });
2325
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2290
2326
  }, [selectedItem]);
2291
2327
  /* Sets cleanup for the keysSoFar after 500ms. */
2292
2328
 
@@ -2343,6 +2379,13 @@ function useSelect(userProps) {
2343
2379
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2344
2380
 
2345
2381
  }, [highlightedIndex]);
2382
+ useEffect(function () {
2383
+ if (isInitialMount.current) {
2384
+ return;
2385
+ }
2386
+
2387
+ previousResultCountRef.current = items.length;
2388
+ });
2346
2389
  /* Make initial ref false. */
2347
2390
 
2348
2391
  useEffect(function () {
@@ -2666,6 +2709,51 @@ function useSelect(userProps) {
2666
2709
  };
2667
2710
  }
2668
2711
 
2712
+ var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2713
+ var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2714
+ var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2715
+ var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2716
+ var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2717
+ var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2718
+ var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2719
+ var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2720
+ var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2721
+ var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2722
+ var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2723
+ var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2724
+ var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2725
+ var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2726
+ var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2727
+ var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2728
+ var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2729
+ var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2730
+ var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2731
+ var ControlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__controlled_prop_updated_selected_item__' : 19;
2732
+
2733
+ var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2734
+ __proto__: null,
2735
+ InputKeyDownArrowDown: InputKeyDownArrowDown,
2736
+ InputKeyDownArrowUp: InputKeyDownArrowUp,
2737
+ InputKeyDownEscape: InputKeyDownEscape,
2738
+ InputKeyDownHome: InputKeyDownHome,
2739
+ InputKeyDownEnd: InputKeyDownEnd,
2740
+ InputKeyDownEnter: InputKeyDownEnter,
2741
+ InputChange: InputChange,
2742
+ InputBlur: InputBlur,
2743
+ MenuMouseLeave: MenuMouseLeave$1,
2744
+ ItemMouseMove: ItemMouseMove$1,
2745
+ ItemClick: ItemClick$1,
2746
+ ToggleButtonClick: ToggleButtonClick$1,
2747
+ FunctionToggleMenu: FunctionToggleMenu$1,
2748
+ FunctionOpenMenu: FunctionOpenMenu$1,
2749
+ FunctionCloseMenu: FunctionCloseMenu$1,
2750
+ FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2751
+ FunctionSelectItem: FunctionSelectItem$1,
2752
+ FunctionSetInputValue: FunctionSetInputValue$1,
2753
+ FunctionReset: FunctionReset$1,
2754
+ ControlledPropUpdatedSelectedItem: ControlledPropUpdatedSelectedItem
2755
+ });
2756
+
2669
2757
  function getElementIds$1(_ref) {
2670
2758
  var id = _ref.id,
2671
2759
  inputId = _ref.inputId,
@@ -2678,7 +2766,6 @@ function getElementIds$1(_ref) {
2678
2766
  id: id
2679
2767
  }, rest)));
2680
2768
  }
2681
-
2682
2769
  function getInitialState$1(props) {
2683
2770
  var initialState = getInitialState(props);
2684
2771
  var selectedItem = initialState.selectedItem;
@@ -2692,7 +2779,6 @@ function getInitialState$1(props) {
2692
2779
  inputValue: inputValue
2693
2780
  });
2694
2781
  }
2695
-
2696
2782
  var propTypes$1 = {
2697
2783
  items: PropTypes.array.isRequired,
2698
2784
  itemToString: PropTypes.func,
@@ -2733,55 +2819,43 @@ var propTypes$1 = {
2733
2819
  })
2734
2820
  })
2735
2821
  };
2822
+ /**
2823
+ * The useCombobox version of useControlledState, which also
2824
+ * checks if the controlled prop selectedItem changed between
2825
+ * renders. If so, it will also update inputValue with its
2826
+ * string equivalent. It uses the common useControlledState to
2827
+ * compute the rest of the state.
2828
+ *
2829
+ * @param {Function} reducer Reducer function from downshift.
2830
+ * @param {Object} initialState Initial state of the hook.
2831
+ * @param {Object} props The hook props.
2832
+ * @returns {Array} An array with the state and an action dispatcher.
2833
+ */
2834
+
2835
+ function useControlledState$1(reducer, initialState, props) {
2836
+ var _useControlledStateCo = useControlledState(reducer, initialState, props),
2837
+ newState = _useControlledStateCo[0],
2838
+ dispatch = _useControlledStateCo[1];
2839
+
2840
+ var previousSelectedItemRef = useRef(null);
2841
+ var selectedItem = props.selectedItem,
2842
+ itemToString = props.itemToString; // ToDo: if needed, make same approach as selectedItemChanged from Downshift.
2843
+
2844
+ if (isControlledProp(props, 'selectedItem') && previousSelectedItemRef.current !== selectedItem) {
2845
+ dispatch({
2846
+ type: ControlledPropUpdatedSelectedItem,
2847
+ inputValue: itemToString(selectedItem)
2848
+ });
2849
+ }
2736
2850
 
2851
+ previousSelectedItemRef.current = selectedItem;
2852
+ return [newState, dispatch];
2853
+ }
2737
2854
  var defaultProps$2 = _extends({}, defaultProps, {
2738
2855
  getA11yStatusMessage: getA11yStatusMessage,
2739
2856
  circularNavigation: true
2740
2857
  });
2741
2858
 
2742
- var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2743
- var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2744
- var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2745
- var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2746
- var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2747
- var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2748
- var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2749
- var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2750
- var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2751
- var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2752
- var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2753
- var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2754
- var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2755
- var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2756
- var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2757
- var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2758
- var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2759
- var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2760
- var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2761
-
2762
- var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2763
- __proto__: null,
2764
- InputKeyDownArrowDown: InputKeyDownArrowDown,
2765
- InputKeyDownArrowUp: InputKeyDownArrowUp,
2766
- InputKeyDownEscape: InputKeyDownEscape,
2767
- InputKeyDownHome: InputKeyDownHome,
2768
- InputKeyDownEnd: InputKeyDownEnd,
2769
- InputKeyDownEnter: InputKeyDownEnter,
2770
- InputChange: InputChange,
2771
- InputBlur: InputBlur,
2772
- MenuMouseLeave: MenuMouseLeave$1,
2773
- ItemMouseMove: ItemMouseMove$1,
2774
- ItemClick: ItemClick$1,
2775
- ToggleButtonClick: ToggleButtonClick$1,
2776
- FunctionToggleMenu: FunctionToggleMenu$1,
2777
- FunctionOpenMenu: FunctionOpenMenu$1,
2778
- FunctionCloseMenu: FunctionCloseMenu$1,
2779
- FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2780
- FunctionSelectItem: FunctionSelectItem$1,
2781
- FunctionSetInputValue: FunctionSetInputValue$1,
2782
- FunctionReset: FunctionReset$1
2783
- });
2784
-
2785
2859
  /* eslint-disable complexity */
2786
2860
 
2787
2861
  function downshiftUseComboboxReducer(state, action) {
@@ -2921,6 +2995,7 @@ function downshiftUseComboboxReducer(state, action) {
2921
2995
  };
2922
2996
  break;
2923
2997
 
2998
+ case ControlledPropUpdatedSelectedItem:
2924
2999
  case FunctionSetInputValue$1:
2925
3000
  changes = {
2926
3001
  inputValue: action.inputValue
@@ -2966,20 +3041,20 @@ function useCombobox(userProps) {
2966
3041
  defaultIsOpen = props.defaultIsOpen,
2967
3042
  items = props.items,
2968
3043
  scrollIntoView = props.scrollIntoView,
2969
- getA11ySelectionMessage = props.getA11ySelectionMessage,
3044
+ environment = props.environment,
2970
3045
  getA11yStatusMessage = props.getA11yStatusMessage,
2971
- itemToString = props.itemToString,
2972
- environment = props.environment; // Initial state depending on controlled props.
3046
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
3047
+ itemToString = props.itemToString; // Initial state depending on controlled props.
2973
3048
 
2974
3049
  var initialState = getInitialState$1(props); // Reducer init.
2975
3050
 
2976
- var _useEnhancedReducer = useEnhancedReducer(downshiftUseComboboxReducer, initialState, props),
2977
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2978
- isOpen = _useEnhancedReducer$.isOpen,
2979
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2980
- selectedItem = _useEnhancedReducer$.selectedItem,
2981
- inputValue = _useEnhancedReducer$.inputValue,
2982
- dispatch = _useEnhancedReducer[1];
3051
+ var _useControlledState = useControlledState$1(downshiftUseComboboxReducer, initialState, props),
3052
+ _useControlledState$ = _useControlledState[0],
3053
+ isOpen = _useControlledState$.isOpen,
3054
+ highlightedIndex = _useControlledState$.highlightedIndex,
3055
+ selectedItem = _useControlledState$.selectedItem,
3056
+ inputValue = _useControlledState$.inputValue,
3057
+ dispatch = _useControlledState[1];
2983
3058
  /* Refs */
2984
3059
 
2985
3060
 
@@ -2996,25 +3071,30 @@ function useCombobox(userProps) {
2996
3071
  isTouchMove: false
2997
3072
  });
2998
3073
  var elementIds = useRef(getElementIds$1(props));
3074
+ var previousResultCountRef = useRef();
2999
3075
  /* Effects */
3000
3076
 
3001
- /* Sets a11y status message on changes in isOpen. */
3077
+ /* Sets a11y status message on changes in state. */
3002
3078
 
3003
3079
  useEffect(function () {
3004
3080
  if (isInitialMount.current) {
3005
3081
  return;
3006
3082
  }
3007
3083
 
3008
- setStatus(getA11yStatusMessage({
3009
- highlightedIndex: highlightedIndex,
3010
- inputValue: inputValue,
3011
- isOpen: isOpen,
3012
- itemToString: itemToString,
3013
- resultCount: items.length,
3014
- highlightedItem: items[highlightedIndex],
3015
- selectedItem: selectedItem
3016
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3017
- }, [isOpen]);
3084
+ var previousResultCount = previousResultCountRef.current;
3085
+ updateA11yStatus(function () {
3086
+ return getA11yStatusMessage({
3087
+ isOpen: isOpen,
3088
+ highlightedIndex: highlightedIndex,
3089
+ selectedItem: selectedItem,
3090
+ inputValue: inputValue,
3091
+ highlightedItem: items[highlightedIndex],
3092
+ resultCount: items.length,
3093
+ itemToString: itemToString,
3094
+ previousResultCount: previousResultCount
3095
+ });
3096
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3097
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
3018
3098
  /* Sets a11y status message on changes in selectedItem. */
3019
3099
 
3020
3100
  useEffect(function () {
@@ -3022,15 +3102,19 @@ function useCombobox(userProps) {
3022
3102
  return;
3023
3103
  }
3024
3104
 
3025
- setStatus(getA11ySelectionMessage({
3026
- highlightedIndex: highlightedIndex,
3027
- inputValue: inputValue,
3028
- isOpen: isOpen,
3029
- itemToString: itemToString,
3030
- resultCount: items.length,
3031
- highlightedItem: items[highlightedIndex],
3032
- selectedItem: selectedItem
3033
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3105
+ var previousResultCount = previousResultCountRef.current;
3106
+ updateA11yStatus(function () {
3107
+ return getA11ySelectionMessage({
3108
+ isOpen: isOpen,
3109
+ highlightedIndex: highlightedIndex,
3110
+ selectedItem: selectedItem,
3111
+ inputValue: inputValue,
3112
+ highlightedItem: items[highlightedIndex],
3113
+ resultCount: items.length,
3114
+ itemToString: itemToString,
3115
+ previousResultCount: previousResultCount
3116
+ });
3117
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3034
3118
  }, [selectedItem]);
3035
3119
  /* Scroll on highlighted item if change comes from keyboard. */
3036
3120
 
@@ -3060,8 +3144,13 @@ function useCombobox(userProps) {
3060
3144
  } // eslint-disable-next-line react-hooks/exhaustive-deps
3061
3145
 
3062
3146
  }, [isOpen]);
3063
- /* Make initial ref false. */
3147
+ useEffect(function () {
3148
+ if (isInitialMount.current) {
3149
+ return;
3150
+ }
3064
3151
 
3152
+ previousResultCountRef.current = items.length;
3153
+ });
3065
3154
  useEffect(function () {
3066
3155
  isInitialMount.current = false;
3067
3156
  }, []);
@@ -3157,6 +3246,11 @@ function useCombobox(userProps) {
3157
3246
  });
3158
3247
  },
3159
3248
  Enter: function Enter(event) {
3249
+ // if IME composing, wait for next Enter keydown event.
3250
+ if (event.which === 229) {
3251
+ return;
3252
+ }
3253
+
3160
3254
  event.preventDefault();
3161
3255
  dispatch({
3162
3256
  type: InputKeyDownEnter,
@@ -3687,11 +3781,11 @@ function useMultipleSelection(userProps) {
3687
3781
  keyNavigationNext = props.keyNavigationNext,
3688
3782
  keyNavigationPrevious = props.keyNavigationPrevious; // Reducer init.
3689
3783
 
3690
- var _useEnhancedReducer = useEnhancedReducer(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3691
- _useEnhancedReducer$ = _useEnhancedReducer[0],
3692
- activeIndex = _useEnhancedReducer$.activeIndex,
3693
- selectedItems = _useEnhancedReducer$.selectedItems,
3694
- dispatch = _useEnhancedReducer[1]; // Refs.
3784
+ var _useControlledState = useControlledState(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3785
+ _useControlledState$ = _useControlledState[0],
3786
+ activeIndex = _useControlledState$.activeIndex,
3787
+ selectedItems = _useControlledState$.selectedItems,
3788
+ dispatch = _useControlledState[1]; // Refs.
3695
3789
 
3696
3790
 
3697
3791
  var isInitialMount = useRef(true);