rsuite
Version:
A suite of react components
116 lines (115 loc) • 3.37 kB
JavaScript
'use client';
import _extends from "@babel/runtime/helpers/esm/extends";
import React, { useState, useRef, useCallback } from 'react';
import classNames from 'classnames';
import Fade from "../../Animation/Fade.js";
import Position, { getPositionStyle } from "./Position.js";
import { useOverlay } from "./OverlayProvider.js";
import { useRootClose } from "../hooks/index.js";
import { mergeRefs, mergeStyles } from "../utils/index.js";
/**
* Overlay is a powerful component that helps you create floating components.
* @private
*/
const Overlay = /*#__PURE__*/React.forwardRef((props, ref) => {
const {
overlayContainer
} = useOverlay();
const {
container = overlayContainer,
containerPadding,
placement,
rootClose,
children,
childrenProps,
transition: Transition = Fade,
open,
preventOverflow,
triggerTarget,
onClose,
onExited,
onExit,
onExiting,
onEnter,
onEntering,
onEntered,
followCursor,
cursorPosition
} = props;
const [exited, setExited] = useState(!open);
const overlayTarget = useRef(null);
if (open) {
if (exited) setExited(false);
} else if (!Transition && !exited) {
setExited(true);
}
const mountOverlay = open || Transition && !exited;
const handleExited = useCallback(args => {
setExited(true);
onExited === null || onExited === void 0 || onExited(args);
}, [onExited]);
useRootClose(onClose, {
triggerTarget,
overlayTarget,
disabled: !rootClose || !mountOverlay
});
if (!mountOverlay) {
return null;
}
const positionProps = {
container,
containerPadding,
triggerTarget,
placement,
preventOverflow,
followCursor,
cursorPosition
};
const renderChildWithPosition = (transitionProps, transitionRef) => {
const {
className
} = transitionProps || {};
return /*#__PURE__*/React.createElement(Position, _extends({}, positionProps, transitionProps, {
ref: mergeRefs(ref, transitionRef)
}), (positionChildProps, childRef) => {
// Position will return coordinates and className
const {
left,
top
} = positionChildProps;
// Components returned by function children need to control their own positioning information. For example: Picker
if (typeof children === 'function') {
return children({
className,
//dataAttributes,
...positionChildProps,
...childrenProps
}, mergeRefs(childRef, overlayTarget));
}
const childElement = children;
const childStyles = mergeStyles(getPositionStyle(left, top), childElement.props.style);
return /*#__PURE__*/React.cloneElement(childElement, {
...childrenProps,
...childElement.props,
className: classNames(childElement.props.className, className),
style: childStyles,
ref: mergeRefs(childRef, overlayTarget)
});
});
};
if (Transition) {
return /*#__PURE__*/React.createElement(Transition, {
in: open,
transitionAppear: true,
onExit: onExit,
onExiting: onExiting,
onExited: handleExited,
onEnter: onEnter,
onEntering: onEntering,
onEntered: onEntered
}, renderChildWithPosition);
}
return renderChildWithPosition();
});
Overlay.displayName = 'Overlay';
export default Overlay;