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.

94 lines (92 loc) 3.22 kB
import React, { useRef, useCallback, useMemo, useEffect } from "react"; import styled from "styled-components"; import Portal from "../Portal"; import PopoverContentWrapper from "./components/ContentWrapper"; import useTheme from "../hooks/useTheme"; import useStateWithTimeout from "../hooks/useStateWithTimeout"; const StyledPopoverChild = styled.div.withConfig({ displayName: "Popover__StyledPopoverChild", componentId: "t88fx4-0" })(["position:relative;"]); const Popover = ({ children, content, preferredPosition = "bottom", dataTest, opened, width, noPadding, overlapped, onClose, onOpen, fixed }) => { const theme = useTheme(); const transitionLength = useMemo(() => parseFloat(theme.orbit.durationFast) * 1000, [theme.orbit.durationFast]); const [shown, setShown, setShownWithTimeout, clearShownTimeout] = useStateWithTimeout(false, transitionLength); const [render, setRender, setRenderWithTimeout, clearRenderTimeout] = useStateWithTimeout(false, transitionLength); const container = useRef(null); const resolveCallback = useCallback(state => { if (onClose && !state) onClose(); if (onOpen && state) onOpen(); }, [onClose, onOpen]); const handleOut = useCallback(ev => { // If open prop is present ignore custom handler if (container.current && !container.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 = 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 { resolveCallback(!shown); } }, [clearRenderTimeout, clearShownTimeout, opened, resolveCallback, setRender, setRenderWithTimeout, setShown, setShownWithTimeout, shown]); 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]); return React.createElement(React.Fragment, null, React.createElement(StyledPopoverChild, { onClick: handleClick, ref: container }, children), render && React.createElement(Portal, { element: "popovers" }, React.createElement(PopoverContentWrapper, { shown: shown, width: width, containerRef: container, preferredPosition: preferredPosition, onClose: handleOut, dataTest: dataTest, noPadding: noPadding, overlapped: overlapped, fixed: fixed }, content))); }; export default Popover;