UNPKG

@kiwicom/orbit-components

Version:

Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.

113 lines 3.66 kB
import * as React from "react"; import styled from "styled-components"; import useStateWithTimeout from "../hooks/useStateWithTimeout"; import { PLACEMENTS } from "../common/consts"; import PopoverContent from "./components/ContentWrapper"; import Portal from "../Portal"; import handleKeyDown from "../utils/handleKeyDown"; const StyledPopoverChild = styled.div.withConfig({ displayName: "Popover__StyledPopoverChild", componentId: "sc-te0bas-0" })(["position:relative;"]); const Popover = ({ children, renderInPortal = true, opened, content, onClose, id, onOpen, offset, placement = PLACEMENTS.BOTTOM_START, fixed, lockScrolling = true, noFlip, labelClose = "Close", renderTimeout = 0, allowOverflow, noPadding, width, maxHeight, actions, overlapped, dataTest }) => { const ref = React.useRef(null); const [shown, setShown, setShownWithTimeout, clearShownTimeout] = useStateWithTimeout(false, renderTimeout); const [render, setRender, setRenderWithTimeout, clearRenderTimeout] = useStateWithTimeout(false, renderTimeout); const resolveCallback = React.useCallback(state => { if (onClose && !state) onClose(); if (onOpen && state) onOpen(); }, [onClose, onOpen]); const handleOut = React.useCallback(ev => { // If open prop is present ignore custom handler if (ev && ref.current && !ref.current.contains(ev.target)) { if (typeof opened === "undefined") { setShown(false); clearShownTimeout(); setRenderWithTimeout(false); resolveCallback(false); } else if (onClose) onClose(); } }, [clearShownTimeout, onClose, opened, resolveCallback, setRenderWithTimeout, setShown]); const handleClick = React.useCallback(() => { // If open prop is present ignore custom handler if (typeof opened === "undefined") { if (shown) { setShown(false); clearShownTimeout(); setRenderWithTimeout(false); resolveCallback(false); } else { setRender(true); clearRenderTimeout(); setShownWithTimeout(true); resolveCallback(true); } } else if (opened) { resolveCallback(false); } else if (!opened) { resolveCallback(true); } }, [clearRenderTimeout, clearShownTimeout, opened, resolveCallback, setRender, setRenderWithTimeout, setShown, setShownWithTimeout, shown]); React.useEffect(() => { if (typeof opened !== "undefined") { if (opened) { setRender(true); clearRenderTimeout(); setShownWithTimeout(true); } else { setShown(false); clearShownTimeout(); setRenderWithTimeout(false); } } }, [opened, clearRenderTimeout, clearShownTimeout, setRender, setShown, setShownWithTimeout, setRenderWithTimeout]); const popover = /*#__PURE__*/React.createElement(PopoverContent, { shown: shown, id: id, labelClose: labelClose, dataTest: dataTest, overlapped: overlapped, fixed: fixed, noFlip: noFlip, allowOverflow: allowOverflow, lockScrolling: lockScrolling, noPadding: noPadding, actions: actions, width: width, maxHeight: maxHeight, offset: offset, referenceElement: ref.current, onClose: handleOut, placement: placement }, content); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledPopoverChild, { ref: ref, onClick: handleClick, onKeyDown: handleKeyDown(handleClick) }, children), render && (renderInPortal ? /*#__PURE__*/React.createElement(Portal, { renderInto: "popovers" }, popover) : popover)); }; export default Popover;