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.
@@ -170,7 +170,8 @@ function resetIdCounter() {
170
170
 
171
171
  function getA11yStatusMessage(_ref2) {
172
172
  var isOpen = _ref2.isOpen,
173
- resultCount = _ref2.resultCount;
173
+ resultCount = _ref2.resultCount,
174
+ previousResultCount = _ref2.previousResultCount;
174
175
 
175
176
  if (!isOpen) {
176
177
  return '';
@@ -180,7 +181,11 @@ function getA11yStatusMessage(_ref2) {
180
181
  return 'No results are available.';
181
182
  }
182
183
 
183
- return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter key to select.";
184
+ if (resultCount !== previousResultCount) {
185
+ return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter key to select.";
186
+ }
187
+
188
+ return '';
184
189
  }
185
190
  /**
186
191
  * Takes an argument and if it's an array, returns the first item in the array
@@ -504,8 +509,12 @@ var stateChangeTypes = /*#__PURE__*/Object.freeze({
504
509
  touchEnd: touchEnd
505
510
  });
506
511
 
507
- var Downshift = /*#__PURE__*/function () {
508
- var Downshift = /*#__PURE__*/function (_Component) {
512
+ var Downshift =
513
+ /*#__PURE__*/
514
+ function () {
515
+ var Downshift =
516
+ /*#__PURE__*/
517
+ function (_Component) {
509
518
  _inheritsLoose(Downshift, _Component);
510
519
 
511
520
  function Downshift(_props) {
@@ -779,6 +788,10 @@ var Downshift = /*#__PURE__*/function () {
779
788
  }
780
789
  },
781
790
  Enter: function Enter(event) {
791
+ if (event.which === 229) {
792
+ return;
793
+ }
794
+
782
795
  var _this$getState2 = this.getState(),
783
796
  isOpen = _this$getState2.isOpen,
784
797
  highlightedIndex = _this$getState2.highlightedIndex;
@@ -1671,6 +1684,65 @@ var dropdownDefaultStateValues = {
1671
1684
  inputValue: ''
1672
1685
  };
1673
1686
 
1687
+ function callOnChangeProps(action, state, newState) {
1688
+ var props = action.props,
1689
+ type = action.type;
1690
+ var changes = {};
1691
+ Object.keys(state).forEach(function (key) {
1692
+ invokeOnChangeHandler(key, props, state, newState);
1693
+
1694
+ if (newState[key] !== state[key]) {
1695
+ changes[key] = newState[key];
1696
+ }
1697
+ });
1698
+
1699
+ if (props.onStateChange && Object.keys(changes).length) {
1700
+ props.onStateChange(_extends({
1701
+ type: type
1702
+ }, changes));
1703
+ }
1704
+ }
1705
+
1706
+ function invokeOnChangeHandler(key, props, state, newState) {
1707
+ var handler = "on" + capitalizeString(key) + "Change";
1708
+
1709
+ if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1710
+ props[handler](newState);
1711
+ }
1712
+ }
1713
+ /**
1714
+ * Default state reducer that returns the changes.
1715
+ *
1716
+ * @param {Object} s state.
1717
+ * @param {Object} a action with changes.
1718
+ * @returns {Object} changes.
1719
+ */
1720
+
1721
+
1722
+ function stateReducer(s, a) {
1723
+ return a.changes;
1724
+ }
1725
+ /**
1726
+ * Returns a message to be added to aria-live region when item is selected.
1727
+ *
1728
+ * @param {Object} selectionParameters Parameters required to build the message.
1729
+ * @returns {string} The a11y message.
1730
+ */
1731
+
1732
+
1733
+ function getA11ySelectionMessage(selectionParameters) {
1734
+ var selectedItem = selectionParameters.selectedItem,
1735
+ itemToStringLocal = selectionParameters.itemToString;
1736
+ return selectedItem ? itemToStringLocal(selectedItem) + " has been selected." : '';
1737
+ }
1738
+ /**
1739
+ * Debounced call for updating the a11y message.
1740
+ */
1741
+
1742
+
1743
+ var updateA11yStatus = debounce(function (getA11yMessage, document) {
1744
+ setStatus(getA11yMessage(), document);
1745
+ }, 200);
1674
1746
  function getElementIds(_ref) {
1675
1747
  var id = _ref.id,
1676
1748
  labelId = _ref.labelId,
@@ -1687,7 +1759,6 @@ function getElementIds(_ref) {
1687
1759
  toggleButtonId: toggleButtonId || uniqueId + "-toggle-button"
1688
1760
  };
1689
1761
  }
1690
-
1691
1762
  function getItemIndex(index, item, items) {
1692
1763
  if (index !== undefined) {
1693
1764
  return index;
@@ -1716,57 +1787,39 @@ function getPropTypesValidator(caller, propTypes) {
1716
1787
  });
1717
1788
  };
1718
1789
  }
1719
-
1720
1790
  function isAcceptedCharacterKey(key) {
1721
1791
  return /^\S{1}$/.test(key);
1722
1792
  }
1723
-
1724
1793
  function capitalizeString(string) {
1725
1794
  return "" + string.slice(0, 1).toUpperCase() + string.slice(1);
1726
1795
  }
1796
+ /**
1797
+ * Computes the controlled state using a the previous state, props,
1798
+ * two reducers, one from downshift and an optional one from the user.
1799
+ * Also calls the onChange handlers for state values that have changed.
1800
+ *
1801
+ * @param {Function} reducer Reducer function from downshift.
1802
+ * @param {Object} initialState Initial state of the hook.
1803
+ * @param {Object} props The hook props.
1804
+ * @returns {Array} An array with the state and an action dispatcher.
1805
+ */
1727
1806
 
1728
- function invokeOnChangeHandler(key, props, state, newState) {
1729
- var handler = "on" + capitalizeString(key) + "Change";
1730
-
1731
- if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1732
- props[handler](newState);
1733
- }
1734
- }
1735
-
1736
- function callOnChangeProps(action, state, newState) {
1737
- var props = action.props,
1738
- type = action.type;
1739
- var changes = {};
1740
- Object.keys(state).forEach(function (key) {
1741
- invokeOnChangeHandler(key, props, state, newState);
1807
+ function useControlledState(reducer, initialState, props) {
1808
+ var _useState = react.useState(initialState),
1809
+ uncontrolledState = _useState[0],
1810
+ setState = _useState[1];
1742
1811
 
1743
- if (newState[key] !== state[key]) {
1744
- changes[key] = newState[key];
1745
- }
1746
- });
1812
+ var state = getState(uncontrolledState, props);
1747
1813
 
1748
- if (props.onStateChange && Object.keys(changes).length) {
1749
- props.onStateChange(_extends({
1750
- type: type
1751
- }, changes));
1752
- }
1753
- }
1754
-
1755
- function useEnhancedReducer(reducer, initialState, props) {
1756
- var enhancedReducer = react.useCallback(function (state, action) {
1757
- state = getState(state, action.props);
1758
- var stateReduceLocal = action.props.stateReducer;
1814
+ var dispatch = function (action) {
1815
+ var stateReducerFromProps = action.props.stateReducer;
1759
1816
  var changes = reducer(state, action);
1760
- var newState = stateReduceLocal(state, _extends({}, action, {
1817
+ var newState = stateReducerFromProps(state, _extends({}, action, {
1761
1818
  changes: changes
1762
1819
  }));
1763
1820
  callOnChangeProps(action, state, newState);
1764
- return newState;
1765
- }, [reducer]);
1766
-
1767
- var _useReducer = react.useReducer(enhancedReducer, initialState),
1768
- state = _useReducer[0],
1769
- dispatch = _useReducer[1];
1821
+ setState(newState);
1822
+ };
1770
1823
 
1771
1824
  return [getState(state, props), function dispatchWithProps(action) {
1772
1825
  return dispatch(_extends({
@@ -1774,32 +1827,6 @@ function useEnhancedReducer(reducer, initialState, props) {
1774
1827
  }, action));
1775
1828
  }];
1776
1829
  }
1777
- /**
1778
- * Default state reducer that returns the changes.
1779
- *
1780
- * @param {Object} s state.
1781
- * @param {Object} a action with changes.
1782
- * @returns {Object} changes.
1783
- */
1784
-
1785
-
1786
- function stateReducer(s, a) {
1787
- return a.changes;
1788
- }
1789
- /**
1790
- * Returns a message to be added to aria-live region when item is selected.
1791
- *
1792
- * @param {Object} selectionParameters Parameters required to build the message.
1793
- * @returns {string} The a11y message.
1794
- */
1795
-
1796
-
1797
- function getA11ySelectionMessage(selectionParameters) {
1798
- var selectedItem = selectionParameters.selectedItem,
1799
- itemToStringLocal = selectionParameters.itemToString;
1800
- return itemToStringLocal(selectedItem) + " has been selected.";
1801
- }
1802
-
1803
1830
  var defaultProps = {
1804
1831
  itemToString: itemToString,
1805
1832
  stateReducer: stateReducer,
@@ -1810,7 +1837,6 @@ var defaultProps = {
1810
1837
  /* istanbul ignore next (ssr) */
1811
1838
  ? {} : window
1812
1839
  };
1813
-
1814
1840
  function getDefaultValue(props, propKey, defaultStateValues) {
1815
1841
  if (defaultStateValues === void 0) {
1816
1842
  defaultStateValues = dropdownDefaultStateValues;
@@ -1824,7 +1850,6 @@ function getDefaultValue(props, propKey, defaultStateValues) {
1824
1850
 
1825
1851
  return defaultStateValues[propKey];
1826
1852
  }
1827
-
1828
1853
  function getInitialValue(props, propKey, defaultStateValues) {
1829
1854
  if (defaultStateValues === void 0) {
1830
1855
  defaultStateValues = dropdownDefaultStateValues;
@@ -1842,7 +1867,6 @@ function getInitialValue(props, propKey, defaultStateValues) {
1842
1867
 
1843
1868
  return getDefaultValue(props, propKey, defaultStateValues);
1844
1869
  }
1845
-
1846
1870
  function getInitialState(props) {
1847
1871
  var selectedItem = getInitialValue(props, 'selectedItem');
1848
1872
  var isOpen = getInitialValue(props, 'isOpen');
@@ -1855,7 +1879,6 @@ function getInitialState(props) {
1855
1879
  inputValue: inputValue
1856
1880
  };
1857
1881
  }
1858
-
1859
1882
  function getHighlightedIndexOnOpen(props, state, offset, getItemNodeFromIndex) {
1860
1883
  var items = props.items,
1861
1884
  initialHighlightedIndex = props.initialHighlightedIndex,
@@ -1962,7 +1985,8 @@ var propTypes = {
1962
1985
 
1963
1986
  function getA11yStatusMessage$1(_ref) {
1964
1987
  var isOpen = _ref.isOpen,
1965
- resultCount = _ref.resultCount;
1988
+ resultCount = _ref.resultCount,
1989
+ previousResultCount = _ref.previousResultCount;
1966
1990
 
1967
1991
  if (!isOpen) {
1968
1992
  return '';
@@ -1972,7 +1996,11 @@ function getA11yStatusMessage$1(_ref) {
1972
1996
  return 'No results are available.';
1973
1997
  }
1974
1998
 
1975
- 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.";
1999
+ if (resultCount !== previousResultCount) {
2000
+ 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.";
2001
+ }
2002
+
2003
+ return '';
1976
2004
  }
1977
2005
 
1978
2006
  var defaultProps$1 = _extends({}, defaultProps, {
@@ -2224,24 +2252,23 @@ function useSelect(userProps) {
2224
2252
  var props = _extends({}, defaultProps$1, {}, userProps);
2225
2253
 
2226
2254
  var items = props.items,
2227
- itemToString = props.itemToString,
2228
- getA11yStatusMessage = props.getA11yStatusMessage,
2229
- getA11ySelectionMessage = props.getA11ySelectionMessage,
2230
2255
  scrollIntoView = props.scrollIntoView,
2231
2256
  environment = props.environment,
2232
2257
  initialIsOpen = props.initialIsOpen,
2233
- defaultIsOpen = props.defaultIsOpen; // Initial state depending on controlled props.
2258
+ defaultIsOpen = props.defaultIsOpen,
2259
+ itemToString = props.itemToString,
2260
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
2261
+ getA11yStatusMessage = props.getA11yStatusMessage; // Initial state depending on controlled props.
2234
2262
 
2235
2263
  var initialState = getInitialState(props); // Reducer init.
2236
2264
 
2237
- var _useEnhancedReducer = useEnhancedReducer(downshiftSelectReducer, initialState, props),
2238
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2239
- isOpen = _useEnhancedReducer$.isOpen,
2240
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2241
- selectedItem = _useEnhancedReducer$.selectedItem,
2242
- inputValue = _useEnhancedReducer$.inputValue,
2243
- dispatch = _useEnhancedReducer[1];
2244
- /* Refs */
2265
+ var _useControlledState = useControlledState(downshiftSelectReducer, initialState, props),
2266
+ _useControlledState$ = _useControlledState[0],
2267
+ isOpen = _useControlledState$.isOpen,
2268
+ highlightedIndex = _useControlledState$.highlightedIndex,
2269
+ selectedItem = _useControlledState$.selectedItem,
2270
+ inputValue = _useControlledState$.inputValue,
2271
+ dispatch = _useControlledState[1]; // Refs
2245
2272
 
2246
2273
 
2247
2274
  var toggleButtonRef = react.useRef(null);
@@ -2253,13 +2280,14 @@ function useSelect(userProps) {
2253
2280
  isMouseDown: false,
2254
2281
  isTouchMove: false
2255
2282
  });
2256
- var elementIds = react.useRef(getElementIds(props)); // Some utils.
2283
+ var elementIds = react.useRef(getElementIds(props));
2284
+ var previousResultCountRef = react.useRef(); // Some utils.
2257
2285
 
2258
2286
  var getItemNodeFromIndex = function (index) {
2259
2287
  return environment.document.getElementById(elementIds.current.getItemId(index));
2260
2288
  }; // Effects.
2261
2289
 
2262
- /* Sets a11y status message on changes in isOpen. */
2290
+ /* Sets a11y status message on changes in state. */
2263
2291
 
2264
2292
 
2265
2293
  react.useEffect(function () {
@@ -2267,16 +2295,20 @@ function useSelect(userProps) {
2267
2295
  return;
2268
2296
  }
2269
2297
 
2270
- setStatus(getA11yStatusMessage({
2271
- highlightedIndex: highlightedIndex,
2272
- inputValue: inputValue,
2273
- isOpen: isOpen,
2274
- itemToString: itemToString,
2275
- resultCount: items.length,
2276
- highlightedItem: items[highlightedIndex],
2277
- selectedItem: selectedItem
2278
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2279
- }, [isOpen]);
2298
+ var previousResultCount = previousResultCountRef.current;
2299
+ updateA11yStatus(function () {
2300
+ return getA11yStatusMessage({
2301
+ isOpen: isOpen,
2302
+ highlightedIndex: highlightedIndex,
2303
+ selectedItem: selectedItem,
2304
+ inputValue: inputValue,
2305
+ highlightedItem: items[highlightedIndex],
2306
+ resultCount: items.length,
2307
+ itemToString: itemToString,
2308
+ previousResultCount: previousResultCount
2309
+ });
2310
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2311
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
2280
2312
  /* Sets a11y status message on changes in selectedItem. */
2281
2313
 
2282
2314
  react.useEffect(function () {
@@ -2284,15 +2316,19 @@ function useSelect(userProps) {
2284
2316
  return;
2285
2317
  }
2286
2318
 
2287
- setStatus(getA11ySelectionMessage({
2288
- highlightedIndex: highlightedIndex,
2289
- inputValue: inputValue,
2290
- isOpen: isOpen,
2291
- itemToString: itemToString,
2292
- resultCount: items.length,
2293
- highlightedItem: items[highlightedIndex],
2294
- selectedItem: selectedItem
2295
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2319
+ var previousResultCount = previousResultCountRef.current;
2320
+ updateA11yStatus(function () {
2321
+ return getA11ySelectionMessage({
2322
+ isOpen: isOpen,
2323
+ highlightedIndex: highlightedIndex,
2324
+ selectedItem: selectedItem,
2325
+ inputValue: inputValue,
2326
+ highlightedItem: items[highlightedIndex],
2327
+ resultCount: items.length,
2328
+ itemToString: itemToString,
2329
+ previousResultCount: previousResultCount
2330
+ });
2331
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2296
2332
  }, [selectedItem]);
2297
2333
  /* Sets cleanup for the keysSoFar after 500ms. */
2298
2334
 
@@ -2349,6 +2385,13 @@ function useSelect(userProps) {
2349
2385
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2350
2386
 
2351
2387
  }, [highlightedIndex]);
2388
+ react.useEffect(function () {
2389
+ if (isInitialMount.current) {
2390
+ return;
2391
+ }
2392
+
2393
+ previousResultCountRef.current = items.length;
2394
+ });
2352
2395
  /* Make initial ref false. */
2353
2396
 
2354
2397
  react.useEffect(function () {
@@ -2672,6 +2715,51 @@ function useSelect(userProps) {
2672
2715
  };
2673
2716
  }
2674
2717
 
2718
+ var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2719
+ var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2720
+ var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2721
+ var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2722
+ var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2723
+ var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2724
+ var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2725
+ var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2726
+ var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2727
+ var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2728
+ var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2729
+ var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2730
+ var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2731
+ var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2732
+ var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2733
+ var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2734
+ var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2735
+ var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2736
+ var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2737
+ var ControlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__controlled_prop_updated_selected_item__' : 19;
2738
+
2739
+ var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2740
+ __proto__: null,
2741
+ InputKeyDownArrowDown: InputKeyDownArrowDown,
2742
+ InputKeyDownArrowUp: InputKeyDownArrowUp,
2743
+ InputKeyDownEscape: InputKeyDownEscape,
2744
+ InputKeyDownHome: InputKeyDownHome,
2745
+ InputKeyDownEnd: InputKeyDownEnd,
2746
+ InputKeyDownEnter: InputKeyDownEnter,
2747
+ InputChange: InputChange,
2748
+ InputBlur: InputBlur,
2749
+ MenuMouseLeave: MenuMouseLeave$1,
2750
+ ItemMouseMove: ItemMouseMove$1,
2751
+ ItemClick: ItemClick$1,
2752
+ ToggleButtonClick: ToggleButtonClick$1,
2753
+ FunctionToggleMenu: FunctionToggleMenu$1,
2754
+ FunctionOpenMenu: FunctionOpenMenu$1,
2755
+ FunctionCloseMenu: FunctionCloseMenu$1,
2756
+ FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2757
+ FunctionSelectItem: FunctionSelectItem$1,
2758
+ FunctionSetInputValue: FunctionSetInputValue$1,
2759
+ FunctionReset: FunctionReset$1,
2760
+ ControlledPropUpdatedSelectedItem: ControlledPropUpdatedSelectedItem
2761
+ });
2762
+
2675
2763
  function getElementIds$1(_ref) {
2676
2764
  var id = _ref.id,
2677
2765
  inputId = _ref.inputId,
@@ -2684,7 +2772,6 @@ function getElementIds$1(_ref) {
2684
2772
  id: id
2685
2773
  }, rest)));
2686
2774
  }
2687
-
2688
2775
  function getInitialState$1(props) {
2689
2776
  var initialState = getInitialState(props);
2690
2777
  var selectedItem = initialState.selectedItem;
@@ -2698,7 +2785,6 @@ function getInitialState$1(props) {
2698
2785
  inputValue: inputValue
2699
2786
  });
2700
2787
  }
2701
-
2702
2788
  var propTypes$1 = {
2703
2789
  items: PropTypes.array.isRequired,
2704
2790
  itemToString: PropTypes.func,
@@ -2739,55 +2825,43 @@ var propTypes$1 = {
2739
2825
  })
2740
2826
  })
2741
2827
  };
2828
+ /**
2829
+ * The useCombobox version of useControlledState, which also
2830
+ * checks if the controlled prop selectedItem changed between
2831
+ * renders. If so, it will also update inputValue with its
2832
+ * string equivalent. It uses the common useControlledState to
2833
+ * compute the rest of the state.
2834
+ *
2835
+ * @param {Function} reducer Reducer function from downshift.
2836
+ * @param {Object} initialState Initial state of the hook.
2837
+ * @param {Object} props The hook props.
2838
+ * @returns {Array} An array with the state and an action dispatcher.
2839
+ */
2840
+
2841
+ function useControlledState$1(reducer, initialState, props) {
2842
+ var _useControlledStateCo = useControlledState(reducer, initialState, props),
2843
+ newState = _useControlledStateCo[0],
2844
+ dispatch = _useControlledStateCo[1];
2845
+
2846
+ var previousSelectedItemRef = react.useRef(null);
2847
+ var selectedItem = props.selectedItem,
2848
+ itemToString = props.itemToString; // ToDo: if needed, make same approach as selectedItemChanged from Downshift.
2849
+
2850
+ if (isControlledProp(props, 'selectedItem') && previousSelectedItemRef.current !== selectedItem) {
2851
+ dispatch({
2852
+ type: ControlledPropUpdatedSelectedItem,
2853
+ inputValue: itemToString(selectedItem)
2854
+ });
2855
+ }
2742
2856
 
2857
+ previousSelectedItemRef.current = selectedItem;
2858
+ return [newState, dispatch];
2859
+ }
2743
2860
  var defaultProps$2 = _extends({}, defaultProps, {
2744
2861
  getA11yStatusMessage: getA11yStatusMessage,
2745
2862
  circularNavigation: true
2746
2863
  });
2747
2864
 
2748
- var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2749
- var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2750
- var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2751
- var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2752
- var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2753
- var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2754
- var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2755
- var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2756
- var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2757
- var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2758
- var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2759
- var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2760
- var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2761
- var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2762
- var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2763
- var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2764
- var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2765
- var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2766
- var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2767
-
2768
- var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2769
- __proto__: null,
2770
- InputKeyDownArrowDown: InputKeyDownArrowDown,
2771
- InputKeyDownArrowUp: InputKeyDownArrowUp,
2772
- InputKeyDownEscape: InputKeyDownEscape,
2773
- InputKeyDownHome: InputKeyDownHome,
2774
- InputKeyDownEnd: InputKeyDownEnd,
2775
- InputKeyDownEnter: InputKeyDownEnter,
2776
- InputChange: InputChange,
2777
- InputBlur: InputBlur,
2778
- MenuMouseLeave: MenuMouseLeave$1,
2779
- ItemMouseMove: ItemMouseMove$1,
2780
- ItemClick: ItemClick$1,
2781
- ToggleButtonClick: ToggleButtonClick$1,
2782
- FunctionToggleMenu: FunctionToggleMenu$1,
2783
- FunctionOpenMenu: FunctionOpenMenu$1,
2784
- FunctionCloseMenu: FunctionCloseMenu$1,
2785
- FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2786
- FunctionSelectItem: FunctionSelectItem$1,
2787
- FunctionSetInputValue: FunctionSetInputValue$1,
2788
- FunctionReset: FunctionReset$1
2789
- });
2790
-
2791
2865
  /* eslint-disable complexity */
2792
2866
 
2793
2867
  function downshiftUseComboboxReducer(state, action) {
@@ -2927,6 +3001,7 @@ function downshiftUseComboboxReducer(state, action) {
2927
3001
  };
2928
3002
  break;
2929
3003
 
3004
+ case ControlledPropUpdatedSelectedItem:
2930
3005
  case FunctionSetInputValue$1:
2931
3006
  changes = {
2932
3007
  inputValue: action.inputValue
@@ -2972,20 +3047,20 @@ function useCombobox(userProps) {
2972
3047
  defaultIsOpen = props.defaultIsOpen,
2973
3048
  items = props.items,
2974
3049
  scrollIntoView = props.scrollIntoView,
2975
- getA11ySelectionMessage = props.getA11ySelectionMessage,
3050
+ environment = props.environment,
2976
3051
  getA11yStatusMessage = props.getA11yStatusMessage,
2977
- itemToString = props.itemToString,
2978
- environment = props.environment; // Initial state depending on controlled props.
3052
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
3053
+ itemToString = props.itemToString; // Initial state depending on controlled props.
2979
3054
 
2980
3055
  var initialState = getInitialState$1(props); // Reducer init.
2981
3056
 
2982
- var _useEnhancedReducer = useEnhancedReducer(downshiftUseComboboxReducer, initialState, props),
2983
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2984
- isOpen = _useEnhancedReducer$.isOpen,
2985
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2986
- selectedItem = _useEnhancedReducer$.selectedItem,
2987
- inputValue = _useEnhancedReducer$.inputValue,
2988
- dispatch = _useEnhancedReducer[1];
3057
+ var _useControlledState = useControlledState$1(downshiftUseComboboxReducer, initialState, props),
3058
+ _useControlledState$ = _useControlledState[0],
3059
+ isOpen = _useControlledState$.isOpen,
3060
+ highlightedIndex = _useControlledState$.highlightedIndex,
3061
+ selectedItem = _useControlledState$.selectedItem,
3062
+ inputValue = _useControlledState$.inputValue,
3063
+ dispatch = _useControlledState[1];
2989
3064
  /* Refs */
2990
3065
 
2991
3066
 
@@ -3002,25 +3077,30 @@ function useCombobox(userProps) {
3002
3077
  isTouchMove: false
3003
3078
  });
3004
3079
  var elementIds = react.useRef(getElementIds$1(props));
3080
+ var previousResultCountRef = react.useRef();
3005
3081
  /* Effects */
3006
3082
 
3007
- /* Sets a11y status message on changes in isOpen. */
3083
+ /* Sets a11y status message on changes in state. */
3008
3084
 
3009
3085
  react.useEffect(function () {
3010
3086
  if (isInitialMount.current) {
3011
3087
  return;
3012
3088
  }
3013
3089
 
3014
- setStatus(getA11yStatusMessage({
3015
- highlightedIndex: highlightedIndex,
3016
- inputValue: inputValue,
3017
- isOpen: isOpen,
3018
- itemToString: itemToString,
3019
- resultCount: items.length,
3020
- highlightedItem: items[highlightedIndex],
3021
- selectedItem: selectedItem
3022
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3023
- }, [isOpen]);
3090
+ var previousResultCount = previousResultCountRef.current;
3091
+ updateA11yStatus(function () {
3092
+ return getA11yStatusMessage({
3093
+ isOpen: isOpen,
3094
+ highlightedIndex: highlightedIndex,
3095
+ selectedItem: selectedItem,
3096
+ inputValue: inputValue,
3097
+ highlightedItem: items[highlightedIndex],
3098
+ resultCount: items.length,
3099
+ itemToString: itemToString,
3100
+ previousResultCount: previousResultCount
3101
+ });
3102
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3103
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
3024
3104
  /* Sets a11y status message on changes in selectedItem. */
3025
3105
 
3026
3106
  react.useEffect(function () {
@@ -3028,15 +3108,19 @@ function useCombobox(userProps) {
3028
3108
  return;
3029
3109
  }
3030
3110
 
3031
- setStatus(getA11ySelectionMessage({
3032
- highlightedIndex: highlightedIndex,
3033
- inputValue: inputValue,
3034
- isOpen: isOpen,
3035
- itemToString: itemToString,
3036
- resultCount: items.length,
3037
- highlightedItem: items[highlightedIndex],
3038
- selectedItem: selectedItem
3039
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3111
+ var previousResultCount = previousResultCountRef.current;
3112
+ updateA11yStatus(function () {
3113
+ return getA11ySelectionMessage({
3114
+ isOpen: isOpen,
3115
+ highlightedIndex: highlightedIndex,
3116
+ selectedItem: selectedItem,
3117
+ inputValue: inputValue,
3118
+ highlightedItem: items[highlightedIndex],
3119
+ resultCount: items.length,
3120
+ itemToString: itemToString,
3121
+ previousResultCount: previousResultCount
3122
+ });
3123
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3040
3124
  }, [selectedItem]);
3041
3125
  /* Scroll on highlighted item if change comes from keyboard. */
3042
3126
 
@@ -3066,8 +3150,13 @@ function useCombobox(userProps) {
3066
3150
  } // eslint-disable-next-line react-hooks/exhaustive-deps
3067
3151
 
3068
3152
  }, [isOpen]);
3069
- /* Make initial ref false. */
3153
+ react.useEffect(function () {
3154
+ if (isInitialMount.current) {
3155
+ return;
3156
+ }
3070
3157
 
3158
+ previousResultCountRef.current = items.length;
3159
+ });
3071
3160
  react.useEffect(function () {
3072
3161
  isInitialMount.current = false;
3073
3162
  }, []);
@@ -3163,6 +3252,11 @@ function useCombobox(userProps) {
3163
3252
  });
3164
3253
  },
3165
3254
  Enter: function Enter(event) {
3255
+ // if IME composing, wait for next Enter keydown event.
3256
+ if (event.which === 229) {
3257
+ return;
3258
+ }
3259
+
3166
3260
  event.preventDefault();
3167
3261
  dispatch({
3168
3262
  type: InputKeyDownEnter,
@@ -3693,11 +3787,11 @@ function useMultipleSelection(userProps) {
3693
3787
  keyNavigationNext = props.keyNavigationNext,
3694
3788
  keyNavigationPrevious = props.keyNavigationPrevious; // Reducer init.
3695
3789
 
3696
- var _useEnhancedReducer = useEnhancedReducer(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3697
- _useEnhancedReducer$ = _useEnhancedReducer[0],
3698
- activeIndex = _useEnhancedReducer$.activeIndex,
3699
- selectedItems = _useEnhancedReducer$.selectedItems,
3700
- dispatch = _useEnhancedReducer[1]; // Refs.
3790
+ var _useControlledState = useControlledState(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3791
+ _useControlledState$ = _useControlledState[0],
3792
+ activeIndex = _useControlledState$.activeIndex,
3793
+ selectedItems = _useControlledState$.selectedItems,
3794
+ dispatch = _useControlledState[1]; // Refs.
3701
3795
 
3702
3796
 
3703
3797
  var isInitialMount = react.useRef(true);