All files / atoms/Dropdown index.jsx

29.41% Statements 5/17
0% Branches 0/6
0% Functions 0/3
33.33% Lines 5/15

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 74 75 76 77 78 79 80 81 82 83                                      1x             1x                                                                         1x 1x                 1x                  
import React, { useRef } from 'react';
import { createPortal } from 'react-dom';
 
import PropTypes from 'prop-types';
import { useClickAway } from 'react-use';
import Paper from '../Paper';
 
import getBodyNode from '../../util/getBodyNode';
import getCss from './getCss';
import usePositionBinding from './usePositionBinding';
 
import {
  DROPDOWN_STATE_DISABLED,
  DROPDOWN_STATE_ENTERING,
  DROPDOWN_STATE_READY,
  DROPDOWN_STATE_EXITING,
  DROPDOWN_PALCEMENT_BL,
} from './constants';
 
const knownStates = [
  DROPDOWN_STATE_DISABLED,
  DROPDOWN_STATE_ENTERING,
  DROPDOWN_STATE_READY,
  DROPDOWN_STATE_EXITING,
];
 
const Dropdown = ({
  bindTo,
  children,
  onExit,
  onBeginExit,
  onReadyState,
  placement,
  state,
  ...rest
}) => {
  const bodyNode = getBodyNode();
  const dropdownRef = useRef(null);
  const dynamicCss = usePositionBinding(bindTo, placement);
 
  function handleAnimationEnd() {
    if (state === DROPDOWN_STATE_EXITING) onExit();
    else onReadyState();
  }
  const awayHandler = state === DROPDOWN_STATE_READY ? onBeginExit : () => {};
  useClickAway(dropdownRef, awayHandler, ['click']);
  if (state === DROPDOWN_STATE_DISABLED) return null;
 
  const output = (
    <Paper
      rize={1}
      {...rest}
      atomRef={dropdownRef}
      css={{ ...getCss(state), ...dynamicCss }}
      // eslint-disable-next-line react/jsx-no-bind
      onAnimationEnd={handleAnimationEnd}
    >
      {children}
    </Paper>
  );
  return createPortal(output, bodyNode);
};
 
Dropdown.displayName = 'Dropdown';
Dropdown.propTypes = {
  bindTo: PropTypes.shape().isRequired,
  children: PropTypes.node.isRequired,
  onBeginExit: PropTypes.func,
  onExit: PropTypes.func,
  onReadyState: PropTypes.func,
  placement: PropTypes.string,
  state: PropTypes.oneOf(knownStates),
};
Dropdown.defaultProps = {
  placement: DROPDOWN_PALCEMENT_BL,
  state: DROPDOWN_STATE_DISABLED,
  onBeginExit: undefined,
  onExit: undefined,
  onReadyState: undefined,
};
 
export default Dropdown;