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
@@ -509,8 +514,12 @@ var stateChangeTypes = /*#__PURE__*/Object.freeze({
509
514
  touchEnd: touchEnd
510
515
  });
511
516
 
512
- var Downshift = /*#__PURE__*/function () {
513
- var Downshift = /*#__PURE__*/function (_Component) {
517
+ var Downshift =
518
+ /*#__PURE__*/
519
+ function () {
520
+ var Downshift =
521
+ /*#__PURE__*/
522
+ function (_Component) {
514
523
  _inheritsLoose(Downshift, _Component);
515
524
 
516
525
  function Downshift(_props) {
@@ -784,6 +793,10 @@ var Downshift = /*#__PURE__*/function () {
784
793
  }
785
794
  },
786
795
  Enter: function Enter(event) {
796
+ if (event.which === 229) {
797
+ return;
798
+ }
799
+
787
800
  var _this$getState2 = this.getState(),
788
801
  isOpen = _this$getState2.isOpen,
789
802
  highlightedIndex = _this$getState2.highlightedIndex;
@@ -1629,6 +1642,65 @@ var dropdownDefaultStateValues = {
1629
1642
  inputValue: ''
1630
1643
  };
1631
1644
 
1645
+ function callOnChangeProps(action, state, newState) {
1646
+ var props = action.props,
1647
+ type = action.type;
1648
+ var changes = {};
1649
+ Object.keys(state).forEach(function (key) {
1650
+ invokeOnChangeHandler(key, props, state, newState);
1651
+
1652
+ if (newState[key] !== state[key]) {
1653
+ changes[key] = newState[key];
1654
+ }
1655
+ });
1656
+
1657
+ if (props.onStateChange && Object.keys(changes).length) {
1658
+ props.onStateChange(_extends({
1659
+ type: type
1660
+ }, changes));
1661
+ }
1662
+ }
1663
+
1664
+ function invokeOnChangeHandler(key, props, state, newState) {
1665
+ var handler = "on" + capitalizeString(key) + "Change";
1666
+
1667
+ if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1668
+ props[handler](newState);
1669
+ }
1670
+ }
1671
+ /**
1672
+ * Default state reducer that returns the changes.
1673
+ *
1674
+ * @param {Object} s state.
1675
+ * @param {Object} a action with changes.
1676
+ * @returns {Object} changes.
1677
+ */
1678
+
1679
+
1680
+ function stateReducer(s, a) {
1681
+ return a.changes;
1682
+ }
1683
+ /**
1684
+ * Returns a message to be added to aria-live region when item is selected.
1685
+ *
1686
+ * @param {Object} selectionParameters Parameters required to build the message.
1687
+ * @returns {string} The a11y message.
1688
+ */
1689
+
1690
+
1691
+ function getA11ySelectionMessage(selectionParameters) {
1692
+ var selectedItem = selectionParameters.selectedItem,
1693
+ itemToStringLocal = selectionParameters.itemToString;
1694
+ return selectedItem ? itemToStringLocal(selectedItem) + " has been selected." : '';
1695
+ }
1696
+ /**
1697
+ * Debounced call for updating the a11y message.
1698
+ */
1699
+
1700
+
1701
+ var updateA11yStatus = debounce(function (getA11yMessage, document) {
1702
+ setStatus(getA11yMessage(), document);
1703
+ }, 200);
1632
1704
  function getElementIds(_ref) {
1633
1705
  var id = _ref.id,
1634
1706
  labelId = _ref.labelId,
@@ -1645,7 +1717,6 @@ function getElementIds(_ref) {
1645
1717
  toggleButtonId: toggleButtonId || uniqueId + "-toggle-button"
1646
1718
  };
1647
1719
  }
1648
-
1649
1720
  function getItemIndex(index, item, items) {
1650
1721
  if (index !== undefined) {
1651
1722
  return index;
@@ -1674,57 +1745,39 @@ function getPropTypesValidator(caller, propTypes) {
1674
1745
  });
1675
1746
  };
1676
1747
  }
1677
-
1678
1748
  function isAcceptedCharacterKey(key) {
1679
1749
  return /^\S{1}$/.test(key);
1680
1750
  }
1681
-
1682
1751
  function capitalizeString(string) {
1683
1752
  return "" + string.slice(0, 1).toUpperCase() + string.slice(1);
1684
1753
  }
1754
+ /**
1755
+ * Computes the controlled state using a the previous state, props,
1756
+ * two reducers, one from downshift and an optional one from the user.
1757
+ * Also calls the onChange handlers for state values that have changed.
1758
+ *
1759
+ * @param {Function} reducer Reducer function from downshift.
1760
+ * @param {Object} initialState Initial state of the hook.
1761
+ * @param {Object} props The hook props.
1762
+ * @returns {Array} An array with the state and an action dispatcher.
1763
+ */
1685
1764
 
1686
- function invokeOnChangeHandler(key, props, state, newState) {
1687
- var handler = "on" + capitalizeString(key) + "Change";
1688
-
1689
- if (props[handler] && newState[key] !== undefined && newState[key] !== state[key]) {
1690
- props[handler](newState);
1691
- }
1692
- }
1693
-
1694
- function callOnChangeProps(action, state, newState) {
1695
- var props = action.props,
1696
- type = action.type;
1697
- var changes = {};
1698
- Object.keys(state).forEach(function (key) {
1699
- invokeOnChangeHandler(key, props, state, newState);
1765
+ function useControlledState(reducer, initialState, props) {
1766
+ var _useState = preact.useState(initialState),
1767
+ uncontrolledState = _useState[0],
1768
+ setState = _useState[1];
1700
1769
 
1701
- if (newState[key] !== state[key]) {
1702
- changes[key] = newState[key];
1703
- }
1704
- });
1770
+ var state = getState(uncontrolledState, props);
1705
1771
 
1706
- if (props.onStateChange && Object.keys(changes).length) {
1707
- props.onStateChange(_extends({
1708
- type: type
1709
- }, changes));
1710
- }
1711
- }
1712
-
1713
- function useEnhancedReducer(reducer, initialState, props) {
1714
- var enhancedReducer = preact.useCallback(function (state, action) {
1715
- state = getState(state, action.props);
1716
- var stateReduceLocal = action.props.stateReducer;
1772
+ var dispatch = function (action) {
1773
+ var stateReducerFromProps = action.props.stateReducer;
1717
1774
  var changes = reducer(state, action);
1718
- var newState = stateReduceLocal(state, _extends({}, action, {
1775
+ var newState = stateReducerFromProps(state, _extends({}, action, {
1719
1776
  changes: changes
1720
1777
  }));
1721
1778
  callOnChangeProps(action, state, newState);
1722
- return newState;
1723
- }, [reducer]);
1724
-
1725
- var _useReducer = preact.useReducer(enhancedReducer, initialState),
1726
- state = _useReducer[0],
1727
- dispatch = _useReducer[1];
1779
+ setState(newState);
1780
+ };
1728
1781
 
1729
1782
  return [getState(state, props), function dispatchWithProps(action) {
1730
1783
  return dispatch(_extends({
@@ -1732,32 +1785,6 @@ function useEnhancedReducer(reducer, initialState, props) {
1732
1785
  }, action));
1733
1786
  }];
1734
1787
  }
1735
- /**
1736
- * Default state reducer that returns the changes.
1737
- *
1738
- * @param {Object} s state.
1739
- * @param {Object} a action with changes.
1740
- * @returns {Object} changes.
1741
- */
1742
-
1743
-
1744
- function stateReducer(s, a) {
1745
- return a.changes;
1746
- }
1747
- /**
1748
- * Returns a message to be added to aria-live region when item is selected.
1749
- *
1750
- * @param {Object} selectionParameters Parameters required to build the message.
1751
- * @returns {string} The a11y message.
1752
- */
1753
-
1754
-
1755
- function getA11ySelectionMessage(selectionParameters) {
1756
- var selectedItem = selectionParameters.selectedItem,
1757
- itemToStringLocal = selectionParameters.itemToString;
1758
- return itemToStringLocal(selectedItem) + " has been selected.";
1759
- }
1760
-
1761
1788
  var defaultProps = {
1762
1789
  itemToString: itemToString,
1763
1790
  stateReducer: stateReducer,
@@ -1768,7 +1795,6 @@ var defaultProps = {
1768
1795
  /* istanbul ignore next (ssr) */
1769
1796
  ? {} : window
1770
1797
  };
1771
-
1772
1798
  function getDefaultValue(props, propKey, defaultStateValues) {
1773
1799
  if (defaultStateValues === void 0) {
1774
1800
  defaultStateValues = dropdownDefaultStateValues;
@@ -1782,7 +1808,6 @@ function getDefaultValue(props, propKey, defaultStateValues) {
1782
1808
 
1783
1809
  return defaultStateValues[propKey];
1784
1810
  }
1785
-
1786
1811
  function getInitialValue(props, propKey, defaultStateValues) {
1787
1812
  if (defaultStateValues === void 0) {
1788
1813
  defaultStateValues = dropdownDefaultStateValues;
@@ -1800,7 +1825,6 @@ function getInitialValue(props, propKey, defaultStateValues) {
1800
1825
 
1801
1826
  return getDefaultValue(props, propKey, defaultStateValues);
1802
1827
  }
1803
-
1804
1828
  function getInitialState(props) {
1805
1829
  var selectedItem = getInitialValue(props, 'selectedItem');
1806
1830
  var isOpen = getInitialValue(props, 'isOpen');
@@ -1813,7 +1837,6 @@ function getInitialState(props) {
1813
1837
  inputValue: inputValue
1814
1838
  };
1815
1839
  }
1816
-
1817
1840
  function getHighlightedIndexOnOpen(props, state, offset, getItemNodeFromIndex) {
1818
1841
  var items = props.items,
1819
1842
  initialHighlightedIndex = props.initialHighlightedIndex,
@@ -1920,7 +1943,8 @@ var propTypes = {
1920
1943
 
1921
1944
  function getA11yStatusMessage$1(_ref) {
1922
1945
  var isOpen = _ref.isOpen,
1923
- resultCount = _ref.resultCount;
1946
+ resultCount = _ref.resultCount,
1947
+ previousResultCount = _ref.previousResultCount;
1924
1948
 
1925
1949
  if (!isOpen) {
1926
1950
  return '';
@@ -1930,7 +1954,11 @@ function getA11yStatusMessage$1(_ref) {
1930
1954
  return 'No results are available.';
1931
1955
  }
1932
1956
 
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.";
1957
+ if (resultCount !== previousResultCount) {
1958
+ 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.";
1959
+ }
1960
+
1961
+ return '';
1934
1962
  }
1935
1963
 
1936
1964
  var defaultProps$1 = _extends({}, defaultProps, {
@@ -2182,24 +2210,23 @@ function useSelect(userProps) {
2182
2210
  var props = _extends({}, defaultProps$1, {}, userProps);
2183
2211
 
2184
2212
  var items = props.items,
2185
- itemToString = props.itemToString,
2186
- getA11yStatusMessage = props.getA11yStatusMessage,
2187
- getA11ySelectionMessage = props.getA11ySelectionMessage,
2188
2213
  scrollIntoView = props.scrollIntoView,
2189
2214
  environment = props.environment,
2190
2215
  initialIsOpen = props.initialIsOpen,
2191
- defaultIsOpen = props.defaultIsOpen; // Initial state depending on controlled props.
2216
+ defaultIsOpen = props.defaultIsOpen,
2217
+ itemToString = props.itemToString,
2218
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
2219
+ getA11yStatusMessage = props.getA11yStatusMessage; // Initial state depending on controlled props.
2192
2220
 
2193
2221
  var initialState = getInitialState(props); // Reducer init.
2194
2222
 
2195
- var _useEnhancedReducer = useEnhancedReducer(downshiftSelectReducer, initialState, props),
2196
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2197
- isOpen = _useEnhancedReducer$.isOpen,
2198
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2199
- selectedItem = _useEnhancedReducer$.selectedItem,
2200
- inputValue = _useEnhancedReducer$.inputValue,
2201
- dispatch = _useEnhancedReducer[1];
2202
- /* Refs */
2223
+ var _useControlledState = useControlledState(downshiftSelectReducer, initialState, props),
2224
+ _useControlledState$ = _useControlledState[0],
2225
+ isOpen = _useControlledState$.isOpen,
2226
+ highlightedIndex = _useControlledState$.highlightedIndex,
2227
+ selectedItem = _useControlledState$.selectedItem,
2228
+ inputValue = _useControlledState$.inputValue,
2229
+ dispatch = _useControlledState[1]; // Refs
2203
2230
 
2204
2231
 
2205
2232
  var toggleButtonRef = preact.useRef(null);
@@ -2211,13 +2238,14 @@ function useSelect(userProps) {
2211
2238
  isMouseDown: false,
2212
2239
  isTouchMove: false
2213
2240
  });
2214
- var elementIds = preact.useRef(getElementIds(props)); // Some utils.
2241
+ var elementIds = preact.useRef(getElementIds(props));
2242
+ var previousResultCountRef = preact.useRef(); // Some utils.
2215
2243
 
2216
2244
  var getItemNodeFromIndex = function (index) {
2217
2245
  return environment.document.getElementById(elementIds.current.getItemId(index));
2218
2246
  }; // Effects.
2219
2247
 
2220
- /* Sets a11y status message on changes in isOpen. */
2248
+ /* Sets a11y status message on changes in state. */
2221
2249
 
2222
2250
 
2223
2251
  preact.useEffect(function () {
@@ -2225,16 +2253,20 @@ function useSelect(userProps) {
2225
2253
  return;
2226
2254
  }
2227
2255
 
2228
- setStatus(getA11yStatusMessage({
2229
- highlightedIndex: highlightedIndex,
2230
- inputValue: inputValue,
2231
- isOpen: isOpen,
2232
- itemToString: itemToString,
2233
- resultCount: items.length,
2234
- highlightedItem: items[highlightedIndex],
2235
- selectedItem: selectedItem
2236
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2237
- }, [isOpen]);
2256
+ var previousResultCount = previousResultCountRef.current;
2257
+ updateA11yStatus(function () {
2258
+ return getA11yStatusMessage({
2259
+ isOpen: isOpen,
2260
+ highlightedIndex: highlightedIndex,
2261
+ selectedItem: selectedItem,
2262
+ inputValue: inputValue,
2263
+ highlightedItem: items[highlightedIndex],
2264
+ resultCount: items.length,
2265
+ itemToString: itemToString,
2266
+ previousResultCount: previousResultCount
2267
+ });
2268
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2269
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
2238
2270
  /* Sets a11y status message on changes in selectedItem. */
2239
2271
 
2240
2272
  preact.useEffect(function () {
@@ -2242,15 +2274,19 @@ function useSelect(userProps) {
2242
2274
  return;
2243
2275
  }
2244
2276
 
2245
- setStatus(getA11ySelectionMessage({
2246
- highlightedIndex: highlightedIndex,
2247
- inputValue: inputValue,
2248
- isOpen: isOpen,
2249
- itemToString: itemToString,
2250
- resultCount: items.length,
2251
- highlightedItem: items[highlightedIndex],
2252
- selectedItem: selectedItem
2253
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2277
+ var previousResultCount = previousResultCountRef.current;
2278
+ updateA11yStatus(function () {
2279
+ return getA11ySelectionMessage({
2280
+ isOpen: isOpen,
2281
+ highlightedIndex: highlightedIndex,
2282
+ selectedItem: selectedItem,
2283
+ inputValue: inputValue,
2284
+ highlightedItem: items[highlightedIndex],
2285
+ resultCount: items.length,
2286
+ itemToString: itemToString,
2287
+ previousResultCount: previousResultCount
2288
+ });
2289
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2254
2290
  }, [selectedItem]);
2255
2291
  /* Sets cleanup for the keysSoFar after 500ms. */
2256
2292
 
@@ -2307,6 +2343,13 @@ function useSelect(userProps) {
2307
2343
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2308
2344
 
2309
2345
  }, [highlightedIndex]);
2346
+ preact.useEffect(function () {
2347
+ if (isInitialMount.current) {
2348
+ return;
2349
+ }
2350
+
2351
+ previousResultCountRef.current = items.length;
2352
+ });
2310
2353
  /* Make initial ref false. */
2311
2354
 
2312
2355
  preact.useEffect(function () {
@@ -2630,6 +2673,51 @@ function useSelect(userProps) {
2630
2673
  };
2631
2674
  }
2632
2675
 
2676
+ var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2677
+ var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2678
+ var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2679
+ var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2680
+ var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2681
+ var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2682
+ var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2683
+ var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2684
+ var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2685
+ var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2686
+ var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2687
+ var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2688
+ var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2689
+ var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2690
+ var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2691
+ var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2692
+ var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2693
+ var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2694
+ var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2695
+ var ControlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__controlled_prop_updated_selected_item__' : 19;
2696
+
2697
+ var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2698
+ __proto__: null,
2699
+ InputKeyDownArrowDown: InputKeyDownArrowDown,
2700
+ InputKeyDownArrowUp: InputKeyDownArrowUp,
2701
+ InputKeyDownEscape: InputKeyDownEscape,
2702
+ InputKeyDownHome: InputKeyDownHome,
2703
+ InputKeyDownEnd: InputKeyDownEnd,
2704
+ InputKeyDownEnter: InputKeyDownEnter,
2705
+ InputChange: InputChange,
2706
+ InputBlur: InputBlur,
2707
+ MenuMouseLeave: MenuMouseLeave$1,
2708
+ ItemMouseMove: ItemMouseMove$1,
2709
+ ItemClick: ItemClick$1,
2710
+ ToggleButtonClick: ToggleButtonClick$1,
2711
+ FunctionToggleMenu: FunctionToggleMenu$1,
2712
+ FunctionOpenMenu: FunctionOpenMenu$1,
2713
+ FunctionCloseMenu: FunctionCloseMenu$1,
2714
+ FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2715
+ FunctionSelectItem: FunctionSelectItem$1,
2716
+ FunctionSetInputValue: FunctionSetInputValue$1,
2717
+ FunctionReset: FunctionReset$1,
2718
+ ControlledPropUpdatedSelectedItem: ControlledPropUpdatedSelectedItem
2719
+ });
2720
+
2633
2721
  function getElementIds$1(_ref) {
2634
2722
  var id = _ref.id,
2635
2723
  inputId = _ref.inputId,
@@ -2642,7 +2730,6 @@ function getElementIds$1(_ref) {
2642
2730
  id: id
2643
2731
  }, rest)));
2644
2732
  }
2645
-
2646
2733
  function getInitialState$1(props) {
2647
2734
  var initialState = getInitialState(props);
2648
2735
  var selectedItem = initialState.selectedItem;
@@ -2656,7 +2743,6 @@ function getInitialState$1(props) {
2656
2743
  inputValue: inputValue
2657
2744
  });
2658
2745
  }
2659
-
2660
2746
  var propTypes$1 = {
2661
2747
  items: PropTypes.array.isRequired,
2662
2748
  itemToString: PropTypes.func,
@@ -2697,55 +2783,43 @@ var propTypes$1 = {
2697
2783
  })
2698
2784
  })
2699
2785
  };
2786
+ /**
2787
+ * The useCombobox version of useControlledState, which also
2788
+ * checks if the controlled prop selectedItem changed between
2789
+ * renders. If so, it will also update inputValue with its
2790
+ * string equivalent. It uses the common useControlledState to
2791
+ * compute the rest of the state.
2792
+ *
2793
+ * @param {Function} reducer Reducer function from downshift.
2794
+ * @param {Object} initialState Initial state of the hook.
2795
+ * @param {Object} props The hook props.
2796
+ * @returns {Array} An array with the state and an action dispatcher.
2797
+ */
2798
+
2799
+ function useControlledState$1(reducer, initialState, props) {
2800
+ var _useControlledStateCo = useControlledState(reducer, initialState, props),
2801
+ newState = _useControlledStateCo[0],
2802
+ dispatch = _useControlledStateCo[1];
2803
+
2804
+ var previousSelectedItemRef = preact.useRef(null);
2805
+ var selectedItem = props.selectedItem,
2806
+ itemToString = props.itemToString; // ToDo: if needed, make same approach as selectedItemChanged from Downshift.
2807
+
2808
+ if (isControlledProp(props, 'selectedItem') && previousSelectedItemRef.current !== selectedItem) {
2809
+ dispatch({
2810
+ type: ControlledPropUpdatedSelectedItem,
2811
+ inputValue: itemToString(selectedItem)
2812
+ });
2813
+ }
2700
2814
 
2815
+ previousSelectedItemRef.current = selectedItem;
2816
+ return [newState, dispatch];
2817
+ }
2701
2818
  var defaultProps$2 = _extends({}, defaultProps, {
2702
2819
  getA11yStatusMessage: getA11yStatusMessage,
2703
2820
  circularNavigation: true
2704
2821
  });
2705
2822
 
2706
- var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
2707
- var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
2708
- var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
2709
- var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
2710
- var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
2711
- var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 5;
2712
- var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 6;
2713
- var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 7;
2714
- var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 8;
2715
- var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 9;
2716
- var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 10;
2717
- var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 11;
2718
- var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 12;
2719
- var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 13;
2720
- var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 14;
2721
- var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 15;
2722
- var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 16;
2723
- var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 17;
2724
- var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 18;
2725
-
2726
- var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
2727
- __proto__: null,
2728
- InputKeyDownArrowDown: InputKeyDownArrowDown,
2729
- InputKeyDownArrowUp: InputKeyDownArrowUp,
2730
- InputKeyDownEscape: InputKeyDownEscape,
2731
- InputKeyDownHome: InputKeyDownHome,
2732
- InputKeyDownEnd: InputKeyDownEnd,
2733
- InputKeyDownEnter: InputKeyDownEnter,
2734
- InputChange: InputChange,
2735
- InputBlur: InputBlur,
2736
- MenuMouseLeave: MenuMouseLeave$1,
2737
- ItemMouseMove: ItemMouseMove$1,
2738
- ItemClick: ItemClick$1,
2739
- ToggleButtonClick: ToggleButtonClick$1,
2740
- FunctionToggleMenu: FunctionToggleMenu$1,
2741
- FunctionOpenMenu: FunctionOpenMenu$1,
2742
- FunctionCloseMenu: FunctionCloseMenu$1,
2743
- FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
2744
- FunctionSelectItem: FunctionSelectItem$1,
2745
- FunctionSetInputValue: FunctionSetInputValue$1,
2746
- FunctionReset: FunctionReset$1
2747
- });
2748
-
2749
2823
  /* eslint-disable complexity */
2750
2824
 
2751
2825
  function downshiftUseComboboxReducer(state, action) {
@@ -2885,6 +2959,7 @@ function downshiftUseComboboxReducer(state, action) {
2885
2959
  };
2886
2960
  break;
2887
2961
 
2962
+ case ControlledPropUpdatedSelectedItem:
2888
2963
  case FunctionSetInputValue$1:
2889
2964
  changes = {
2890
2965
  inputValue: action.inputValue
@@ -2930,20 +3005,20 @@ function useCombobox(userProps) {
2930
3005
  defaultIsOpen = props.defaultIsOpen,
2931
3006
  items = props.items,
2932
3007
  scrollIntoView = props.scrollIntoView,
2933
- getA11ySelectionMessage = props.getA11ySelectionMessage,
3008
+ environment = props.environment,
2934
3009
  getA11yStatusMessage = props.getA11yStatusMessage,
2935
- itemToString = props.itemToString,
2936
- environment = props.environment; // Initial state depending on controlled props.
3010
+ getA11ySelectionMessage = props.getA11ySelectionMessage,
3011
+ itemToString = props.itemToString; // Initial state depending on controlled props.
2937
3012
 
2938
3013
  var initialState = getInitialState$1(props); // Reducer init.
2939
3014
 
2940
- var _useEnhancedReducer = useEnhancedReducer(downshiftUseComboboxReducer, initialState, props),
2941
- _useEnhancedReducer$ = _useEnhancedReducer[0],
2942
- isOpen = _useEnhancedReducer$.isOpen,
2943
- highlightedIndex = _useEnhancedReducer$.highlightedIndex,
2944
- selectedItem = _useEnhancedReducer$.selectedItem,
2945
- inputValue = _useEnhancedReducer$.inputValue,
2946
- dispatch = _useEnhancedReducer[1];
3015
+ var _useControlledState = useControlledState$1(downshiftUseComboboxReducer, initialState, props),
3016
+ _useControlledState$ = _useControlledState[0],
3017
+ isOpen = _useControlledState$.isOpen,
3018
+ highlightedIndex = _useControlledState$.highlightedIndex,
3019
+ selectedItem = _useControlledState$.selectedItem,
3020
+ inputValue = _useControlledState$.inputValue,
3021
+ dispatch = _useControlledState[1];
2947
3022
  /* Refs */
2948
3023
 
2949
3024
 
@@ -2960,25 +3035,30 @@ function useCombobox(userProps) {
2960
3035
  isTouchMove: false
2961
3036
  });
2962
3037
  var elementIds = preact.useRef(getElementIds$1(props));
3038
+ var previousResultCountRef = preact.useRef();
2963
3039
  /* Effects */
2964
3040
 
2965
- /* Sets a11y status message on changes in isOpen. */
3041
+ /* Sets a11y status message on changes in state. */
2966
3042
 
2967
3043
  preact.useEffect(function () {
2968
3044
  if (isInitialMount.current) {
2969
3045
  return;
2970
3046
  }
2971
3047
 
2972
- setStatus(getA11yStatusMessage({
2973
- highlightedIndex: highlightedIndex,
2974
- inputValue: inputValue,
2975
- isOpen: isOpen,
2976
- itemToString: itemToString,
2977
- resultCount: items.length,
2978
- highlightedItem: items[highlightedIndex],
2979
- selectedItem: selectedItem
2980
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2981
- }, [isOpen]);
3048
+ var previousResultCount = previousResultCountRef.current;
3049
+ updateA11yStatus(function () {
3050
+ return getA11yStatusMessage({
3051
+ isOpen: isOpen,
3052
+ highlightedIndex: highlightedIndex,
3053
+ selectedItem: selectedItem,
3054
+ inputValue: inputValue,
3055
+ highlightedItem: items[highlightedIndex],
3056
+ resultCount: items.length,
3057
+ itemToString: itemToString,
3058
+ previousResultCount: previousResultCount
3059
+ });
3060
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3061
+ }, [isOpen, highlightedIndex, selectedItem, inputValue]);
2982
3062
  /* Sets a11y status message on changes in selectedItem. */
2983
3063
 
2984
3064
  preact.useEffect(function () {
@@ -2986,15 +3066,19 @@ function useCombobox(userProps) {
2986
3066
  return;
2987
3067
  }
2988
3068
 
2989
- setStatus(getA11ySelectionMessage({
2990
- highlightedIndex: highlightedIndex,
2991
- inputValue: inputValue,
2992
- isOpen: isOpen,
2993
- itemToString: itemToString,
2994
- resultCount: items.length,
2995
- highlightedItem: items[highlightedIndex],
2996
- selectedItem: selectedItem
2997
- }), environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
3069
+ var previousResultCount = previousResultCountRef.current;
3070
+ updateA11yStatus(function () {
3071
+ return getA11ySelectionMessage({
3072
+ isOpen: isOpen,
3073
+ highlightedIndex: highlightedIndex,
3074
+ selectedItem: selectedItem,
3075
+ inputValue: inputValue,
3076
+ highlightedItem: items[highlightedIndex],
3077
+ resultCount: items.length,
3078
+ itemToString: itemToString,
3079
+ previousResultCount: previousResultCount
3080
+ });
3081
+ }, environment.document); // eslint-disable-next-line react-hooks/exhaustive-deps
2998
3082
  }, [selectedItem]);
2999
3083
  /* Scroll on highlighted item if change comes from keyboard. */
3000
3084
 
@@ -3024,8 +3108,13 @@ function useCombobox(userProps) {
3024
3108
  } // eslint-disable-next-line react-hooks/exhaustive-deps
3025
3109
 
3026
3110
  }, [isOpen]);
3027
- /* Make initial ref false. */
3111
+ preact.useEffect(function () {
3112
+ if (isInitialMount.current) {
3113
+ return;
3114
+ }
3028
3115
 
3116
+ previousResultCountRef.current = items.length;
3117
+ });
3029
3118
  preact.useEffect(function () {
3030
3119
  isInitialMount.current = false;
3031
3120
  }, []);
@@ -3121,6 +3210,11 @@ function useCombobox(userProps) {
3121
3210
  });
3122
3211
  },
3123
3212
  Enter: function Enter(event) {
3213
+ // if IME composing, wait for next Enter keydown event.
3214
+ if (event.which === 229) {
3215
+ return;
3216
+ }
3217
+
3124
3218
  event.preventDefault();
3125
3219
  dispatch({
3126
3220
  type: InputKeyDownEnter,
@@ -3651,11 +3745,11 @@ function useMultipleSelection(userProps) {
3651
3745
  keyNavigationNext = props.keyNavigationNext,
3652
3746
  keyNavigationPrevious = props.keyNavigationPrevious; // Reducer init.
3653
3747
 
3654
- var _useEnhancedReducer = useEnhancedReducer(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3655
- _useEnhancedReducer$ = _useEnhancedReducer[0],
3656
- activeIndex = _useEnhancedReducer$.activeIndex,
3657
- selectedItems = _useEnhancedReducer$.selectedItems,
3658
- dispatch = _useEnhancedReducer[1]; // Refs.
3748
+ var _useControlledState = useControlledState(downshiftMultipleSelectionReducer, getInitialState$2(props), props),
3749
+ _useControlledState$ = _useControlledState[0],
3750
+ activeIndex = _useControlledState$.activeIndex,
3751
+ selectedItems = _useControlledState$.selectedItems,
3752
+ dispatch = _useControlledState[1]; // Refs.
3659
3753
 
3660
3754
 
3661
3755
  var isInitialMount = preact.useRef(true);