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.

219 lines 8.19 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import * as React from "react"; import styled, { css } from "styled-components"; import { convertHexToRgba } from "@kiwicom/orbit-design-tokens"; import { usePopper } from "react-popper"; import defaultTheme from "../../defaultTheme"; import mq from "../../utils/mediaQuery"; import Button from "../../Button"; import useMediaQuery from "../../hooks/useMediaQuery"; import transition from "../../utils/transition"; import useClickOutside from "../../hooks/useClickOutside"; import useLockScrolling from "../../hooks/useLockScrolling"; import { ModalContext } from "../../Modal/ModalContext"; import { PLACEMENTS } from "../../common/consts"; import boundingClientRect from "../../utils/boundingClientRect"; const mobileTop = ({ theme }) => theme.orbit.spaceXLarge; const popoverPadding = ({ theme }) => theme.orbit.spaceMedium; const StyledContentWrapper = styled.div.withConfig({ displayName: "ContentWrapper__StyledContentWrapper", componentId: "sc-4br52r-0" })(["", ""], ({ theme, windowHeight, actionsHeight, maxHeight }) => css(["overflow:auto;border-top-left-radius:", ";border-top-right-radius:", ";position:absolute;left:0;width:100%;background-color:", ";max-height:", "px;bottom:", "px;", ""], theme.orbit.spaceSmall, theme.orbit.spaceSmall, theme.orbit.paletteWhite, windowHeight && actionsHeight && windowHeight - actionsHeight - 32, actionsHeight || 0, mq.largeMobile(css(["max-height:", ";border-radius:", ";bottom:auto;left:auto;position:relative;"], maxHeight || "100%", theme.orbit.borderRadiusNormal)))); StyledContentWrapper.defaultProps = { theme: defaultTheme }; const StyledActions = styled.div.withConfig({ displayName: "ContentWrapper__StyledActions", componentId: "sc-4br52r-1" })(["", ""], ({ theme }) => css(["position:fixed;bottom:0;left:0;width:100%;box-sizing:border-box;padding:", ";padding-top:", ";background-color:", ";.orbit-button-primitive{width:100%;flex:1 1 auto;}", ";"], popoverPadding, theme.orbit.spaceSmall, theme.orbit.paletteWhite, mq.largeMobile(css(["position:relative;bottom:auto;left:auto;border-bottom-left-radius:", ";border-bottom-right-radius:3px;.orbit-button-primitive{width:auto;flex-grow:0;}"], theme.orbit.borderRadiusNormal)))); StyledActions.defaultProps = { theme: defaultTheme }; const StyledPopoverParent = styled.div.withConfig({ displayName: "ContentWrapper__StyledPopoverParent", componentId: "sc-4br52r-2" })(["", ""], ({ isInsideModal, width, shown, theme, transform, top, left, bottom, right, position, $zIndex }) => css(["position:fixed;bottom:0;left:0;right:0;height:auto;width:100%;z-index:1000;box-sizing:border-box;box-shadow:", ";background-color:", ";max-height:calc(100% - ", ");&:focus{outline:0;}", ""], theme.orbit.boxShadowRaisedReverse, theme.orbit.backgroundModal, mobileTop, mq.largeMobile(css(["top:", ";left:", ";bottom:", ";right:", ";transform:", ";transition:", ";position:", ";z-index:", ";width:", ";border-radius:", ";box-shadow:", ";opacity:", ";max-height:none;"], top, left, bottom, right, transform, transition(["opacity"], "fast", "ease-in-out"), position, isInsideModal ? "1000" : $zIndex, width ? `${width}` : "auto", theme.orbit.borderRadiusNormal, theme.orbit.boxShadowRaised, shown ? "1" : "0")))); StyledPopoverParent.defaultProps = { theme: defaultTheme }; const StyledPopoverPadding = styled.div.withConfig({ displayName: "ContentWrapper__StyledPopoverPadding", componentId: "sc-4br52r-3" })(["padding:", ";"], ({ noPadding }) => noPadding ? 0 : popoverPadding); StyledPopoverPadding.defaultProps = { theme: defaultTheme }; const StyledPopoverContent = styled.div.withConfig({ displayName: "ContentWrapper__StyledPopoverContent", componentId: "sc-4br52r-4" })(["", ""], ({ shownMobile }) => css(["transform:translateY(", ");will-change:transform;transition:", ";", ""], shownMobile ? "0%" : "100%", transition(["opacity, transform"], "fast", "ease-in-out"), mq.largeMobile(css(["transform:none;transition:none;"])))); StyledPopoverContent.defaultProps = { theme: defaultTheme }; const StyledOverlay = styled.div.withConfig({ displayName: "ContentWrapper__StyledOverlay", componentId: "sc-4br52r-5" })(["", ""], ({ theme, shown }) => css(["display:block;position:fixed;opacity:", ";top:0;left:0;right:0;width:100%;height:100%;background-color:", ";transition:", ";z-index:999;", ";"], shown ? "1" : "0", convertHexToRgba(theme.orbit.paletteInkDark, 60), transition(["opacity", "transform"], "normal", "ease-in-out"), mq.largeMobile(css(["display:none;"])))); StyledOverlay.defaultProps = { theme: defaultTheme }; const StyledPopoverClose = styled.div.withConfig({ displayName: "ContentWrapper__StyledPopoverClose", componentId: "sc-4br52r-6" })(["padding:", ";", ""], popoverPadding, mq.largeMobile(css(["display:none;visibility:hidden;padding-bottom:0;"]))); StyledPopoverClose.defaultProps = { theme: defaultTheme }; const PopoverContentWrapper = ({ children, onClose, zIndex = 710, labelClose, width, maxHeight, noFlip, offset = { top: 4, left: 0 }, referenceElement, dataTest, id, placement = PLACEMENTS.BOTTOM_START, noPadding, overlapped, shown, fixed, allowOverflow, lockScrolling = true, actions }) => { const [actionsHeight, setActionsHeight] = React.useState(null); const { isInsideModal } = React.useContext(ModalContext); const { isLargeMobile } = useMediaQuery(); const actionsRef = React.useRef(null); const content = React.useRef(null); const scrollingElementRef = React.useRef(null); useLockScrolling(scrollingElementRef, lockScrolling && !isLargeMobile); const popoverRef = React.useRef(null); const windowHeight = typeof window !== "undefined" ? window.innerHeight : 0; const { styles, update } = usePopper(referenceElement, popoverRef.current, { placement, strategy: fixed ? "fixed" : "absolute", modifiers: [{ name: "offset", enabled: !!offset, options: { offset: [offset.left, overlapped ? -Number(referenceElement?.offsetHeight) : offset.top] } }, { name: "flip", enabled: !noFlip }, { name: "preventOverflow", enabled: !allowOverflow }] }); const { popper } = styles; React.useEffect(() => { const timer = setTimeout(() => { if (popoverRef.current) { popoverRef.current.focus(); } }, 100); if (update) update(); if (actionsRef.current) { const { height } = boundingClientRect({ current: actionsRef.current }); setActionsHeight(height); } return () => { clearTimeout(timer); }; }, [update, actions, setActionsHeight]); useClickOutside(content, ev => { if (isLargeMobile) onClose(ev); }); const handleKeyDown = ev => { if (ev.keyCode === 27 && onClose) onClose(); }; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledOverlay, { shown: shown, onClick: onClose }), /*#__PURE__*/React.createElement(StyledPopoverParent, _extends({ width: width, ref: popoverRef, $zIndex: zIndex, tabIndex: 0, "data-test": dataTest, id: id, noPadding: noPadding, overlapped: overlapped, role: "tooltip", onKeyDown: handleKeyDown, fixed: fixed, shown: shown, isInsideModal: isInsideModal }, popper), /*#__PURE__*/React.createElement(StyledPopoverContent, { ref: content, shownMobile: shown }, /*#__PURE__*/React.createElement(StyledContentWrapper, { actionsHeight: actionsHeight, ref: scrollingElementRef, windowHeight: windowHeight, maxHeight: maxHeight }, /*#__PURE__*/React.createElement(StyledPopoverPadding, { noPadding: noPadding }, children)), actions ? /*#__PURE__*/React.createElement(StyledActions, { ref: actionsRef }, actions) : /*#__PURE__*/React.createElement(StyledPopoverClose, { ref: actionsRef }, /*#__PURE__*/React.createElement(Button, { type: "secondary", fullWidth: true, onClick: onClose }, labelClose))))); }; export default PopoverContentWrapper;