@drivy/cobalt
Version:
Opinionated design system for Drivy's projects.
56 lines (53 loc) • 3.52 kB
JavaScript
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import cx from 'classnames';
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import { getA11yOnClick } from '../../helpers/index.js';
import useBreakpoint from '../../hooks/useBreakpoint.js';
import Button from '../Buttons/Button/index.js';
import '../Icon/index.js';
import { Fixed } from '../Layout/Surfaces/index.js';
import Modal from '../Modal/index.js';
import CloseIcon from '../Icon/__generated__/CloseIcon.js';
const SidepanelFooter = ({ children, className }) => {
return (jsx("div", { className: cx("c-p-sm c-border-t c-border-outline", className), children: children }));
};
// Memoized component to not render content when the panel is collapsing
function _SidepanelContent({ title, close, children }) {
return (jsxs(Fragment, { children: [title && (jsxs("div", { className: "c-flex c-gap-sm c-items-start c-px-sm c-py-md c-border-b c-border-outline", children: [jsx("div", { className: "c-text-title-md c-flex-1", children: title }), close && (jsx(Button, { className: "cobalt-sidepanel__close", icon: jsx(CloseIcon, {}), text: true, ...getA11yOnClick(close) }))] })), children] }));
}
function areSidepanelContentEqual(_prevProps, nextProps) {
return !nextProps.isOpen;
}
const SidepanelContent = React.memo(_SidepanelContent, areSidepanelContentEqual);
SidepanelContent.displayName = "SidepanelContent";
// Only for the API, render nothing
const SidepanelFooterAPI = (_props) => null;
const isSidepanelFooterAPIComponent = (component) => React.isValidElement(component) && component.type === SidepanelFooterAPI;
const _Sidepanel = ({ isOpen, title, close, withDesktopOverlay, onPointerDownOutside, width = 420, children, }) => {
const { isMobile } = useBreakpoint();
// To display box-shadow when visible. We can't rely on isOpen because it triggers the collapse animation and so the box shadow would not be set during the transition
const [isPanelVisible, setIsPanelVisible] = useState(false);
useEffect(() => {
isOpen && setIsPanelVisible(true);
}, [isOpen]);
const sidepanelFooter = React.Children.toArray(children).find((c) => isSidepanelFooterAPIComponent(c));
let footer = null;
if (React.isValidElement(sidepanelFooter)) {
footer = isMobile ? (jsx(Modal.Footer, { ...sidepanelFooter.props })) : (jsx(SidepanelFooter, { ...sidepanelFooter.props }));
}
return isMobile ? (jsxs(Modal, { "aria-label": "Sidepanel", isOpen: isOpen, bodySpacing: false, close: close, title: title, fullScreen: true, children: [children, footer] })) : (ReactDOM.createPortal(jsxs(Fragment, { children: [jsx("div", { className: cx("cobalt-sidepanel", {
"cobalt-sidepanel--show": isOpen,
"cobalt-sidepanel--visible": isPanelVisible,
}), onTransitionEnd: () => {
!isOpen && setIsPanelVisible(false);
}, children: jsx(Fixed, { width: width, isFullHeight: true, children: jsxs(SidepanelContent, { isOpen: isOpen, title: title, close: close, children: [children, footer] }) }) }), withDesktopOverlay && (jsx("div", { className: "cobalt-sidepanel-overlay", ...(onPointerDownOutside
? getA11yOnClick(onPointerDownOutside)
: {}) }))] }), document.body));
};
_Sidepanel.displayName = "Sidepanel";
const Sidepanel = Object.assign(_Sidepanel, {
Footer: SidepanelFooterAPI,
});
export { Sidepanel };
//# sourceMappingURL=index.js.map