downshift 8.4.0 → 8.5.0

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.
@@ -1828,17 +1828,15 @@ function getHighlightedIndexOnOpen(props, state, offset) {
1828
1828
  }
1829
1829
  return offset < 0 ? items.length - 1 : 0;
1830
1830
  }
1831
-
1832
1831
  /**
1833
- * Reuse the movement tracking of mouse and touch events.
1832
+ * Tracks mouse and touch events, such as mouseDown, touchMove and touchEnd.
1834
1833
  *
1835
- * @param {boolean} isOpen Whether the dropdown is open or not.
1836
- * @param {Array<Object>} downshiftElementRefs Downshift element refs to track movement (toggleButton, menu etc.)
1837
- * @param {Object} environment Environment where component/hook exists.
1838
- * @param {Function} handleBlur Handler on blur from mouse or touch.
1839
- * @returns {Object} Ref containing whether mouseDown or touchMove event is happening
1834
+ * @param {Object} environment The environment to add the event listeners to, for instance window.
1835
+ * @param {Array<HTMLElement>} downshiftElementRefs The refs for the element that should not trigger a blur action from mouseDown or touchEnd.
1836
+ * @param {Function} handleBlur The function that is called if mouseDown or touchEnd occured outside the downshiftElements.
1837
+ * @returns {Object} The mouse and touch events information, if any of are happening.
1840
1838
  */
1841
- function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, handleBlur) {
1839
+ function useMouseAndTouchTracker(environment, downshiftElementRefs, handleBlur) {
1842
1840
  var mouseAndTouchTrackersRef = React.useRef({
1843
1841
  isMouseDown: false,
1844
1842
  isTouchMove: false,
@@ -1846,45 +1844,39 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
1846
1844
  });
1847
1845
  React.useEffect(function () {
1848
1846
  if (!environment) {
1849
- return;
1847
+ return noop;
1850
1848
  }
1851
-
1852
- // The same strategy for checking if a click occurred inside or outside downshift
1853
- // as in downshift.js.
1854
- var onMouseDown = function onMouseDown() {
1849
+ var downshiftElements = downshiftElementRefs.map(function (ref) {
1850
+ return ref.current;
1851
+ });
1852
+ function onMouseDown() {
1855
1853
  mouseAndTouchTrackersRef.current.isTouchEnd = false; // reset this one.
1856
1854
  mouseAndTouchTrackersRef.current.isMouseDown = true;
1857
- };
1858
- var onMouseUp = function onMouseUp(event) {
1855
+ }
1856
+ function onMouseUp(event) {
1859
1857
  mouseAndTouchTrackersRef.current.isMouseDown = false;
1860
- if (isOpen && !targetWithinDownshift(event.target, downshiftElementRefs.map(function (ref) {
1861
- return ref.current;
1862
- }), environment)) {
1858
+ if (!targetWithinDownshift(event.target, downshiftElements, environment)) {
1863
1859
  handleBlur();
1864
1860
  }
1865
- };
1866
- var onTouchStart = function onTouchStart() {
1861
+ }
1862
+ function onTouchStart() {
1867
1863
  mouseAndTouchTrackersRef.current.isTouchEnd = false;
1868
1864
  mouseAndTouchTrackersRef.current.isTouchMove = false;
1869
- };
1870
- var onTouchMove = function onTouchMove() {
1865
+ }
1866
+ function onTouchMove() {
1871
1867
  mouseAndTouchTrackersRef.current.isTouchMove = true;
1872
- };
1873
- var onTouchEnd = function onTouchEnd(event) {
1868
+ }
1869
+ function onTouchEnd(event) {
1874
1870
  mouseAndTouchTrackersRef.current.isTouchEnd = true;
1875
- if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, downshiftElementRefs.map(function (ref) {
1876
- return ref.current;
1877
- }), environment, false)) {
1871
+ if (!mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, downshiftElements, environment, false)) {
1878
1872
  handleBlur();
1879
1873
  }
1880
- };
1874
+ }
1881
1875
  environment.addEventListener('mousedown', onMouseDown);
1882
1876
  environment.addEventListener('mouseup', onMouseUp);
1883
1877
  environment.addEventListener('touchstart', onTouchStart);
1884
1878
  environment.addEventListener('touchmove', onTouchMove);
1885
1879
  environment.addEventListener('touchend', onTouchEnd);
1886
-
1887
- // eslint-disable-next-line consistent-return
1888
1880
  return function cleanup() {
1889
1881
  environment.removeEventListener('mousedown', onMouseDown);
1890
1882
  environment.removeEventListener('mouseup', onMouseUp);
@@ -1892,9 +1884,9 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
1892
1884
  environment.removeEventListener('touchmove', onTouchMove);
1893
1885
  environment.removeEventListener('touchend', onTouchEnd);
1894
1886
  };
1895
- // eslint-disable-next-line react-hooks/exhaustive-deps
1896
- }, [isOpen, environment]);
1897
- return mouseAndTouchTrackersRef;
1887
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- refs don't change
1888
+ }, [environment, handleBlur]);
1889
+ return mouseAndTouchTrackersRef.current;
1898
1890
  }
1899
1891
 
1900
1892
  /* istanbul ignore next */
@@ -2487,12 +2479,13 @@ function useSelect(userProps) {
2487
2479
  }
2488
2480
  // eslint-disable-next-line react-hooks/exhaustive-deps
2489
2481
  }, []);
2490
- // Add mouse/touch events to document.
2491
- var mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [menuRef, toggleButtonRef], environment, function () {
2492
- dispatch({
2493
- type: ToggleButtonBlur
2494
- });
2495
- });
2482
+ var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, [toggleButtonRef, menuRef], React.useCallback(function handleBlur() {
2483
+ if (latest.current.state.isOpen) {
2484
+ dispatch({
2485
+ type: ToggleButtonBlur
2486
+ });
2487
+ }
2488
+ }, [dispatch, latest]));
2496
2489
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
2497
2490
  // Reset itemRefs on close.
2498
2491
  React.useEffect(function () {
@@ -2678,7 +2671,7 @@ function useSelect(userProps) {
2678
2671
  });
2679
2672
  };
2680
2673
  var toggleButtonHandleBlur = function toggleButtonHandleBlur() {
2681
- if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
2674
+ if (latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
2682
2675
  dispatch({
2683
2676
  type: ToggleButtonBlur
2684
2677
  });
@@ -2707,7 +2700,7 @@ function useSelect(userProps) {
2707
2700
  }
2708
2701
  setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
2709
2702
  return toggleProps;
2710
- }, [latest, elementIds, setGetterPropCallInfo, dispatch, mouseAndTouchTrackersRef, toggleButtonKeyDownHandlers]);
2703
+ }, [dispatch, elementIds, latest, mouseAndTouchTrackers, setGetterPropCallInfo, toggleButtonKeyDownHandlers]);
2711
2704
  var getItemProps = React.useCallback(function (_temp6) {
2712
2705
  var _extends4;
2713
2706
  var _ref6 = _temp6 === void 0 ? {} : _temp6,
@@ -2733,7 +2726,7 @@ function useSelect(userProps) {
2733
2726
  index = _getItemAndIndex[1];
2734
2727
  var disabled = latestProps.isItemDisabled(item, index);
2735
2728
  var itemHandleMouseMove = function itemHandleMouseMove() {
2736
- if (mouseAndTouchTrackersRef.current.isTouchEnd || index === latestState.highlightedIndex) {
2729
+ if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
2737
2730
  return;
2738
2731
  }
2739
2732
  shouldScrollRef.current = false;
@@ -2767,7 +2760,7 @@ function useSelect(userProps) {
2767
2760
  itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
2768
2761
  itemProps.onMouseDown = callAllEventHandlers(onMouseDown, itemHandleMouseDown);
2769
2762
  return itemProps;
2770
- }, [latest, elementIds, mouseAndTouchTrackersRef, shouldScrollRef, dispatch]);
2763
+ }, [latest, elementIds, mouseAndTouchTrackers, shouldScrollRef, dispatch]);
2771
2764
  return {
2772
2765
  // prop getters.
2773
2766
  getToggleButtonProps: getToggleButtonProps,
@@ -3128,13 +3121,14 @@ function useCombobox(userProps) {
3128
3121
  previousResultCountRef.current = items.length;
3129
3122
  }
3130
3123
  });
3131
- // Add mouse/touch events to document.
3132
- var mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [inputRef, menuRef, toggleButtonRef], environment, function () {
3133
- dispatch({
3134
- type: InputBlur,
3135
- selectItem: false
3136
- });
3137
- });
3124
+ var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, [toggleButtonRef, menuRef, inputRef], React.useCallback(function handleBlur() {
3125
+ if (latest.current.state.isOpen) {
3126
+ dispatch({
3127
+ type: InputBlur,
3128
+ selectItem: false
3129
+ });
3130
+ }
3131
+ }, [dispatch, latest]));
3138
3132
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
3139
3133
  // Reset itemRefs on close.
3140
3134
  React.useEffect(function () {
@@ -3282,7 +3276,7 @@ function useCombobox(userProps) {
3282
3276
  var onSelectKey = 'onClick';
3283
3277
  var customClickHandler = onClick;
3284
3278
  var itemHandleMouseMove = function itemHandleMouseMove() {
3285
- if (mouseAndTouchTrackersRef.current.isTouchEnd || index === latestState.highlightedIndex) {
3279
+ if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
3286
3280
  return;
3287
3281
  }
3288
3282
  shouldScrollRef.current = false;
@@ -3310,7 +3304,7 @@ function useCombobox(userProps) {
3310
3304
  onMouseMove: callAllEventHandlers(onMouseMove, itemHandleMouseMove),
3311
3305
  onMouseDown: callAllEventHandlers(onMouseDown, itemHandleMouseDown)
3312
3306
  }, rest);
3313
- }, [dispatch, elementIds, latest, mouseAndTouchTrackersRef, shouldScrollRef]);
3307
+ }, [dispatch, elementIds, latest, mouseAndTouchTrackers, shouldScrollRef]);
3314
3308
  var getToggleButtonProps = React.useCallback(function (_temp4) {
3315
3309
  var _extends4;
3316
3310
  var _ref5 = _temp4 === void 0 ? {} : _temp4,
@@ -3364,7 +3358,7 @@ function useCombobox(userProps) {
3364
3358
  };
3365
3359
  var inputHandleBlur = function inputHandleBlur(event) {
3366
3360
  /* istanbul ignore else */
3367
- if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
3361
+ if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
3368
3362
  var isBlurByTabChange = event.relatedTarget === null && environment.document.activeElement !== environment.document.body;
3369
3363
  dispatch({
3370
3364
  type: InputBlur,
@@ -3388,7 +3382,7 @@ function useCombobox(userProps) {
3388
3382
  return _extends__default["default"]((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
3389
3383
  inputRef.current = inputNode;
3390
3384
  }), _extends5['aria-activedescendant'] = latestState.isOpen && latestState.highlightedIndex > -1 ? elementIds.getItemId(latestState.highlightedIndex) : '', _extends5['aria-autocomplete'] = 'list', _extends5['aria-controls'] = elementIds.menuId, _extends5['aria-expanded'] = latestState.isOpen, _extends5['aria-labelledby'] = rest && rest['aria-label'] ? undefined : elementIds.labelId, _extends5.autoComplete = 'off', _extends5.id = elementIds.inputId, _extends5.role = 'combobox', _extends5.value = latestState.inputValue, _extends5), eventHandlers, rest);
3391
- }, [setGetterPropCallInfo, latest, elementIds, inputKeyDownHandlers, dispatch, mouseAndTouchTrackersRef, environment]);
3385
+ }, [dispatch, elementIds, environment, inputKeyDownHandlers, latest, mouseAndTouchTrackers, setGetterPropCallInfo]);
3392
3386
 
3393
3387
  // returns
3394
3388
  var toggleMenu = React.useCallback(function () {
@@ -1815,17 +1815,15 @@ function getHighlightedIndexOnOpen(props, state, offset) {
1815
1815
  }
1816
1816
  return offset < 0 ? items.length - 1 : 0;
1817
1817
  }
1818
-
1819
1818
  /**
1820
- * Reuse the movement tracking of mouse and touch events.
1819
+ * Tracks mouse and touch events, such as mouseDown, touchMove and touchEnd.
1821
1820
  *
1822
- * @param {boolean} isOpen Whether the dropdown is open or not.
1823
- * @param {Array<Object>} downshiftElementRefs Downshift element refs to track movement (toggleButton, menu etc.)
1824
- * @param {Object} environment Environment where component/hook exists.
1825
- * @param {Function} handleBlur Handler on blur from mouse or touch.
1826
- * @returns {Object} Ref containing whether mouseDown or touchMove event is happening
1821
+ * @param {Object} environment The environment to add the event listeners to, for instance window.
1822
+ * @param {Array<HTMLElement>} downshiftElementRefs The refs for the element that should not trigger a blur action from mouseDown or touchEnd.
1823
+ * @param {Function} handleBlur The function that is called if mouseDown or touchEnd occured outside the downshiftElements.
1824
+ * @returns {Object} The mouse and touch events information, if any of are happening.
1827
1825
  */
1828
- function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, handleBlur) {
1826
+ function useMouseAndTouchTracker(environment, downshiftElementRefs, handleBlur) {
1829
1827
  var mouseAndTouchTrackersRef = useRef({
1830
1828
  isMouseDown: false,
1831
1829
  isTouchMove: false,
@@ -1833,45 +1831,39 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
1833
1831
  });
1834
1832
  useEffect(function () {
1835
1833
  if (!environment) {
1836
- return;
1834
+ return noop;
1837
1835
  }
1838
-
1839
- // The same strategy for checking if a click occurred inside or outside downshift
1840
- // as in downshift.js.
1841
- var onMouseDown = function onMouseDown() {
1836
+ var downshiftElements = downshiftElementRefs.map(function (ref) {
1837
+ return ref.current;
1838
+ });
1839
+ function onMouseDown() {
1842
1840
  mouseAndTouchTrackersRef.current.isTouchEnd = false; // reset this one.
1843
1841
  mouseAndTouchTrackersRef.current.isMouseDown = true;
1844
- };
1845
- var onMouseUp = function onMouseUp(event) {
1842
+ }
1843
+ function onMouseUp(event) {
1846
1844
  mouseAndTouchTrackersRef.current.isMouseDown = false;
1847
- if (isOpen && !targetWithinDownshift(event.target, downshiftElementRefs.map(function (ref) {
1848
- return ref.current;
1849
- }), environment)) {
1845
+ if (!targetWithinDownshift(event.target, downshiftElements, environment)) {
1850
1846
  handleBlur();
1851
1847
  }
1852
- };
1853
- var onTouchStart = function onTouchStart() {
1848
+ }
1849
+ function onTouchStart() {
1854
1850
  mouseAndTouchTrackersRef.current.isTouchEnd = false;
1855
1851
  mouseAndTouchTrackersRef.current.isTouchMove = false;
1856
- };
1857
- var onTouchMove = function onTouchMove() {
1852
+ }
1853
+ function onTouchMove() {
1858
1854
  mouseAndTouchTrackersRef.current.isTouchMove = true;
1859
- };
1860
- var onTouchEnd = function onTouchEnd(event) {
1855
+ }
1856
+ function onTouchEnd(event) {
1861
1857
  mouseAndTouchTrackersRef.current.isTouchEnd = true;
1862
- if (isOpen && !mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, downshiftElementRefs.map(function (ref) {
1863
- return ref.current;
1864
- }), environment, false)) {
1858
+ if (!mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, downshiftElements, environment, false)) {
1865
1859
  handleBlur();
1866
1860
  }
1867
- };
1861
+ }
1868
1862
  environment.addEventListener('mousedown', onMouseDown);
1869
1863
  environment.addEventListener('mouseup', onMouseUp);
1870
1864
  environment.addEventListener('touchstart', onTouchStart);
1871
1865
  environment.addEventListener('touchmove', onTouchMove);
1872
1866
  environment.addEventListener('touchend', onTouchEnd);
1873
-
1874
- // eslint-disable-next-line consistent-return
1875
1867
  return function cleanup() {
1876
1868
  environment.removeEventListener('mousedown', onMouseDown);
1877
1869
  environment.removeEventListener('mouseup', onMouseUp);
@@ -1879,9 +1871,9 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
1879
1871
  environment.removeEventListener('touchmove', onTouchMove);
1880
1872
  environment.removeEventListener('touchend', onTouchEnd);
1881
1873
  };
1882
- // eslint-disable-next-line react-hooks/exhaustive-deps
1883
- }, [isOpen, environment]);
1884
- return mouseAndTouchTrackersRef;
1874
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- refs don't change
1875
+ }, [environment, handleBlur]);
1876
+ return mouseAndTouchTrackersRef.current;
1885
1877
  }
1886
1878
 
1887
1879
  /* istanbul ignore next */
@@ -2474,12 +2466,13 @@ function useSelect(userProps) {
2474
2466
  }
2475
2467
  // eslint-disable-next-line react-hooks/exhaustive-deps
2476
2468
  }, []);
2477
- // Add mouse/touch events to document.
2478
- var mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [menuRef, toggleButtonRef], environment, function () {
2479
- dispatch({
2480
- type: ToggleButtonBlur
2481
- });
2482
- });
2469
+ var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, [toggleButtonRef, menuRef], useCallback(function handleBlur() {
2470
+ if (latest.current.state.isOpen) {
2471
+ dispatch({
2472
+ type: ToggleButtonBlur
2473
+ });
2474
+ }
2475
+ }, [dispatch, latest]));
2483
2476
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
2484
2477
  // Reset itemRefs on close.
2485
2478
  useEffect(function () {
@@ -2665,7 +2658,7 @@ function useSelect(userProps) {
2665
2658
  });
2666
2659
  };
2667
2660
  var toggleButtonHandleBlur = function toggleButtonHandleBlur() {
2668
- if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
2661
+ if (latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
2669
2662
  dispatch({
2670
2663
  type: ToggleButtonBlur
2671
2664
  });
@@ -2694,7 +2687,7 @@ function useSelect(userProps) {
2694
2687
  }
2695
2688
  setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
2696
2689
  return toggleProps;
2697
- }, [latest, elementIds, setGetterPropCallInfo, dispatch, mouseAndTouchTrackersRef, toggleButtonKeyDownHandlers]);
2690
+ }, [dispatch, elementIds, latest, mouseAndTouchTrackers, setGetterPropCallInfo, toggleButtonKeyDownHandlers]);
2698
2691
  var getItemProps = useCallback(function (_temp6) {
2699
2692
  var _extends4;
2700
2693
  var _ref6 = _temp6 === void 0 ? {} : _temp6,
@@ -2720,7 +2713,7 @@ function useSelect(userProps) {
2720
2713
  index = _getItemAndIndex[1];
2721
2714
  var disabled = latestProps.isItemDisabled(item, index);
2722
2715
  var itemHandleMouseMove = function itemHandleMouseMove() {
2723
- if (mouseAndTouchTrackersRef.current.isTouchEnd || index === latestState.highlightedIndex) {
2716
+ if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
2724
2717
  return;
2725
2718
  }
2726
2719
  shouldScrollRef.current = false;
@@ -2754,7 +2747,7 @@ function useSelect(userProps) {
2754
2747
  itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
2755
2748
  itemProps.onMouseDown = callAllEventHandlers(onMouseDown, itemHandleMouseDown);
2756
2749
  return itemProps;
2757
- }, [latest, elementIds, mouseAndTouchTrackersRef, shouldScrollRef, dispatch]);
2750
+ }, [latest, elementIds, mouseAndTouchTrackers, shouldScrollRef, dispatch]);
2758
2751
  return {
2759
2752
  // prop getters.
2760
2753
  getToggleButtonProps: getToggleButtonProps,
@@ -3115,13 +3108,14 @@ function useCombobox(userProps) {
3115
3108
  previousResultCountRef.current = items.length;
3116
3109
  }
3117
3110
  });
3118
- // Add mouse/touch events to document.
3119
- var mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [inputRef, menuRef, toggleButtonRef], environment, function () {
3120
- dispatch({
3121
- type: InputBlur,
3122
- selectItem: false
3123
- });
3124
- });
3111
+ var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, [toggleButtonRef, menuRef, inputRef], useCallback(function handleBlur() {
3112
+ if (latest.current.state.isOpen) {
3113
+ dispatch({
3114
+ type: InputBlur,
3115
+ selectItem: false
3116
+ });
3117
+ }
3118
+ }, [dispatch, latest]));
3125
3119
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
3126
3120
  // Reset itemRefs on close.
3127
3121
  useEffect(function () {
@@ -3269,7 +3263,7 @@ function useCombobox(userProps) {
3269
3263
  var onSelectKey = 'onClick';
3270
3264
  var customClickHandler = onClick;
3271
3265
  var itemHandleMouseMove = function itemHandleMouseMove() {
3272
- if (mouseAndTouchTrackersRef.current.isTouchEnd || index === latestState.highlightedIndex) {
3266
+ if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
3273
3267
  return;
3274
3268
  }
3275
3269
  shouldScrollRef.current = false;
@@ -3297,7 +3291,7 @@ function useCombobox(userProps) {
3297
3291
  onMouseMove: callAllEventHandlers(onMouseMove, itemHandleMouseMove),
3298
3292
  onMouseDown: callAllEventHandlers(onMouseDown, itemHandleMouseDown)
3299
3293
  }, rest);
3300
- }, [dispatch, elementIds, latest, mouseAndTouchTrackersRef, shouldScrollRef]);
3294
+ }, [dispatch, elementIds, latest, mouseAndTouchTrackers, shouldScrollRef]);
3301
3295
  var getToggleButtonProps = useCallback(function (_temp4) {
3302
3296
  var _extends4;
3303
3297
  var _ref5 = _temp4 === void 0 ? {} : _temp4,
@@ -3351,7 +3345,7 @@ function useCombobox(userProps) {
3351
3345
  };
3352
3346
  var inputHandleBlur = function inputHandleBlur(event) {
3353
3347
  /* istanbul ignore else */
3354
- if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
3348
+ if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
3355
3349
  var isBlurByTabChange = event.relatedTarget === null && environment.document.activeElement !== environment.document.body;
3356
3350
  dispatch({
3357
3351
  type: InputBlur,
@@ -3375,7 +3369,7 @@ function useCombobox(userProps) {
3375
3369
  return _extends((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
3376
3370
  inputRef.current = inputNode;
3377
3371
  }), _extends5['aria-activedescendant'] = latestState.isOpen && latestState.highlightedIndex > -1 ? elementIds.getItemId(latestState.highlightedIndex) : '', _extends5['aria-autocomplete'] = 'list', _extends5['aria-controls'] = elementIds.menuId, _extends5['aria-expanded'] = latestState.isOpen, _extends5['aria-labelledby'] = rest && rest['aria-label'] ? undefined : elementIds.labelId, _extends5.autoComplete = 'off', _extends5.id = elementIds.inputId, _extends5.role = 'combobox', _extends5.value = latestState.inputValue, _extends5), eventHandlers, rest);
3378
- }, [setGetterPropCallInfo, latest, elementIds, inputKeyDownHandlers, dispatch, mouseAndTouchTrackersRef, environment]);
3372
+ }, [dispatch, elementIds, environment, inputKeyDownHandlers, latest, mouseAndTouchTrackers, setGetterPropCallInfo]);
3379
3373
 
3380
3374
  // returns
3381
3375
  var toggleMenu = useCallback(function () {
@@ -1724,17 +1724,15 @@ function getHighlightedIndexOnOpen(props, state, offset) {
1724
1724
  }
1725
1725
  return offset < 0 ? items.length - 1 : 0;
1726
1726
  }
1727
-
1728
1727
  /**
1729
- * Reuse the movement tracking of mouse and touch events.
1728
+ * Tracks mouse and touch events, such as mouseDown, touchMove and touchEnd.
1730
1729
  *
1731
- * @param {boolean} isOpen Whether the dropdown is open or not.
1732
- * @param {Array<Object>} downshiftElementRefs Downshift element refs to track movement (toggleButton, menu etc.)
1733
- * @param {Object} environment Environment where component/hook exists.
1734
- * @param {Function} handleBlur Handler on blur from mouse or touch.
1735
- * @returns {Object} Ref containing whether mouseDown or touchMove event is happening
1730
+ * @param {Object} environment The environment to add the event listeners to, for instance window.
1731
+ * @param {Array<HTMLElement>} downshiftElementRefs The refs for the element that should not trigger a blur action from mouseDown or touchEnd.
1732
+ * @param {Function} handleBlur The function that is called if mouseDown or touchEnd occured outside the downshiftElements.
1733
+ * @returns {Object} The mouse and touch events information, if any of are happening.
1736
1734
  */
1737
- function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, handleBlur) {
1735
+ function useMouseAndTouchTracker(environment, downshiftElementRefs, handleBlur) {
1738
1736
  var mouseAndTouchTrackersRef = React.useRef({
1739
1737
  isMouseDown: false,
1740
1738
  isTouchMove: false,
@@ -1742,11 +1740,11 @@ function useMouseAndTouchTracker(isOpen, downshiftElementRefs, environment, hand
1742
1740
  });
1743
1741
  React.useEffect(function () {
1744
1742
  {
1745
- return;
1743
+ return noop;
1746
1744
  }
1747
- // eslint-disable-next-line react-hooks/exhaustive-deps
1748
- }, [isOpen, environment]);
1749
- return mouseAndTouchTrackersRef;
1745
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- refs don't change
1746
+ }, [environment, handleBlur]);
1747
+ return mouseAndTouchTrackersRef.current;
1750
1748
  }
1751
1749
 
1752
1750
  /* istanbul ignore next */
@@ -2339,8 +2337,13 @@ function useSelect(userProps) {
2339
2337
  }
2340
2338
  // eslint-disable-next-line react-hooks/exhaustive-deps
2341
2339
  }, []);
2342
- // Add mouse/touch events to document.
2343
- var mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [menuRef, toggleButtonRef], environment);
2340
+ var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, [toggleButtonRef, menuRef], React.useCallback(function handleBlur() {
2341
+ if (latest.current.state.isOpen) {
2342
+ dispatch({
2343
+ type: ToggleButtonBlur
2344
+ });
2345
+ }
2346
+ }, [dispatch, latest]));
2344
2347
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
2345
2348
  // Reset itemRefs on close.
2346
2349
  React.useEffect(function () {
@@ -2526,7 +2529,7 @@ function useSelect(userProps) {
2526
2529
  });
2527
2530
  };
2528
2531
  var toggleButtonHandleBlur = function toggleButtonHandleBlur() {
2529
- if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
2532
+ if (latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
2530
2533
  dispatch({
2531
2534
  type: ToggleButtonBlur
2532
2535
  });
@@ -2543,7 +2546,7 @@ function useSelect(userProps) {
2543
2546
  }
2544
2547
  setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
2545
2548
  return toggleProps;
2546
- }, [latest, elementIds, setGetterPropCallInfo, dispatch, mouseAndTouchTrackersRef, toggleButtonKeyDownHandlers]);
2549
+ }, [dispatch, elementIds, latest, mouseAndTouchTrackers, setGetterPropCallInfo, toggleButtonKeyDownHandlers]);
2547
2550
  var getItemProps = React.useCallback(function (_temp6) {
2548
2551
  var _extends4;
2549
2552
  var _ref6 = _temp6 === void 0 ? {} : _temp6,
@@ -2569,7 +2572,7 @@ function useSelect(userProps) {
2569
2572
  index = _getItemAndIndex[1];
2570
2573
  var disabled = latestProps.isItemDisabled(item, index);
2571
2574
  var itemHandleMouseMove = function itemHandleMouseMove() {
2572
- if (mouseAndTouchTrackersRef.current.isTouchEnd || index === latestState.highlightedIndex) {
2575
+ if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
2573
2576
  return;
2574
2577
  }
2575
2578
  shouldScrollRef.current = false;
@@ -2603,7 +2606,7 @@ function useSelect(userProps) {
2603
2606
  itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
2604
2607
  itemProps.onMouseDown = callAllEventHandlers(onMouseDown, itemHandleMouseDown);
2605
2608
  return itemProps;
2606
- }, [latest, elementIds, mouseAndTouchTrackersRef, shouldScrollRef, dispatch]);
2609
+ }, [latest, elementIds, mouseAndTouchTrackers, shouldScrollRef, dispatch]);
2607
2610
  return {
2608
2611
  // prop getters.
2609
2612
  getToggleButtonProps: getToggleButtonProps,
@@ -2964,8 +2967,14 @@ function useCombobox(userProps) {
2964
2967
  previousResultCountRef.current = items.length;
2965
2968
  }
2966
2969
  });
2967
- // Add mouse/touch events to document.
2968
- var mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [inputRef, menuRef, toggleButtonRef], environment);
2970
+ var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, [toggleButtonRef, menuRef, inputRef], React.useCallback(function handleBlur() {
2971
+ if (latest.current.state.isOpen) {
2972
+ dispatch({
2973
+ type: InputBlur,
2974
+ selectItem: false
2975
+ });
2976
+ }
2977
+ }, [dispatch, latest]));
2969
2978
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
2970
2979
  // Reset itemRefs on close.
2971
2980
  React.useEffect(function () {
@@ -3113,7 +3122,7 @@ function useCombobox(userProps) {
3113
3122
  var onSelectKey = /* istanbul ignore next (react-native) */'onPress' ;
3114
3123
  var customClickHandler = /* istanbul ignore next (react-native) */onPress ;
3115
3124
  var itemHandleMouseMove = function itemHandleMouseMove() {
3116
- if (mouseAndTouchTrackersRef.current.isTouchEnd || index === latestState.highlightedIndex) {
3125
+ if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
3117
3126
  return;
3118
3127
  }
3119
3128
  shouldScrollRef.current = false;
@@ -3141,7 +3150,7 @@ function useCombobox(userProps) {
3141
3150
  onMouseMove: callAllEventHandlers(onMouseMove, itemHandleMouseMove),
3142
3151
  onMouseDown: callAllEventHandlers(onMouseDown, itemHandleMouseDown)
3143
3152
  }, rest);
3144
- }, [dispatch, elementIds, latest, mouseAndTouchTrackersRef, shouldScrollRef]);
3153
+ }, [dispatch, elementIds, latest, mouseAndTouchTrackers, shouldScrollRef]);
3145
3154
  var getToggleButtonProps = React.useCallback(function (_temp4) {
3146
3155
  var _extends4;
3147
3156
  var _ref5 = _temp4 === void 0 ? {} : _temp4;
@@ -3195,7 +3204,7 @@ function useCombobox(userProps) {
3195
3204
  };
3196
3205
  var inputHandleBlur = function inputHandleBlur(event) {
3197
3206
  /* istanbul ignore else */
3198
- if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
3207
+ if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
3199
3208
  var isBlurByTabChange = event.relatedTarget === null && environment.document.activeElement !== environment.document.body;
3200
3209
  dispatch({
3201
3210
  type: InputBlur,
@@ -3231,7 +3240,7 @@ function useCombobox(userProps) {
3231
3240
  return _extends__default["default"]((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
3232
3241
  inputRef.current = inputNode;
3233
3242
  }), _extends5['aria-activedescendant'] = latestState.isOpen && latestState.highlightedIndex > -1 ? elementIds.getItemId(latestState.highlightedIndex) : '', _extends5['aria-autocomplete'] = 'list', _extends5['aria-controls'] = elementIds.menuId, _extends5['aria-expanded'] = latestState.isOpen, _extends5['aria-labelledby'] = rest && rest['aria-label'] ? undefined : elementIds.labelId, _extends5.autoComplete = 'off', _extends5.id = elementIds.inputId, _extends5.role = 'combobox', _extends5.value = latestState.inputValue, _extends5), eventHandlers, rest);
3234
- }, [setGetterPropCallInfo, latest, elementIds, inputKeyDownHandlers, dispatch, mouseAndTouchTrackersRef, environment]);
3243
+ }, [dispatch, elementIds, environment, inputKeyDownHandlers, latest, mouseAndTouchTrackers, setGetterPropCallInfo]);
3235
3244
 
3236
3245
  // returns
3237
3246
  var toggleMenu = React.useCallback(function () {