UNPKG

@chakra-ui/core

Version:

Responsive and accessible React UI components built with React and Emotion

210 lines (178 loc) 6.98 kB
import _extends from "@babel/runtime/helpers/extends"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } /** * Popper Component * * The following code is a derivative of the amazing work done by the Material UI team. * Original source: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Popper/Popper.js */ /** @jsx jsx */ import { jsx } from "@emotion/core"; import React, { forwardRef, useEffect, useLayoutEffect, useRef, useImperativeHandle, useState, useCallback } from "react"; import PopperJS from "popper.js"; import Portal from "../Portal"; import PseudoBox from "../PseudoBox"; import Box from "../Box"; import { useForkRef, setRef, createChainedFunction } from "../utils"; import getPopperArrowStyle from "./styles"; /** * Flips placement if in <body dir="rtl" /> * @param {string} placement */ function flipPlacement(placement) { var direction = typeof window !== "undefined" && document.body.getAttribute("dir") || "ltr"; if (direction !== "rtl") { return placement; } switch (placement) { case "bottom-end": return "bottom-start"; case "bottom-start": return "bottom-end"; case "top-end": return "top-start"; case "top-start": return "top-end"; default: return placement; } } function getAnchorEl(anchorEl) { return typeof anchorEl === "function" ? anchorEl() : anchorEl; } var useEnhancedEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect; var Popper = forwardRef(function (_ref, ref) { var anchorEl = _ref.anchorEl, children = _ref.children, gutter = _ref.gutter, container = _ref.container, _ref$usePortal = _ref.usePortal, usePortal = _ref$usePortal === void 0 ? true : _ref$usePortal, _ref$unmountOnExit = _ref.unmountOnExit, unmountOnExit = _ref$unmountOnExit === void 0 ? true : _ref$unmountOnExit, modifiers = _ref.modifiers, isOpen = _ref.isOpen, _ref$placement = _ref.placement, initialPlacement = _ref$placement === void 0 ? "bottom" : _ref$placement, _ref$popperOptions = _ref.popperOptions, popperOptions = _ref$popperOptions === void 0 ? {} : _ref$popperOptions, popperRefProp = _ref.popperRef, _ref$willUseTransitio = _ref.willUseTransition, willUseTransition = _ref$willUseTransitio === void 0 ? false : _ref$willUseTransitio, arrowSize = _ref.arrowSize, arrowShadowColor = _ref.arrowShadowColor, hasArrow = _ref.hasArrow, rest = _objectWithoutPropertiesLoose(_ref, ["anchorEl", "children", "gutter", "container", "usePortal", "unmountOnExit", "modifiers", "isOpen", "placement", "popperOptions", "popperRef", "willUseTransition", "arrowSize", "arrowShadowColor", "hasArrow"]); var tooltipRef = useRef(null); var ownRef = useForkRef(tooltipRef, ref); var popperRef = useRef(null); var handlePopperRef = useForkRef(popperRef, popperRefProp); var handlePopperRefRef = useRef(handlePopperRef); useEnhancedEffect(function () { handlePopperRefRef.current = handlePopperRef; }, [handlePopperRef]); useImperativeHandle(popperRefProp, function () { return popperRef.current; }, []); var _useState = useState(true), exited = _useState[0], setExited = _useState[1]; var rtlPlacement = flipPlacement(initialPlacement); var _useState2 = useState(rtlPlacement), placement = _useState2[0], setPlacement = _useState2[1]; if (rtlPlacement !== placement) { setPlacement(rtlPlacement); } var handleOpen = useCallback(function () { var popperNode = tooltipRef.current; if (!popperNode || !anchorEl || !isOpen) { return; } if (popperRef.current) { popperRef.current.destroy(); handlePopperRefRef.current(null); } var handlePopperUpdate = function handlePopperUpdate(data) { setPlacement(data.placement); }; var popper = new PopperJS(getAnchorEl(anchorEl), popperNode, _objectSpread({ placement: rtlPlacement }, popperOptions, { modifiers: _objectSpread({}, usePortal && { preventOverflow: { boundariesElement: "window" } }, {}, modifiers, {}, popperOptions.modifiers), onUpdate: createChainedFunction(handlePopperUpdate, popperOptions.onUpdate) })); handlePopperRefRef.current(popper); }, [anchorEl, usePortal, modifiers, isOpen, rtlPlacement, popperOptions]); var handleRef = useCallback(function (node) { setRef(ownRef, node); handleOpen(); }, [ownRef, handleOpen]); var handleEnter = function handleEnter() { setExited(false); }; var handleClose = function handleClose() { if (!popperRef.current) { return; } popperRef.current.destroy(); handlePopperRefRef.current(null); }; var handleExited = function handleExited() { setExited(true); handleClose(); }; useEffect(function () { handleOpen(); }, [handleOpen]); useEffect(function () { return function () { handleClose(); }; }, []); useEffect(function () { if (!isOpen && !willUseTransition) { handleClose(); } }, [isOpen, willUseTransition]); if (unmountOnExit && !isOpen && (!willUseTransition || exited)) { return null; } var childProps = { placement: placement }; if (willUseTransition) { childProps.transition = { "in": isOpen, onEnter: handleEnter, onExited: handleExited }; } return jsx(Portal, { isDisabled: !usePortal, container: container }, jsx(PseudoBox, _extends({ ref: handleRef, pos: "absolute", css: getPopperArrowStyle({ arrowSize: arrowSize, arrowShadowColor: arrowShadowColor, hasArrow: hasArrow }) }, rest), typeof children === "function" ? children(childProps) : children)); }); export default Popper; export var PopperArrow = function PopperArrow(props) { return jsx(Box, _extends({ "x-arrow": "", role: "presentation", bg: "inherit" }, props)); };