downshift 8.2.3 → 8.2.4-alpha.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.
@@ -58,9 +58,10 @@ export namespace defaultProps {
58
58
  * @param {Function} reducer Reducer function from downshift.
59
59
  * @param {Object} props The hook props, also passed to createInitialState.
60
60
  * @param {Function} createInitialState Function that returns the initial state.
61
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
61
62
  * @returns {Array} An array with the state and an action dispatcher.
62
63
  */
63
- export function useControlledReducer(reducer: Function, props: Object, createInitialState: Function): any[];
64
+ export function useControlledReducer(reducer: Function, props: Object, createInitialState: Function, isStateEqual: Function): any[];
64
65
  /**
65
66
  * Computes the controlled state using a the previous state, props,
66
67
  * two reducers, one from downshift and an optional one from the user.
@@ -69,9 +70,10 @@ export function useControlledReducer(reducer: Function, props: Object, createIni
69
70
  * @param {Function} reducer Reducer function from downshift.
70
71
  * @param {Object} props The hook props, also passed to createInitialState.
71
72
  * @param {Function} createInitialState Function that returns the initial state.
73
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
72
74
  * @returns {Array} An array with the state and an action dispatcher.
73
75
  */
74
- export function useEnhancedReducer(reducer: Function, props: Object, createInitialState: Function): any[];
76
+ export function useEnhancedReducer(reducer: Function, props: Object, createInitialState: Function, isStateEqual: Function): any[];
75
77
  export function useLatestRef(val: any): React.MutableRefObject<any>;
76
78
  export function capitalizeString(string: any): string;
77
79
  export function isAcceptedCharacterKey(key: any): boolean;
@@ -112,6 +114,15 @@ export const useElementIds: (({ id, labelId, menuId, getItemId, toggleButtonId,
112
114
  * @returns The changes for the state.
113
115
  */
114
116
  export function getChangesOnSelection(props: Object, highlightedIndex: number, inputValue?: boolean): any;
117
+ /**
118
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
119
+ * Used by useSelect and useCombobox.
120
+ *
121
+ * @param {Object} prevState
122
+ * @param {Object} newState
123
+ * @returns {boolean} Wheather the states are deeply equal.
124
+ */
125
+ export function isDropdownsStateEqual(prevState: Object, newState: Object): boolean;
115
126
  export namespace commonDropdownPropTypes {
116
127
  export const getA11yStatusMessage: PropTypes.Requireable<(...args: any[]) => any>;
117
128
  export const highlightedIndex: PropTypes.Requireable<number>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "downshift",
3
- "version": "8.2.3",
3
+ "version": "8.2.4-alpha.1",
4
4
  "description": "🏎 A set of primitives to build simple, flexible, WAI-ARIA compliant React autocomplete, combobox or select dropdown components.",
5
5
  "main": "dist/downshift.cjs.js",
6
6
  "react-native": "dist/downshift.native.cjs.js",
@@ -1658,9 +1658,10 @@ function useLatestRef(val) {
1658
1658
  * @param {Function} reducer Reducer function from downshift.
1659
1659
  * @param {Object} props The hook props, also passed to createInitialState.
1660
1660
  * @param {Function} createInitialState Function that returns the initial state.
1661
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1661
1662
  * @returns {Array} An array with the state and an action dispatcher.
1662
1663
  */
1663
- function useEnhancedReducer(reducer, props, createInitialState) {
1664
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1664
1665
  var prevStateRef = React.useRef();
1665
1666
  var actionRef = React.useRef();
1666
1667
  var enhancedReducer = React.useCallback(function (state, action) {
@@ -1683,11 +1684,12 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1683
1684
  }, [propsRef]);
1684
1685
  var action = actionRef.current;
1685
1686
  React.useEffect(function () {
1686
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1687
+ var stateChanged = prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1688
+ if (action && stateChanged) {
1687
1689
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1688
1690
  }
1689
1691
  prevStateRef.current = state;
1690
- }, [state, props, action]);
1692
+ }, [state, props, action, isStateEqual]);
1691
1693
  return [state, dispatchWithProps];
1692
1694
  }
1693
1695
 
@@ -1698,10 +1700,11 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1698
1700
  * @param {Function} reducer Reducer function from downshift.
1699
1701
  * @param {Object} props The hook props, also passed to createInitialState.
1700
1702
  * @param {Function} createInitialState Function that returns the initial state.
1703
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1701
1704
  * @returns {Array} An array with the state and an action dispatcher.
1702
1705
  */
1703
- function useControlledReducer$1(reducer, props, createInitialState) {
1704
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1706
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1707
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1705
1708
  state = _useEnhancedReducer[0],
1706
1709
  dispatch = _useEnhancedReducer[1];
1707
1710
  return [getState(state, props), dispatch];
@@ -1983,6 +1986,18 @@ function getChangesOnSelection(props, highlightedIndex, inputValue) {
1983
1986
  }));
1984
1987
  }
1985
1988
 
1989
+ /**
1990
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
1991
+ * Used by useSelect and useCombobox.
1992
+ *
1993
+ * @param {Object} prevState
1994
+ * @param {Object} newState
1995
+ * @returns {boolean} Wheather the states are deeply equal.
1996
+ */
1997
+ function isDropdownsStateEqual(prevState, newState) {
1998
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
1999
+ }
2000
+
1986
2001
  // Shared between all exports.
1987
2002
  var commonPropTypes = {
1988
2003
  environment: PropTypes__default["default"].shape({
@@ -2305,14 +2320,13 @@ function useSelect(userProps) {
2305
2320
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2306
2321
  getA11yStatusMessage = props.getA11yStatusMessage;
2307
2322
  // Initial state depending on controlled props.
2308
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2323
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2309
2324
  state = _useControlledReducer[0],
2310
2325
  dispatch = _useControlledReducer[1];
2311
2326
  var isOpen = state.isOpen,
2312
2327
  highlightedIndex = state.highlightedIndex,
2313
2328
  selectedItem = state.selectedItem,
2314
2329
  inputValue = state.inputValue;
2315
-
2316
2330
  // Element efs.
2317
2331
  var toggleButtonRef = React.useRef(null);
2318
2332
  var menuRef = React.useRef(null);
@@ -2790,11 +2804,12 @@ var propTypes$1 = _extends__default["default"]({}, commonDropdownPropTypes, {
2790
2804
  * @param {Function} reducer Reducer function from downshift.
2791
2805
  * @param {Object} props The hook props, also passed to createInitialState.
2792
2806
  * @param {Function} createInitialState Function that returns the initial state.
2807
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
2793
2808
  * @returns {Array} An array with the state and an action dispatcher.
2794
2809
  */
2795
- function useControlledReducer(reducer, props, createInitialState) {
2810
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
2796
2811
  var previousSelectedItemRef = React.useRef();
2797
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
2812
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
2798
2813
  state = _useEnhancedReducer[0],
2799
2814
  dispatch = _useEnhancedReducer[1];
2800
2815
 
@@ -2968,7 +2983,7 @@ function useCombobox(userProps) {
2968
2983
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2969
2984
  itemToString = props.itemToString;
2970
2985
  // Initial state depending on controlled props.
2971
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
2986
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
2972
2987
  state = _useControlledReducer[0],
2973
2988
  dispatch = _useControlledReducer[1];
2974
2989
  var isOpen = state.isOpen,
@@ -3453,6 +3468,18 @@ function getA11yRemovalMessage(selectionParameters) {
3453
3468
  itemToStringLocal = selectionParameters.itemToString;
3454
3469
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3455
3470
  }
3471
+
3472
+ /**
3473
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3474
+ * Used by useSelect and useCombobox.
3475
+ *
3476
+ * @param {Object} prevState
3477
+ * @param {Object} newState
3478
+ * @returns {boolean} Wheather the states are deeply equal.
3479
+ */
3480
+ function isStateEqual(prevState, newState) {
3481
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3482
+ }
3456
3483
  var propTypes = _extends__default["default"]({}, commonPropTypes, {
3457
3484
  selectedItems: PropTypes__default["default"].array,
3458
3485
  initialSelectedItems: PropTypes__default["default"].array,
@@ -3642,7 +3669,7 @@ function useMultipleSelection(userProps) {
3642
3669
  keyNavigationPrevious = props.keyNavigationPrevious;
3643
3670
 
3644
3671
  // Reducer init.
3645
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3672
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3646
3673
  state = _useControlledReducer[0],
3647
3674
  dispatch = _useControlledReducer[1];
3648
3675
  var activeIndex = state.activeIndex,
@@ -1645,9 +1645,10 @@ function useLatestRef(val) {
1645
1645
  * @param {Function} reducer Reducer function from downshift.
1646
1646
  * @param {Object} props The hook props, also passed to createInitialState.
1647
1647
  * @param {Function} createInitialState Function that returns the initial state.
1648
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1648
1649
  * @returns {Array} An array with the state and an action dispatcher.
1649
1650
  */
1650
- function useEnhancedReducer(reducer, props, createInitialState) {
1651
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1651
1652
  var prevStateRef = useRef();
1652
1653
  var actionRef = useRef();
1653
1654
  var enhancedReducer = useCallback(function (state, action) {
@@ -1670,11 +1671,12 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1670
1671
  }, [propsRef]);
1671
1672
  var action = actionRef.current;
1672
1673
  useEffect(function () {
1673
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1674
+ var stateChanged = prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1675
+ if (action && stateChanged) {
1674
1676
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1675
1677
  }
1676
1678
  prevStateRef.current = state;
1677
- }, [state, props, action]);
1679
+ }, [state, props, action, isStateEqual]);
1678
1680
  return [state, dispatchWithProps];
1679
1681
  }
1680
1682
 
@@ -1685,10 +1687,11 @@ function useEnhancedReducer(reducer, props, createInitialState) {
1685
1687
  * @param {Function} reducer Reducer function from downshift.
1686
1688
  * @param {Object} props The hook props, also passed to createInitialState.
1687
1689
  * @param {Function} createInitialState Function that returns the initial state.
1690
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1688
1691
  * @returns {Array} An array with the state and an action dispatcher.
1689
1692
  */
1690
- function useControlledReducer$1(reducer, props, createInitialState) {
1691
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1693
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1694
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1692
1695
  state = _useEnhancedReducer[0],
1693
1696
  dispatch = _useEnhancedReducer[1];
1694
1697
  return [getState(state, props), dispatch];
@@ -1970,6 +1973,18 @@ function getChangesOnSelection(props, highlightedIndex, inputValue) {
1970
1973
  }));
1971
1974
  }
1972
1975
 
1976
+ /**
1977
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
1978
+ * Used by useSelect and useCombobox.
1979
+ *
1980
+ * @param {Object} prevState
1981
+ * @param {Object} newState
1982
+ * @returns {boolean} Wheather the states are deeply equal.
1983
+ */
1984
+ function isDropdownsStateEqual(prevState, newState) {
1985
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
1986
+ }
1987
+
1973
1988
  // Shared between all exports.
1974
1989
  var commonPropTypes = {
1975
1990
  environment: PropTypes.shape({
@@ -2292,14 +2307,13 @@ function useSelect(userProps) {
2292
2307
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2293
2308
  getA11yStatusMessage = props.getA11yStatusMessage;
2294
2309
  // Initial state depending on controlled props.
2295
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2310
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2296
2311
  state = _useControlledReducer[0],
2297
2312
  dispatch = _useControlledReducer[1];
2298
2313
  var isOpen = state.isOpen,
2299
2314
  highlightedIndex = state.highlightedIndex,
2300
2315
  selectedItem = state.selectedItem,
2301
2316
  inputValue = state.inputValue;
2302
-
2303
2317
  // Element efs.
2304
2318
  var toggleButtonRef = useRef(null);
2305
2319
  var menuRef = useRef(null);
@@ -2777,11 +2791,12 @@ var propTypes$1 = _extends({}, commonDropdownPropTypes, {
2777
2791
  * @param {Function} reducer Reducer function from downshift.
2778
2792
  * @param {Object} props The hook props, also passed to createInitialState.
2779
2793
  * @param {Function} createInitialState Function that returns the initial state.
2794
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
2780
2795
  * @returns {Array} An array with the state and an action dispatcher.
2781
2796
  */
2782
- function useControlledReducer(reducer, props, createInitialState) {
2797
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
2783
2798
  var previousSelectedItemRef = useRef();
2784
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
2799
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
2785
2800
  state = _useEnhancedReducer[0],
2786
2801
  dispatch = _useEnhancedReducer[1];
2787
2802
 
@@ -2955,7 +2970,7 @@ function useCombobox(userProps) {
2955
2970
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2956
2971
  itemToString = props.itemToString;
2957
2972
  // Initial state depending on controlled props.
2958
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
2973
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
2959
2974
  state = _useControlledReducer[0],
2960
2975
  dispatch = _useControlledReducer[1];
2961
2976
  var isOpen = state.isOpen,
@@ -3440,6 +3455,18 @@ function getA11yRemovalMessage(selectionParameters) {
3440
3455
  itemToStringLocal = selectionParameters.itemToString;
3441
3456
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3442
3457
  }
3458
+
3459
+ /**
3460
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3461
+ * Used by useSelect and useCombobox.
3462
+ *
3463
+ * @param {Object} prevState
3464
+ * @param {Object} newState
3465
+ * @returns {boolean} Wheather the states are deeply equal.
3466
+ */
3467
+ function isStateEqual(prevState, newState) {
3468
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3469
+ }
3443
3470
  var propTypes = _extends({}, commonPropTypes, {
3444
3471
  selectedItems: PropTypes.array,
3445
3472
  initialSelectedItems: PropTypes.array,
@@ -3629,7 +3656,7 @@ function useMultipleSelection(userProps) {
3629
3656
  keyNavigationPrevious = props.keyNavigationPrevious;
3630
3657
 
3631
3658
  // Reducer init.
3632
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3659
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3633
3660
  state = _useControlledReducer[0],
3634
3661
  dispatch = _useControlledReducer[1];
3635
3662
  var activeIndex = state.activeIndex,
@@ -295,7 +295,7 @@
295
295
 
296
296
  var reactIsExports = reactIs.exports;
297
297
 
298
- const t=t=>"object"==typeof t&&null!=t&&1===t.nodeType,e=(t,e)=>(!e||"hidden"!==t)&&("visible"!==t&&"clip"!==t),n=(t,n)=>{if(t.clientHeight<t.scrollHeight||t.clientWidth<t.scrollWidth){const o=getComputedStyle(t,null);return e(o.overflowY,n)||e(o.overflowX,n)||(t=>{const e=(t=>{if(!t.ownerDocument||!t.ownerDocument.defaultView)return null;try{return t.ownerDocument.defaultView.frameElement}catch(t){return null}})(t);return !!e&&(e.clientHeight<t.scrollHeight||e.clientWidth<t.scrollWidth)})(t)}return !1},o=(t,e,n,o,l,r,i,s)=>r<t&&i>e||r>t&&i<e?0:r<=t&&s<=n||i>=e&&s>=n?r-t-o:i>e&&s<n||r<t&&s>n?i-e+l:0,l=t=>{const e=t.parentElement;return null==e?t.getRootNode().host||null:e},r=(e,r)=>{var i,s,d,h;if("undefined"==typeof document)return [];const{scrollMode:c,block:f,inline:u,boundary:a,skipOverflowHiddenElements:g}=r,p="function"==typeof a?a:t=>t!==a;if(!t(e))throw new TypeError("Invalid target");const m=document.scrollingElement||document.documentElement,w=[];let W=e;for(;t(W)&&p(W);){if(W=l(W),W===m){w.push(W);break}null!=W&&W===document.body&&n(W)&&!n(document.documentElement)||null!=W&&n(W,g)&&w.push(W);}const b=null!=(s=null==(i=window.visualViewport)?void 0:i.width)?s:innerWidth,H=null!=(h=null==(d=window.visualViewport)?void 0:d.height)?h:innerHeight,{scrollX:y,scrollY:M}=window,{height:v,width:E,top:x,right:C,bottom:I,left:R}=e.getBoundingClientRect(),{top:T,right:B,bottom:F,left:V}=(t=>{const e=window.getComputedStyle(t);return {top:parseFloat(e.scrollMarginTop)||0,right:parseFloat(e.scrollMarginRight)||0,bottom:parseFloat(e.scrollMarginBottom)||0,left:parseFloat(e.scrollMarginLeft)||0}})(e);let k="start"===f||"nearest"===f?x-T:"end"===f?I+F:x+v/2-T+F,D="center"===u?R+E/2-V+B:"end"===u?C+B:R-V;const L=[];for(let t=0;t<w.length;t++){const e=w[t],{height:n,width:l,top:r,right:i,bottom:s,left:d}=e.getBoundingClientRect();if("if-needed"===c&&x>=0&&R>=0&&I<=H&&C<=b&&x>=r&&I<=s&&R>=d&&C<=i)return L;const h=getComputedStyle(e),a=parseInt(h.borderLeftWidth,10),g=parseInt(h.borderTopWidth,10),p=parseInt(h.borderRightWidth,10),W=parseInt(h.borderBottomWidth,10);let T=0,B=0;const F="offsetWidth"in e?e.offsetWidth-e.clientWidth-a-p:0,V="offsetHeight"in e?e.offsetHeight-e.clientHeight-g-W:0,S="offsetWidth"in e?0===e.offsetWidth?0:l/e.offsetWidth:0,X="offsetHeight"in e?0===e.offsetHeight?0:n/e.offsetHeight:0;if(m===e)T="start"===f?k:"end"===f?k-H:"nearest"===f?o(M,M+H,H,g,W,M+k,M+k+v,v):k-H/2,B="start"===u?D:"center"===u?D-b/2:"end"===u?D-b:o(y,y+b,b,a,p,y+D,y+D+E,E),T=Math.max(0,T+M),B=Math.max(0,B+y);else {T="start"===f?k-r-g:"end"===f?k-s+W+V:"nearest"===f?o(r,s,n,g,W+V,k,k+v,v):k-(r+n/2)+V/2,B="start"===u?D-d-a:"center"===u?D-(d+l/2)+F/2:"end"===u?D-i+p+F:o(d,i,l,a,p+F,D,D+E,E);const{scrollLeft:t,scrollTop:h}=e;T=0===X?0:Math.max(0,Math.min(h+T/X,e.scrollHeight-n/X+V)),B=0===S?0:Math.max(0,Math.min(t+B/S,e.scrollWidth-l/S+F)),k+=h-T,D+=t-B;}L.push({el:e,top:T,left:B});}return L};
298
+ const t=t=>"object"==typeof t&&null!=t&&1===t.nodeType,e=(t,e)=>(!e||"hidden"!==t)&&("visible"!==t&&"clip"!==t),n=(t,n)=>{if(t.clientHeight<t.scrollHeight||t.clientWidth<t.scrollWidth){const o=getComputedStyle(t,null);return e(o.overflowY,n)||e(o.overflowX,n)||(t=>{const e=(t=>{if(!t.ownerDocument||!t.ownerDocument.defaultView)return null;try{return t.ownerDocument.defaultView.frameElement}catch(t){return null}})(t);return !!e&&(e.clientHeight<t.scrollHeight||e.clientWidth<t.scrollWidth)})(t)}return !1},o=(t,e,n,o,i,l,r,d)=>l<t&&r>e||l>t&&r<e?0:l<=t&&d<=n||r>=e&&d>=n?l-t-o:r>e&&d<n||l<t&&d>n?r-e+i:0,i=t=>{const e=t.parentElement;return null==e?t.getRootNode().host||null:e},l=(e,l)=>{var r,d,s,h;if("undefined"==typeof document)return [];const{scrollMode:c,block:f,inline:u,boundary:a,skipOverflowHiddenElements:g}=l,m="function"==typeof a?a:t=>t!==a;if(!t(e))throw new TypeError("Invalid target");const p=document.scrollingElement||document.documentElement,w=[];let W=e;for(;t(W)&&m(W);){if(W=i(W),W===p){w.push(W);break}null!=W&&W===document.body&&n(W)&&!n(document.documentElement)||null!=W&&n(W,g)&&w.push(W);}const H=null!=(d=null==(r=window.visualViewport)?void 0:r.width)?d:innerWidth,b=null!=(h=null==(s=window.visualViewport)?void 0:s.height)?h:innerHeight,{scrollX:v,scrollY:y}=window,{height:E,width:M,top:x,right:I,bottom:C,left:R}=e.getBoundingClientRect();let T="start"===f||"nearest"===f?x:"end"===f?C:x+E/2,V="center"===u?R+M/2:"end"===u?I:R;const k=[];for(let t=0;t<w.length;t++){const e=w[t],{height:n,width:i,top:l,right:r,bottom:d,left:s}=e.getBoundingClientRect();if("if-needed"===c&&x>=0&&R>=0&&C<=b&&I<=H&&x>=l&&C<=d&&R>=s&&I<=r)return k;const h=getComputedStyle(e),a=parseInt(h.borderLeftWidth,10),g=parseInt(h.borderTopWidth,10),m=parseInt(h.borderRightWidth,10),W=parseInt(h.borderBottomWidth,10);let B=0,D=0;const L="offsetWidth"in e?e.offsetWidth-e.clientWidth-a-m:0,S="offsetHeight"in e?e.offsetHeight-e.clientHeight-g-W:0,X="offsetWidth"in e?0===e.offsetWidth?0:i/e.offsetWidth:0,Y="offsetHeight"in e?0===e.offsetHeight?0:n/e.offsetHeight:0;if(p===e)B="start"===f?T:"end"===f?T-b:"nearest"===f?o(y,y+b,b,g,W,y+T,y+T+E,E):T-b/2,D="start"===u?V:"center"===u?V-H/2:"end"===u?V-H:o(v,v+H,H,a,m,v+V,v+V+M,M),B=Math.max(0,B+y),D=Math.max(0,D+v);else {B="start"===f?T-l-g:"end"===f?T-d+W+S:"nearest"===f?o(l,d,n,g,W+S,T,T+E,E):T-(l+n/2)+S/2,D="start"===u?V-s-a:"center"===u?V-(s+i/2)+L/2:"end"===u?V-r+m+L:o(s,r,i,a,m+L,V,V+M,M);const{scrollLeft:t,scrollTop:h}=e;B=Math.max(0,Math.min(h+B/Y,e.scrollHeight-n/Y+S)),D=Math.max(0,Math.min(t+D/X,e.scrollWidth-i/X+L)),T+=h-B,V+=t-D;}k.push({el:e,top:B,left:D});}return k};
299
299
 
300
300
  var idCounter = 0;
301
301
 
@@ -321,7 +321,7 @@
321
321
  if (!node) {
322
322
  return;
323
323
  }
324
- var actions = r(node, {
324
+ var actions = l(node, {
325
325
  boundary: menuNode,
326
326
  block: 'nearest',
327
327
  scrollMode: 'if-needed'
@@ -1927,9 +1927,10 @@
1927
1927
  * @param {Function} reducer Reducer function from downshift.
1928
1928
  * @param {Object} props The hook props, also passed to createInitialState.
1929
1929
  * @param {Function} createInitialState Function that returns the initial state.
1930
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1930
1931
  * @returns {Array} An array with the state and an action dispatcher.
1931
1932
  */
1932
- function useEnhancedReducer(reducer, props, createInitialState) {
1933
+ function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
1933
1934
  var prevStateRef = React.useRef();
1934
1935
  var actionRef = React.useRef();
1935
1936
  var enhancedReducer = React.useCallback(function (state, action) {
@@ -1952,11 +1953,12 @@
1952
1953
  }, [propsRef]);
1953
1954
  var action = actionRef.current;
1954
1955
  React.useEffect(function () {
1955
- if (action && prevStateRef.current && prevStateRef.current !== state) {
1956
+ var stateChanged = prevStateRef.current && !isStateEqual(prevStateRef.current, state);
1957
+ if (action && stateChanged) {
1956
1958
  callOnChangeProps(action, getState(prevStateRef.current, action.props), state);
1957
1959
  }
1958
1960
  prevStateRef.current = state;
1959
- }, [state, props, action]);
1961
+ }, [state, props, action, isStateEqual]);
1960
1962
  return [state, dispatchWithProps];
1961
1963
  }
1962
1964
 
@@ -1967,10 +1969,11 @@
1967
1969
  * @param {Function} reducer Reducer function from downshift.
1968
1970
  * @param {Object} props The hook props, also passed to createInitialState.
1969
1971
  * @param {Function} createInitialState Function that returns the initial state.
1972
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
1970
1973
  * @returns {Array} An array with the state and an action dispatcher.
1971
1974
  */
1972
- function useControlledReducer$1(reducer, props, createInitialState) {
1973
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
1975
+ function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
1976
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
1974
1977
  state = _useEnhancedReducer[0],
1975
1978
  dispatch = _useEnhancedReducer[1];
1976
1979
  return [getState(state, props), dispatch];
@@ -2252,6 +2255,18 @@
2252
2255
  }));
2253
2256
  }
2254
2257
 
2258
+ /**
2259
+ * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
2260
+ * Used by useSelect and useCombobox.
2261
+ *
2262
+ * @param {Object} prevState
2263
+ * @param {Object} newState
2264
+ * @returns {boolean} Wheather the states are deeply equal.
2265
+ */
2266
+ function isDropdownsStateEqual(prevState, newState) {
2267
+ return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
2268
+ }
2269
+
2255
2270
  // Shared between all exports.
2256
2271
  var commonPropTypes = {
2257
2272
  environment: PropTypes__default["default"].shape({
@@ -2605,14 +2620,13 @@
2605
2620
  getA11ySelectionMessage = props.getA11ySelectionMessage,
2606
2621
  getA11yStatusMessage = props.getA11yStatusMessage;
2607
2622
  // Initial state depending on controlled props.
2608
- var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2),
2623
+ var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$2, isDropdownsStateEqual),
2609
2624
  state = _useControlledReducer[0],
2610
2625
  dispatch = _useControlledReducer[1];
2611
2626
  var isOpen = state.isOpen,
2612
2627
  highlightedIndex = state.highlightedIndex,
2613
2628
  selectedItem = state.selectedItem,
2614
2629
  inputValue = state.inputValue;
2615
-
2616
2630
  // Element efs.
2617
2631
  var toggleButtonRef = React.useRef(null);
2618
2632
  var menuRef = React.useRef(null);
@@ -3090,11 +3104,12 @@
3090
3104
  * @param {Function} reducer Reducer function from downshift.
3091
3105
  * @param {Object} props The hook props, also passed to createInitialState.
3092
3106
  * @param {Function} createInitialState Function that returns the initial state.
3107
+ * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
3093
3108
  * @returns {Array} An array with the state and an action dispatcher.
3094
3109
  */
3095
- function useControlledReducer(reducer, props, createInitialState) {
3110
+ function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
3096
3111
  var previousSelectedItemRef = React.useRef();
3097
- var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState),
3112
+ var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
3098
3113
  state = _useEnhancedReducer[0],
3099
3114
  dispatch = _useEnhancedReducer[1];
3100
3115
 
@@ -3268,7 +3283,7 @@
3268
3283
  getA11ySelectionMessage = props.getA11ySelectionMessage,
3269
3284
  itemToString = props.itemToString;
3270
3285
  // Initial state depending on controlled props.
3271
- var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1),
3286
+ var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$1, isDropdownsStateEqual),
3272
3287
  state = _useControlledReducer[0],
3273
3288
  dispatch = _useControlledReducer[1];
3274
3289
  var isOpen = state.isOpen,
@@ -3753,6 +3768,18 @@
3753
3768
  itemToStringLocal = selectionParameters.itemToString;
3754
3769
  return itemToStringLocal(removedSelectedItem) + " has been removed.";
3755
3770
  }
3771
+
3772
+ /**
3773
+ * Check if a state is equal for taglist, by comparing active index and selected items.
3774
+ * Used by useSelect and useCombobox.
3775
+ *
3776
+ * @param {Object} prevState
3777
+ * @param {Object} newState
3778
+ * @returns {boolean} Wheather the states are deeply equal.
3779
+ */
3780
+ function isStateEqual(prevState, newState) {
3781
+ return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
3782
+ }
3756
3783
  var propTypes = _extends({}, commonPropTypes, {
3757
3784
  selectedItems: PropTypes__default["default"].array,
3758
3785
  initialSelectedItems: PropTypes__default["default"].array,
@@ -3942,7 +3969,7 @@
3942
3969
  keyNavigationPrevious = props.keyNavigationPrevious;
3943
3970
 
3944
3971
  // Reducer init.
3945
- var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState),
3972
+ var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState, isStateEqual),
3946
3973
  state = _useControlledReducer[0],
3947
3974
  dispatch = _useControlledReducer[1];
3948
3975
  var activeIndex = state.activeIndex,