import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; import PropTypes from 'prop-types'; import React, { useState } from 'react'; import ReactDOM from 'react-dom'; import useCallbackRef from '@restart/hooks/useCallbackRef'; import useMergedRefs from '@restart/hooks/useMergedRefs'; import { placements } from './popper'; import usePopper from './usePopper'; import useRootClose from './useRootClose'; import useWaitForDOMRef from './useWaitForDOMRef'; import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig'; /** * Built on top of `Popper.js`, the overlay component is * great for custom tooltip overlays. */ var Overlay = /*#__PURE__*/React.forwardRef(function (props, outerRef) { var flip = props.flip, offset = props.offset, placement = props.placement, _props$containerPaddi = props.containerPadding, containerPadding = _props$containerPaddi === void 0 ? 5 : _props$containerPaddi, _props$popperConfig = props.popperConfig, popperConfig = _props$popperConfig === void 0 ? {} : _props$popperConfig, Transition = props.transition; var _useCallbackRef = useCallbackRef(), rootElement = _useCallbackRef[0], attachRef = _useCallbackRef[1]; var _useCallbackRef2 = useCallbackRef(), arrowElement = _useCallbackRef2[0], attachArrowRef = _useCallbackRef2[1]; var mergedRef = useMergedRefs(attachRef, outerRef); var container = useWaitForDOMRef(props.container); var target = useWaitForDOMRef(props.target); var _useState = useState(!props.show), exited = _useState[0], setExited = _useState[1]; var _usePopper = usePopper(target, rootElement, mergeOptionsWithPopperConfig({ placement: placement, enableEvents: !!props.show, containerPadding: containerPadding || 5, flip: flip, offset: offset, arrowElement: arrowElement, popperConfig: popperConfig })), styles = _usePopper.styles, attributes = _usePopper.attributes, popper = _objectWithoutPropertiesLoose(_usePopper, ["styles", "attributes"]); if (props.show) { if (exited) setExited(false); } else if (!props.transition && !exited) { setExited(true); } var handleHidden = function handleHidden() { setExited(true); if (props.onExited) { props.onExited.apply(props, arguments); } }; // Don't un-render the overlay while it's transitioning out. var mountOverlay = props.show || Transition && !exited; useRootClose(rootElement, props.onHide, { disabled: !props.rootClose || props.rootCloseDisabled, clickTrigger: props.rootCloseEvent }); if (!mountOverlay) { // Don't bother showing anything if we don't have to. return null; } var child = props.children(_extends({}, popper, { show: !!props.show, props: _extends({}, attributes.popper, { style: styles.popper, ref: mergedRef }), arrowProps: _extends({}, attributes.arrow, { style: styles.arrow, ref: attachArrowRef }) })); if (Transition) { var onExit = props.onExit, onExiting = props.onExiting, onEnter = props.onEnter, onEntering = props.onEntering, onEntered = props.onEntered; child = /*#__PURE__*/React.createElement(Transition, { "in": props.show, appear: true, onExit: onExit, onExiting: onExiting, onExited: handleHidden, onEnter: onEnter, onEntering: onEntering, onEntered: onEntered }, child); } return container ? /*#__PURE__*/ReactDOM.createPortal(child, container) : null; }); Overlay.displayName = 'Overlay'; Overlay.propTypes = { /** * Set the visibility of the Overlay */ show: PropTypes.bool, /** Specify where the overlay element is positioned in relation to the target element */ placement: PropTypes.oneOf(placements), /** * A DOM Element, Ref to an element, or function that returns either. The `target` element is where * the overlay is positioned relative to. */ target: PropTypes.any, /** * A DOM Element, Ref to an element, or function that returns either. The `container` will have the Portal children * appended to it. */ container: PropTypes.any, /** * Enables the Popper.js `flip` modifier, allowing the Overlay to * automatically adjust it's placement in case of overlap with the viewport or toggle. * Refer to the [flip docs](https://popper.js.org/popper-documentation.html#modifiers..flip.enabled) for more info */ flip: PropTypes.bool, /** * A render prop that returns an element to overlay and position. See * the [react-popper documentation](https://github.com/FezVrasta/react-popper#children) for more info. * * @type {Function ({ * show: boolean, * placement: Placement, * update: () => void, * forceUpdate: () => void, * props: { * ref: (?HTMLElement) => void, * style: { [string]: string | number }, * aria-labelledby: ?string * [string]: string | number, * }, * arrowProps: { * ref: (?HTMLElement) => void, * style: { [string]: string | number }, * [string]: string | number, * }, * }) => React.Element} */ children: PropTypes.func.isRequired, /** * Control how much space there is between the edge of the boundary element and overlay. * A convenience shortcut to setting `popperConfig.modfiers.preventOverflow.padding` */ containerPadding: PropTypes.number, /** * A set of popper options and props passed directly to react-popper's Popper component. */ popperConfig: PropTypes.object, /** * Specify whether the overlay should trigger `onHide` when the user clicks outside the overlay */ rootClose: PropTypes.bool, /** * Specify event for toggling overlay */ rootCloseEvent: PropTypes.oneOf(['click', 'mousedown']), /** * Specify disabled for disable RootCloseWrapper */ rootCloseDisabled: PropTypes.bool, /** * A Callback fired by the Overlay when it wishes to be hidden. * * __required__ when `rootClose` is `true`. * * @type func */ onHide: function onHide(props) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (props.rootClose) { var _PropTypes$func; return (_PropTypes$func = PropTypes.func).isRequired.apply(_PropTypes$func, [props].concat(args)); } return PropTypes.func.apply(PropTypes, [props].concat(args)); }, /** * A `react-transition-group@2.0.0` `` component * used to animate the overlay as it changes visibility. */ // @ts-ignore transition: PropTypes.elementType, /** * Callback fired before the Overlay transitions in */ onEnter: PropTypes.func, /** * Callback fired as the Overlay begins to transition in */ onEntering: PropTypes.func, /** * Callback fired after the Overlay finishes transitioning in */ onEntered: PropTypes.func, /** * Callback fired right before the Overlay transitions out */ onExit: PropTypes.func, /** * Callback fired as the Overlay begins to transition out */ onExiting: PropTypes.func, /** * Callback fired after the Overlay finishes transitioning out */ onExited: PropTypes.func }; export default Overlay;