UNPKG

react-bootstrap-typeahead

Version:
71 lines (70 loc) 2.13 kB
import PropTypes from 'prop-types'; import { useEffect, useState, } from 'react'; import { usePopper } from 'react-popper'; import { noop } from '../../utils'; const alignValues = ['justify', 'left', 'right']; const SafeElement = typeof Element === 'undefined' ? noop : Element; const propTypes = { align: PropTypes.oneOf(alignValues), children: PropTypes.func.isRequired, dropup: PropTypes.bool, flip: PropTypes.bool, isMenuShown: PropTypes.bool, positionFixed: PropTypes.bool, referenceElement: PropTypes.instanceOf(SafeElement), }; const defaultProps = { align: 'justify', dropup: false, flip: false, isMenuShown: false, positionFixed: false, }; const setPopperWidth = { enabled: true, fn: (data) => { data.state.styles.popper.width = `${data.state.rects.reference.width}px`; }, name: 'setPopperWidth', phase: 'write', }; export function getModifiers(props) { const modifiers = [ { enabled: !!props.flip, name: 'flip', }, ]; if (props.align !== 'right' && props.align !== 'left') { modifiers.push(setPopperWidth); } return modifiers; } export function getPlacement(props) { const x = props.align === 'right' ? 'end' : 'start'; const y = props.dropup ? 'top' : 'bottom'; return `${y}-${x}`; } const Overlay = ({ referenceElement, ...props }) => { const [popperElement, attachRef] = useState(null); const { attributes, styles, forceUpdate } = usePopper(referenceElement, popperElement, { modifiers: getModifiers(props), placement: getPlacement(props), strategy: props.positionFixed ? 'fixed' : 'absolute', }); const refElementHeight = referenceElement?.offsetHeight; useEffect(() => { forceUpdate && forceUpdate(); }, [refElementHeight]); if (!props.isMenuShown) { return null; } return props.children({ ...attributes.popper, innerRef: attachRef, style: styles.popper, }); }; Overlay.propTypes = propTypes; Overlay.defaultProps = defaultProps; export default Overlay;