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;
@@ -1604,6 +1617,65 @@ var dropdownDefaultStateValues = {
1604
1617
  inputValue: ''
1605
1618
  };
1606
1619
 
1620
+ function callOnChangeProps(action, state, newState) {
1621
+ var props = action.props,
1622
+ type = action.type;
1623
+ var changes = {};
1624
+ Object.keys(state).forEach(function (key) {
1625
+ invokeOnChangeHandler(key, props, state, newState);
1626
+
1627
+ if (newState[key] !== state[key]) {
1628
+ changes[key] = newState[key];
1629
+ }
1630
+ });
1631
+
1632
+ if (props.onStateChange && Object.keys(changes).length) {
1633
+ props.onStateChange(_extends({
1634
+ type: type
1635
+ }, changes));
1636
+ }
1637
+ }
1638
+
1639
+ function invokeOnChangeHandler(key, props, state, newState) {
1640
+ var handler = "on" + capitalizeString(key) + "Change";
1641
+
1642
+ if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1643
+ props[handler](newState);
1644
+ }
1645
+ }
1646
+ /**
1647
+ * Default state reducer that returns the changes.
1648
+ *
1649
+ * @param {Object} s state.
1650
+ * @param {Object} a action with changes.
1651
+ * @returns {Object} changes.
1652
+ */
1653
+
1654
+
1655
+ function stateReducer(s, a) {
1656
+ return a.changes;
1657
+ }
1658
+ /**
1659
+ * Returns a message to be added to aria-live region when item is selected.
1660
+ *
1661
+ * @param {Object} selectionParameters Parameters required to build the message.
1662
+ * @returns {string} The a11y message.
1663
+ */
1664
+
1665
+
1666
+ function getA11ySelectionMessage(selectionParameters) {
1667
+ var selectedItem = selectionParameters.selectedItem,
1668
+ itemToStringLocal = selectionParameters.itemToString;
1669
+ return selectedItem ? itemToStringLocal(selectedItem) + " has been selected." : '';
1670
+ }
1671
+ /**
1672
+ * Debounced call for updating the a11y message.
1673
+ */
1674
+
1675
+
1676
+ var updateA11yStatus = debounce(function (getA11yMessage, document) {
1677
+ setStatus(getA11yMessage(), document);
1678
+ }, 200);
1607
1679
  function getElementIds(_ref) {
1608
1680
  var id = _ref.id,
1609
1681
  labelId = _ref.labelId,
@@ -1620,7 +1692,6 @@ function getElementIds(_ref) {
1620
1692
  toggleButtonId: toggleButtonId || uniqueId + "-toggle-button"
1621
1693
  };
1622
1694
  }
1623
-
1624
1695
  function getItemIndex(index, item, items) {
1625
1696
  if (index !== undefined) {
1626
1697
  return index;
@@ -1649,57 +1720,39 @@ function getPropTypesValidator(caller, propTypes) {
1649
1720
  });
1650
1721
  };
1651
1722
  }
1652
-
1653
1723
  function isAcceptedCharacterKey(key) {
1654
1724
  return /^\S{1}$/.test(key);
1655
1725
  }
1656
-
1657
1726
  function capitalizeString(string) {
1658
1727
  return "" + string.slice(0, 1).toUpperCase() + string.slice(1);
1659
1728
  }
1729
+ /**
1730
+ * Computes the controlled state using a the previous state, props,
1731
+ * two reducers, one from downshift and an optional one from the user.
1732
+ * Also calls the onChange handlers for state values that have changed.
1733
+ *
1734
+ * @param {Function} reducer Reducer function from downshift.
1735
+ * @param {Object} initialState Initial state of the hook.
1736
+ * @param {Object} props The hook props.
1737
+ * @returns {Array} An array with the state and an action dispatcher.
1738
+ */
1660
1739
 
1661
- function invokeOnChangeHandler(key, props, state, newState) {
1662
- var handler = "on" + capitalizeString(key) + "Change";
1663
-
1664
- if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1665
- props[handler](newState);
1666
- }
1667
- }
1668
-
1669
- function callOnChangeProps(action, state, newState) {
1670
- var props = action.props,
1671
- type = action.type;
1672
- var changes = {};
1673
- Object.keys(state).forEach(function (key) {
1674
- invokeOnChangeHandler(key, props, state, newState);
1740
+ function useControlledState(reducer, initialState, props) {
1741
+ var _useState = react.useState(initialState),
1742
+ uncontrolledState = _useState[0],
1743
+ setState = _useState[1];
1675
1744
 
1676
- if (newState[key] !== state[key]) {
1677
- changes[key] = newState[key];
1678
- }
1679
- });
1745
+ var state = getState(uncontrolledState, props);
1680
1746
 
1681
- if (props.onStateChange && Object.keys(changes).length) {
1682
- props.onStateChange(_extends({
1683
- type: type
1684
- }, changes));
1685
- }
1686
- }
1687
-
1688
- function useEnhancedReducer(reducer, initialState, props) {
1689
- var enhancedReducer = react.useCallback(function (state, action) {
1690
- state = getState(state, action.props);
1691
- var stateReduceLocal = action.props.stateReducer;
1747
+ var dispatch = function (action) {
1748
+ var stateReducerFromProps = action.props.stateReducer;
1692
1749
  var changes = reducer(state, action);
1693
- var newState = stateReduceLocal(state, _extends({}, action, {
1750
+ var newState = stateReducerFromProps(state, _extends({}, action, {
1694
1751
  changes: changes
1695
1752
  }));
1696
1753
  callOnChangeProps(action, state, newState);
1697
- return newState;
1698
- }, [reducer]);
1699
-
1700
- var _useReducer = react.useReducer(enhancedReducer, initialState),
1701
- state = _useReducer[0],
1702
- dispatch = _useReducer[1];
1754
+ setState(newState);
1755
+ };
1703
1756
 
1704
1757
  return [getState(state, props), function dispatchWithProps(action) {
1705
1758
  return dispatch(_extends({
@@ -1707,32 +1760,6 @@ function useEnhancedReducer(reducer, initialState, props) {
1707
1760
  }, action));
1708
1761
  }];
1709
1762
  }
1710
- /**
1711
- * Default state reducer that returns the changes.
1712
- *
1713
- * @param {Object} s state.
1714
- * @param {Object} a action with changes.
1715
- * @returns {Object} changes.
1716
- */
1717
-
1718
-
1719
- function stateReducer(s, a) {
1720
- return a.changes;
1721
- }
1722
- /**
1723
- * Returns a message to be added to aria-live region when item is selected.
1724
- *
1725
- * @param {Object} selectionParameters Parameters required to build the message.
1726
- * @returns {string} The a11y message.
1727
- */
1728
-
1729
-
1730
- function getA11ySelectionMessage(selectionParameters) {
1731
- var selectedItem = selectionParameters.selectedItem,
1732
- itemToStringLocal = selectionParameters.itemToString;
1733
- return itemToStringLocal(selectedItem) + " has been selected.";
1734
- }
1735
-
1736
1763
  var defaultProps = {
1737
1764
  itemToString: itemToString,
1738
1765
  stateReducer: stateReducer,
@@ -1743,7 +1770,6 @@ var defaultProps = {
1743
1770
  /* istanbul ignore next (ssr) */
1744
1771
  ? {} : window
1745
1772
  };
1746
-
1747
1773
  function getDefaultValue(props, propKey, defaultStateValues) {
1748
1774
  if (defaultStateValues === void 0) {
1749
1775
  defaultStateValues = dropdownDefaultStateValues;
@@ -1757,7 +1783,6 @@ function getDefaultValue(props, propKey, defaultStateValues) {
1757
1783
 
1758
1784
  return defaultStateValues[propKey];
1759
1785
  }
1760
-
1761
1786
  function getInitialValue(props, propKey, defaultStateValues) {
1762
1787
  if (defaultStateValues === void 0) {
1763
1788
  defaultStateValues = dropdownDefaultStateValues;
@@ -1775,7 +1800,6 @@ function getInitialValue(props, propKey, defaultStateValues) {
1775
1800
 
1776
1801
  return getDefaultValue(props, propKey, defaultStateValues);
1777
1802
  }
1778
-
1779
1803
  function getInitialState(props) {
1780
1804
  var selectedItem = getInitialValue(props, 'selectedItem');
1781
1805
  var isOpen = getInitialValue(props, 'isOpen');
@@ -1788,7 +1812,6 @@ function getInitialState(props) {
1788
1812
  inputValue: inputValue
1789
1813
  };
1790
1814
  }
1791
-
1792
1815
  function getHighlightedIndexOnOpen(props, state, offset, getItemNodeFromIndex) {
1793
1816
  var items = props.items,
1794
1817
  initialHighlightedIndex = props.initialHighlightedIndex,
@@ -1895,7 +1918,8 @@ var propTypes = {
1895
1918
 
1896
1919
  function getA11yStatusMessage$1(_ref) {
1897
1920
  var isOpen = _ref.isOpen,
1898
- resultCount = _ref.resultCount;
1921
+ resultCount = _ref.resultCount,
1922
+ previousResultCount = _ref.previousResultCount;
1899
1923
 
1900
1924
  if (!isOpen) {
1901
1925
  return '';
@@ -1905,7 +1929,11 @@ function getA11yStatusMessage$1(_ref) {
1905
1929
  return 'No results are available.';
1906
1930
  }
1907
1931
 
1908
- 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.";
1932
+ if (resultCount !== previousResultCount) {
1933
+ 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.";
1934
+ }
1935
+
1936
+ return '';
1909
1937
  }
1910
1938
 
1911
1939
  var defaultProps$1 = _extends({}, defaultProps, {
@@ -2157,24 +2185,23 @@ function useSelect(userProps) {
2157
2185
  var props = _extends({}, defaultProps$1, {}, userProps);
2158
2186
 
2159
2187
  var items = props.items,
2160
- itemToString = props.itemToString,
2161
- getA11yStatusMessage = props.getA11yStatusMessage,
2162
- getA11ySelectionMessage = props.getA11ySelectionMessage,
2163
2188
  scrollIntoView = props.scrollIntoView,
2164
2189
  environment = props.environment,
2165
2190
  initialIsOpen = props.initialIsOpen,
2166
- defaultIsOpen = props.defaultIsOpen; // Initial state depending on controlled props.
2191
+ defaultIsOpen = props.defaultIsOpen,
2192
+ itemToString = props.itemToString,
2193
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
2194
+ getA11yStatusMessage = props.getA11yStatusMessage; // Initial state depending on controlled props.
2167
2195
 
2168
2196
  var initialState = getInitialState(props); // Reducer init.
2169
2197
 
2170
- var _useEnhancedReducer = useEnhancedReducer(downshiftSelectReducer, initialState, props),
2171
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2172
- isOpen = _useEnhancedReducer$.isOpen,
2173
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2174
- selectedItem = _useEnhancedReducer$.selectedItem,
2175
- inputValue = _useEnhancedReducer$.inputValue,
2176
- dispatch = _useEnhancedReducer[1];
2177
- /* Refs */
2198
+ var _useControlledState = useControlledState(downshiftSelectReducer, initialState, props),
2199
+ _useControlledState$ = _useControlledState[0],
2200
+ isOpen = _useControlledState$.isOpen,
2201
+ highlightedIndex = _useControlledState$.highlightedIndex,
2202
+ selectedItem = _useControlledState$.selectedItem,
2203
+ inputValue = _useControlledState$.inputValue,
2204
+ dispatch = _useControlledState[1]; // Refs
2178
2205
 
2179
2206
 
2180
2207
  var toggleButtonRef = react.useRef(null);
@@ -2186,13 +2213,14 @@ function useSelect(userProps) {
2186
2213
  isMouseDown: false,
2187
2214
  isTouchMove: false
2188
2215
  });
2189
- var elementIds = react.useRef(getElementIds(props)); // Some utils.
2216
+ var elementIds = react.useRef(getElementIds(props));
2217
+ var previousResultCountRef = react.useRef(); // Some utils.
2190
2218
 
2191
2219
  var getItemNodeFromIndex = function (index) {
2192
2220
  return environment.document.getElementById(elementIds.current.getItemId(index));
2193
2221
  }; // Effects.
2194
2222
 
2195
- /* Sets a11y status message on changes in isOpen. */
2223
+ /* Sets a11y status message on changes in state. */
2196
2224
 
2197
2225
 
2198
2226
  react.useEffect(function () {
@@ -2200,16 +2228,20 @@ function useSelect(userProps) {
2200
2228
  return;
2201
2229
  }
2202
2230
 
2203
- setStatus(getA11yStatusMessage({
2204
- highlightedIndex: highlightedIndex,
2205
- inputValue: inputValue,
2206
- isOpen: isOpen,
2207
- itemToString: itemToString,
2208
- resultCount: items.length,
2209
- highlightedItem: items[highlightedIndex],
2210
- selectedItem: selectedItem
2211
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2212
- }, [isOpen]);
2231
+ var previousResultCount = previousResultCountRef.current;
2232
+ updateA11yStatus(function () {
2233
+ return getA11yStatusMessage({
2234
+ isOpen: isOpen,
2235
+ highlightedIndex: highlightedIndex,
2236
+ selectedItem: selectedItem,
2237
+ inputValue: inputValue,
2238
+ highlightedItem: items[highlightedIndex],
2239
+ resultCount: items.length,
2240
+ itemToString: itemToString,
2241
+ previousResultCount: previousResultCount
2242
+ });
2243
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2244
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
2213
2245
  /* Sets a11y status message on changes in selectedItem. */
2214
2246
 
2215
2247
  react.useEffect(function () {
@@ -2217,15 +2249,19 @@ function useSelect(userProps) {
2217
2249
  return;
2218
2250
  }
2219
2251
 
2220
- setStatus(getA11ySelectionMessage({
2221
- highlightedIndex: highlightedIndex,
2222
- inputValue: inputValue,
2223
- isOpen: isOpen,
2224
- itemToString: itemToString,
2225
- resultCount: items.length,
2226
- highlightedItem: items[highlightedIndex],
2227
- selectedItem: selectedItem
2228
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2252
+ var previousResultCount = previousResultCountRef.current;
2253
+ updateA11yStatus(function () {
2254
+ return getA11ySelectionMessage({
2255
+ isOpen: isOpen,
2256
+ highlightedIndex: highlightedIndex,
2257
+ selectedItem: selectedItem,
2258
+ inputValue: inputValue,
2259
+ highlightedItem: items[highlightedIndex],
2260
+ resultCount: items.length,
2261
+ itemToString: itemToString,
2262
+ previousResultCount: previousResultCount
2263
+ });
2264
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2229
2265
  }, [selectedItem]);
2230
2266
  /* Sets cleanup for the keysSoFar after 500ms. */
2231
2267
 
@@ -2282,6 +2318,13 @@ function useSelect(userProps) {
2282
2318
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2283
2319
 
2284
2320
  }, [highlightedIndex]);
2321
+ react.useEffect(function () {
2322
+ if (isInitialMount.current) {
2323
+ return;
2324
+ }
2325
+
2326
+ previousResultCountRef.current = items.length;
2327
+ });
2285
2328
  /* Make initial ref false. */
2286
2329
 
2287
2330
  react.useEffect(function () {
@@ -2605,6 +2648,51 @@ function useSelect(userProps) {
2605
2648
  };
2606
2649
  }
2607
2650
 
2651
+ var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2652
+ var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2653
+ var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2654
+ var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2655
+ var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2656
+ var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2657
+ var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2658
+ var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2659
+ var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2660
+ var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2661
+ var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2662
+ var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2663
+ var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2664
+ var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2665
+ var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2666
+ var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2667
+ var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2668
+ var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2669
+ var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2670
+ var ControlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__controlled_prop_updated_selected_item__' : 19;
2671
+
2672
+ var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2673
+ __proto__: null,
2674
+ InputKeyDownArrowDown: InputKeyDownArrowDown,
2675
+ InputKeyDownArrowUp: InputKeyDownArrowUp,
2676
+ InputKeyDownEscape: InputKeyDownEscape,
2677
+ InputKeyDownHome: InputKeyDownHome,
2678
+ InputKeyDownEnd: InputKeyDownEnd,
2679
+ InputKeyDownEnter: InputKeyDownEnter,
2680
+ InputChange: InputChange,
2681
+ InputBlur: InputBlur,
2682
+ MenuMouseLeave: MenuMouseLeave$1,
2683
+ ItemMouseMove: ItemMouseMove$1,
2684
+ ItemClick: ItemClick$1,
2685
+ ToggleButtonClick: ToggleButtonClick$1,
2686
+ FunctionToggleMenu: FunctionToggleMenu$1,
2687
+ FunctionOpenMenu: FunctionOpenMenu$1,
2688
+ FunctionCloseMenu: FunctionCloseMenu$1,
2689
+ FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2690
+ FunctionSelectItem: FunctionSelectItem$1,
2691
+ FunctionSetInputValue: FunctionSetInputValue$1,
2692
+ FunctionReset: FunctionReset$1,
2693
+ ControlledPropUpdatedSelectedItem: ControlledPropUpdatedSelectedItem
2694
+ });
2695
+
2608
2696
  function getElementIds$1(_ref) {
2609
2697
  var id = _ref.id,
2610
2698
  inputId = _ref.inputId,
@@ -2617,7 +2705,6 @@ function getElementIds$1(_ref) {
2617
2705
  id: id
2618
2706
  }, rest)));
2619
2707
  }
2620
-
2621
2708
  function getInitialState$1(props) {
2622
2709
  var initialState = getInitialState(props);
2623
2710
  var selectedItem = initialState.selectedItem;
@@ -2631,7 +2718,6 @@ function getInitialState$1(props) {
2631
2718
  inputValue: inputValue
2632
2719
  });
2633
2720
  }
2634
-
2635
2721
  var propTypes$1 = {
2636
2722
  items: PropTypes.array.isRequired,
2637
2723
  itemToString: PropTypes.func,
@@ -2672,55 +2758,43 @@ var propTypes$1 = {
2672
2758
  })
2673
2759
  })
2674
2760
  };
2761
+ /**
2762
+ * The useCombobox version of useControlledState, which also
2763
+ * checks if the controlled prop selectedItem changed between
2764
+ * renders. If so, it will also update inputValue with its
2765
+ * string equivalent. It uses the common useControlledState to
2766
+ * compute the rest of the state.
2767
+ *
2768
+ * @param {Function} reducer Reducer function from downshift.
2769
+ * @param {Object} initialState Initial state of the hook.
2770
+ * @param {Object} props The hook props.
2771
+ * @returns {Array} An array with the state and an action dispatcher.
2772
+ */
2773
+
2774
+ function useControlledState$1(reducer, initialState, props) {
2775
+ var _useControlledStateCo = useControlledState(reducer, initialState, props),
2776
+ newState = _useControlledStateCo[0],
2777
+ dispatch = _useControlledStateCo[1];
2778
+
2779
+ var previousSelectedItemRef = react.useRef(null);
2780
+ var selectedItem = props.selectedItem,
2781
+ itemToString = props.itemToString; // ToDo: if needed, make same approach as selectedItemChanged from Downshift.
2782
+
2783
+ if (isControlledProp(props, 'selectedItem') && previousSelectedItemRef.current !== selectedItem) {
2784
+ dispatch({
2785
+ type: ControlledPropUpdatedSelectedItem,
2786
+ inputValue: itemToString(selectedItem)
2787
+ });
2788
+ }
2675
2789
 
2790
+ previousSelectedItemRef.current = selectedItem;
2791
+ return [newState, dispatch];
2792
+ }
2676
2793
  var defaultProps$2 = _extends({}, defaultProps, {
2677
2794
  getA11yStatusMessage: getA11yStatusMessage,
2678
2795
  circularNavigation: true
2679
2796
  });
2680
2797
 
2681
- var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2682
- var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2683
- var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2684
- var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2685
- var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2686
- var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2687
- var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2688
- var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2689
- var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2690
- var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2691
- var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2692
- var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2693
- var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2694
- var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2695
- var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2696
- var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2697
- var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2698
- var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2699
- var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2700
-
2701
- var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2702
- __proto__: null,
2703
- InputKeyDownArrowDown: InputKeyDownArrowDown,
2704
- InputKeyDownArrowUp: InputKeyDownArrowUp,
2705
- InputKeyDownEscape: InputKeyDownEscape,
2706
- InputKeyDownHome: InputKeyDownHome,
2707
- InputKeyDownEnd: InputKeyDownEnd,
2708
- InputKeyDownEnter: InputKeyDownEnter,
2709
- InputChange: InputChange,
2710
- InputBlur: InputBlur,
2711
- MenuMouseLeave: MenuMouseLeave$1,
2712
- ItemMouseMove: ItemMouseMove$1,
2713
- ItemClick: ItemClick$1,
2714
- ToggleButtonClick: ToggleButtonClick$1,
2715
- FunctionToggleMenu: FunctionToggleMenu$1,
2716
- FunctionOpenMenu: FunctionOpenMenu$1,
2717
- FunctionCloseMenu: FunctionCloseMenu$1,
2718
- FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2719
- FunctionSelectItem: FunctionSelectItem$1,
2720
- FunctionSetInputValue: FunctionSetInputValue$1,
2721
- FunctionReset: FunctionReset$1
2722
- });
2723
-
2724
2798
  /* eslint-disable complexity */
2725
2799
 
2726
2800
  function downshiftUseComboboxReducer(state, action) {
@@ -2860,6 +2934,7 @@ function downshiftUseComboboxReducer(state, action) {
2860
2934
  };
2861
2935
  break;
2862
2936
 
2937
+ case ControlledPropUpdatedSelectedItem:
2863
2938
  case FunctionSetInputValue$1:
2864
2939
  changes = {
2865
2940
  inputValue: action.inputValue
@@ -2905,20 +2980,20 @@ function useCombobox(userProps) {
2905
2980
  defaultIsOpen = props.defaultIsOpen,
2906
2981
  items = props.items,
2907
2982
  scrollIntoView = props.scrollIntoView,
2908
- getA11ySelectionMessage = props.getA11ySelectionMessage,
2983
+ environment = props.environment,
2909
2984
  getA11yStatusMessage = props.getA11yStatusMessage,
2910
- itemToString = props.itemToString,
2911
- environment = props.environment; // Initial state depending on controlled props.
2985
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
2986
+ itemToString = props.itemToString; // Initial state depending on controlled props.
2912
2987
 
2913
2988
  var initialState = getInitialState$1(props); // Reducer init.
2914
2989
 
2915
- var _useEnhancedReducer = useEnhancedReducer(downshiftUseComboboxReducer, initialState, props),
2916
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2917
- isOpen = _useEnhancedReducer$.isOpen,
2918
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2919
- selectedItem = _useEnhancedReducer$.selectedItem,
2920
- inputValue = _useEnhancedReducer$.inputValue,
2921
- dispatch = _useEnhancedReducer[1];
2990
+ var _useControlledState = useControlledState$1(downshiftUseComboboxReducer, initialState, props),
2991
+ _useControlledState$ = _useControlledState[0],
2992
+ isOpen = _useControlledState$.isOpen,
2993
+ highlightedIndex = _useControlledState$.highlightedIndex,
2994
+ selectedItem = _useControlledState$.selectedItem,
2995
+ inputValue = _useControlledState$.inputValue,
2996
+ dispatch = _useControlledState[1];
2922
2997
  /* Refs */
2923
2998
 
2924
2999
 
@@ -2935,25 +3010,30 @@ function useCombobox(userProps) {
2935
3010
  isTouchMove: false
2936
3011
  });
2937
3012
  var elementIds = react.useRef(getElementIds$1(props));
3013
+ var previousResultCountRef = react.useRef();
2938
3014
  /* Effects */
2939
3015
 
2940
- /* Sets a11y status message on changes in isOpen. */
3016
+ /* Sets a11y status message on changes in state. */
2941
3017
 
2942
3018
  react.useEffect(function () {
2943
3019
  if (isInitialMount.current) {
2944
3020
  return;
2945
3021
  }
2946
3022
 
2947
- setStatus(getA11yStatusMessage({
2948
- highlightedIndex: highlightedIndex,
2949
- inputValue: inputValue,
2950
- isOpen: isOpen,
2951
- itemToString: itemToString,
2952
- resultCount: items.length,
2953
- highlightedItem: items[highlightedIndex],
2954
- selectedItem: selectedItem
2955
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2956
- }, [isOpen]);
3023
+ var previousResultCount = previousResultCountRef.current;
3024
+ updateA11yStatus(function () {
3025
+ return getA11yStatusMessage({
3026
+ isOpen: isOpen,
3027
+ highlightedIndex: highlightedIndex,
3028
+ selectedItem: selectedItem,
3029
+ inputValue: inputValue,
3030
+ highlightedItem: items[highlightedIndex],
3031
+ resultCount: items.length,
3032
+ itemToString: itemToString,
3033
+ previousResultCount: previousResultCount
3034
+ });
3035
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3036
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
2957
3037
  /* Sets a11y status message on changes in selectedItem. */
2958
3038
 
2959
3039
  react.useEffect(function () {
@@ -2961,15 +3041,19 @@ function useCombobox(userProps) {
2961
3041
  return;
2962
3042
  }
2963
3043
 
2964
- setStatus(getA11ySelectionMessage({
2965
- highlightedIndex: highlightedIndex,
2966
- inputValue: inputValue,
2967
- isOpen: isOpen,
2968
- itemToString: itemToString,
2969
- resultCount: items.length,
2970
- highlightedItem: items[highlightedIndex],
2971
- selectedItem: selectedItem
2972
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3044
+ var previousResultCount = previousResultCountRef.current;
3045
+ updateA11yStatus(function () {
3046
+ return getA11ySelectionMessage({
3047
+ isOpen: isOpen,
3048
+ highlightedIndex: highlightedIndex,
3049
+ selectedItem: selectedItem,
3050
+ inputValue: inputValue,
3051
+ highlightedItem: items[highlightedIndex],
3052
+ resultCount: items.length,
3053
+ itemToString: itemToString,
3054
+ previousResultCount: previousResultCount
3055
+ });
3056
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2973
3057
  }, [selectedItem]);
2974
3058
  /* Scroll on highlighted item if change comes from keyboard. */
2975
3059
 
@@ -2999,8 +3083,13 @@ function useCombobox(userProps) {
2999
3083
  } // eslint-disable-next-line react-hooks/exhaustive-deps
3000
3084
 
3001
3085
  }, [isOpen]);
3002
- /* Make initial ref false. */
3086
+ react.useEffect(function () {
3087
+ if (isInitialMount.current) {
3088
+ return;
3089
+ }
3003
3090
 
3091
+ previousResultCountRef.current = items.length;
3092
+ });
3004
3093
  react.useEffect(function () {
3005
3094
  isInitialMount.current = false;
3006
3095
  }, []);
@@ -3096,6 +3185,11 @@ function useCombobox(userProps) {
3096
3185
  });
3097
3186
  },
3098
3187
  Enter: function Enter(event) {
3188
+ // if IME composing, wait for next Enter keydown event.
3189
+ if (event.which === 229) {
3190
+ return;
3191
+ }
3192
+
3099
3193
  event.preventDefault();
3100
3194
  dispatch({
3101
3195
  type: InputKeyDownEnter,
@@ -3642,11 +3736,11 @@ function useMultipleSelection(userProps) {
3642
3736
  keyNavigationNext = props.keyNavigationNext,
3643
3737
  keyNavigationPrevious = props.keyNavigationPrevious; // Reducer init.
3644
3738
 
3645
- var _useEnhancedReducer = useEnhancedReducer(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3646
- _useEnhancedReducer$ = _useEnhancedReducer[0],
3647
- activeIndex = _useEnhancedReducer$.activeIndex,
3648
- selectedItems = _useEnhancedReducer$.selectedItems,
3649
- dispatch = _useEnhancedReducer[1]; // Refs.
3739
+ var _useControlledState = useControlledState(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3740
+ _useControlledState$ = _useControlledState[0],
3741
+ activeIndex = _useControlledState$.activeIndex,
3742
+ selectedItems = _useControlledState$.selectedItems,
3743
+ dispatch = _useControlledState[1]; // Refs.
3650
3744
 
3651
3745
 
3652
3746
  var isInitialMount = react.useRef(true);