All files / ResponsiveButtonGroup useResponsiveButtonGroupSizing.js

3.7% Statements 1/27
0% Branches 0/15
0% Functions 0/7
3.7% Lines 1/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73            27x                                                                                                                                    
import { cloneElement, useEffect, useRef, useState } from 'react';
import isEqual from 'lodash/isEqual';
 
import { useResizeDetector } from 'react-resize-detector';
import { debounce } from 'lodash';
 
const useResponsiveButtonGroupSizing = ({
  id,
  buttons = [],
}) => {
  const eventString = 'responsive-button-group-loaded' + (id ? `-${id}` : '');
  const loadedEvent = new Event(eventString);
 
  const isMounted = useRef(false);
  useEffect(() => {
    isMounted.current = true;
 
    return () => {
      isMounted.current = false;
    };
  }, []);
 
  // Set up size measuring to be able to do fullWidth if and only if the button is too small for the container.
  // This way when the button is too _large_ for the container, we can measure it properly
  const { ref: containerRef, width: containerWidth } = useResizeDetector();
 
  const [cachedSizeArray, setCachedSizeArray] = useState([]);
  const [sizeArray, setSizeArray] = useState([]);
  // We also need to set up a ref for each of the buttons
  // to measure the size of each one, we can then use that for choosing where to break later.
  const refArray = buttons.map((_button, index) => {
    return (node) => {
      if (node !== null) {
        const newSizeArray = sizeArray.slice(0, index)
                                      .concat([node?.clientWidth ?? 0])
                                      .concat(sizeArray.slice(index + 1));
 
        if (!isEqual(sizeArray, newSizeArray)) {
          setSizeArray(newSizeArray);
        }
      }
    };
  });
 
  const [ready, setReady] = useState(false);
 
  // eslint-disable-next-line react-hooks/exhaustive-deps
  useEffect(debounce(() => {
    if (isMounted.current) {
      if (!cachedSizeArray?.length && sizeArray?.length) {
        setCachedSizeArray(sizeArray);
        setReady(true);
        document.dispatchEvent(loadedEvent);
      }
    }
  }, 150), [cachedSizeArray, sizeArray]);
 
  const returnButtons = buttons?.map((button, index) => {
    return cloneElement(button, { ref: refArray?.[index] });
  });
 
  return {
    buttons: returnButtons,
    cachedSizeArray,
    containerRef,
    containerWidth,
    ready,
    sizeArray
  };
};
 
export default useResponsiveButtonGroupSizing;