UNPKG

@geist-ui/react

Version:

Modern and minimalist React UI library.

141 lines (121 loc) 4.56 kB
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _extends from "@babel/runtime/helpers/esm/extends"; import _JSXStyle from "../styled-jsx.es.js"; import React, { useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import usePortal from '../utils/use-portal'; import useResize from '../utils/use-resize'; import CssTransition from './css-transition'; import useClickAnyWhere from '../utils/use-click-anywhere'; import useDOMObserver from '../utils/use-dom-observer'; import useWarning from '../utils/use-warning'; var defaultRect = { top: -1000, left: -1000, right: -1000, width: 0 }; var getOffset = function getOffset(el) { if (!el) return { top: 0, left: 0 }; var _el$getBoundingClient = el.getBoundingClientRect(), top = _el$getBoundingClient.top, left = _el$getBoundingClient.left; return { top: top, left: left }; }; var getRect = function getRect(ref, getContainer) { if (!ref || !ref.current) return defaultRect; var rect = ref.current.getBoundingClientRect(); var container = getContainer ? getContainer() : null; var scrollElement = container || document.documentElement; var _getOffset = getOffset(container), offsetTop = _getOffset.top, offsetLeft = _getOffset.left; return _extends({}, rect, { width: rect.width || rect.right - rect.left, top: rect.bottom + scrollElement.scrollTop - offsetTop, left: rect.left + scrollElement.scrollLeft - offsetLeft }); }; var Dropdown = /*#__PURE__*/React.memo(function (_ref) { var children = _ref.children, parent = _ref.parent, visible = _ref.visible, disableMatchWidth = _ref.disableMatchWidth, getPopupContainer = _ref.getPopupContainer; var el = usePortal('dropdown', getPopupContainer); var _useState = useState(defaultRect), _useState2 = _slicedToArray(_useState, 2), rect = _useState2[0], setRect = _useState2[1]; if (!parent) return null; /* istanbul ignore next */ if (process.env.NODE_ENV !== 'production') { if (getPopupContainer && getPopupContainer()) { var _el = getPopupContainer(); var style = window.getComputedStyle(_el); if (style.position === 'static') { useWarning('The element specified by "getPopupContainer" must have "position" set.'); } } } var updateRect = function updateRect() { var _getRect = getRect(parent, getPopupContainer), top = _getRect.top, left = _getRect.left, right = _getRect.right, nativeWidth = _getRect.width; setRect({ top: top, left: left, right: right, width: nativeWidth }); }; useResize(updateRect); useClickAnyWhere(function () { var _getRect2 = getRect(parent, getPopupContainer), top = _getRect2.top, left = _getRect2.left; var shouldUpdatePosition = top !== rect.top || left !== rect.left; if (!shouldUpdatePosition) return; updateRect(); }); useDOMObserver(parent, function () { updateRect(); }); useEffect(function () { if (!parent || !parent.current) return; parent.current.addEventListener('mouseenter', updateRect); /* istanbul ignore next */ return function () { if (!parent || !parent.current) return; parent.current.removeEventListener('mouseenter', updateRect); }; }, [parent]); var clickHandler = function clickHandler(event) { event.stopPropagation(); event.nativeEvent.stopImmediatePropagation(); event.preventDefault(); }; var mouseDownHandler = function mouseDownHandler(event) { event.preventDefault(); }; if (!el) return null; return /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(CssTransition, { visible: visible }, /*#__PURE__*/React.createElement("div", { onClick: clickHandler, onMouseDown: mouseDownHandler, className: _JSXStyle.dynamic([["2976859150", [rect.top + 2, rect.left, rect.width, rect.width]]]) + " " + "dropdown ".concat(disableMatchWidth ? 'disable-match' : 'width-match') }, children, /*#__PURE__*/React.createElement(_JSXStyle, { id: "2976859150", dynamic: [rect.top + 2, rect.left, rect.width, rect.width] }, ".dropdown.__jsx-style-dynamic-selector{position:absolute;top:".concat(rect.top + 2, "px;left:").concat(rect.left, "px;z-index:1100;}.width-match.__jsx-style-dynamic-selector{width:").concat(rect.width, "px;}.disable-match.__jsx-style-dynamic-selector{min-width:").concat(rect.width, "px;}")))), el); }); export default Dropdown;