@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
JavaScript
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;