@cimpress/react-components
Version:
React components to support the MCP styleguide
206 lines (200 loc) • 6.46 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import React, { useMemo } from 'react';
import ReactDOM from 'react-dom';
import { css, cx } from '@emotion/css';
import cvar from '../theme/cvar';
import { BREAKPOINT_L, BREAKPOINT_M, BREAKPOINT_S } from '../breakpoint';
import { Close, BlockButton } from '../internal';
import { granite, white } from '../colors';
const defaultSizeStyles = css `
max-height: 72vh;
@media screen and (max-width: ${BREAKPOINT_S}) {
width: 100%;
}
@media screen and (min-width: calc(${BREAKPOINT_S} + 1px)) and (max-width: ${BREAKPOINT_M}) {
width: 58%;
}
@media screen and (min-width: calc(${BREAKPOINT_M} + 1px)) and (max-width: ${BREAKPOINT_L}) {
width: 50%;
}
@media screen and (min-width: calc(${BREAKPOINT_L} + 1px)) {
width: 38%;
}
`;
const largeSizeStyles = css `
max-height: 84vh;
@media screen and (max-width: ${BREAKPOINT_S}) {
width: 100%;
}
@media screen and (min-width: calc(${BREAKPOINT_S} + 1px)) and (max-width: ${BREAKPOINT_M}) {
width: 72%;
}
@media screen and (min-width: calc(${BREAKPOINT_M} + 1px)) and (max-width: ${BREAKPOINT_L}) {
width: 60%;
}
@media screen and (min-width: calc(${BREAKPOINT_L} + 1px)) {
width: 50%;
}
`;
const xLargeSizeStyles = css `
max-height: 96vh;
@media screen and (max-width: ${BREAKPOINT_S}) {
width: 100%;
}
@media screen and (min-width: calc(${BREAKPOINT_S} + 1px)) and (max-width: ${BREAKPOINT_M}) {
width: 84%;
}
@media screen and (min-width: calc(${BREAKPOINT_M} + 1px)) and (max-width: ${BREAKPOINT_L}) {
width: 72%;
}
@media screen and (min-width: calc(${BREAKPOINT_L} + 1px)) {
width: 72%;
}
`;
const modalDialogCss = css `
position: relative;
margin: 30px auto;
z-index: 1050;
`;
const modalBackdrop = css `
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1040;
background-color: #000;
opacity: 0.5;
`;
const modalCss = css `
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
overflow: hidden;
-webkit-overflow-scrolling: touch;
outline: 0;
&.modal-enter,
&.modal-enter-active,
&.modal-enter-done {
display: block;
}
&.modal-enter > .fade-in {
opacity: 0;
transition: opacity 0.15s linear;
}
&.modal-enter.modal-enter-active > .fade-in,
&.modal-enter-done > .fade-in {
opacity: 0.5;
}
`;
const modalTitle = css `
font-size: 24px;
line-height: 1.3em;
font-weight: normal;
flex-grow: 1;
`;
const modalCloseButton = css `
color: ${cvar('color-icon-secondary')};
height: ${cvar('spacing-48')};
vertical-align: middle;
margin-top: -10px;
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
-webkit-appearance: none;
appearance: none;
&:hover,
&:active {
color: shale;
opacity: 1;
}
`;
const modalHeaderCss = css `
background-color: ${cvar('color-background')};
border-bottom: none;
display: flex;
justify-content: flex-end;
flex-shrink: 0;
`;
const getModalInteractionCss = (status) => {
let color = white;
switch (status) {
case 'success': {
color = cvar('color-border-success');
break;
}
case 'danger': {
color = cvar('color-border-error');
break;
}
case 'warning': {
color = cvar('color-border-warning');
break;
}
case 'info': {
color = cvar('color-border-info');
break;
}
default: {
break;
}
}
return css `
border-top: 4px solid ${color};
`;
};
const modalContentCss = css `
background-color: ${cvar('color-background')};
border: 0;
box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
border-radius: 4px;
max-height: 90vh;
padding: ${cvar('spacing-24')};
`;
const modalBodyCss = css `
padding: ${cvar('spacing-24')} 0;
overflow-y: auto;
flex-grow: 1;
`;
const modalFooterCss = css `
border-top: none;
padding: ${cvar('spacing-24')} 0 0;
text-align: right;
`;
export const DisplayModal = (_a) => {
var { title, closeButton, footer, size = 'md', onRequestHide, closeOnOutsideClick = false, style, className, status, wrapperStyle } = _a, rest = __rest(_a, ["title", "closeButton", "footer", "size", "onRequestHide", "closeOnOutsideClick", "style", "className", "status", "wrapperStyle"]);
const modalStatusCss = useMemo(() => getModalInteractionCss(status), [status]);
const ModalHeader = (React.createElement("div", { className: modalHeaderCss },
React.createElement("div", { className: modalTitle }, title),
closeButton ? (React.createElement("button", { className: modalCloseButton, onClick: e => (onRequestHide ? onRequestHide(e) : null) },
React.createElement(Close, { width: "16px", color: granite.base, cropped: true, "aria-label": "Close modal" }))) : null));
const ModalFooter = footer && React.createElement("div", { className: modalFooterCss }, footer);
const modalNode = (React.createElement(BlockButton, { onClick: e => e.stopPropagation(), onKeyDown: e => e.stopPropagation(), className: modalCss, tabIndex: -1 },
React.createElement("div", { className: cx('crc-modal', modalDialogCss, defaultSizeStyles, {
[largeSizeStyles]: size === 'lg',
[xLargeSizeStyles]: size === 'xl',
}, className), style: Object.assign({}, style) },
React.createElement("div", Object.assign({ className: cx(modalContentCss, modalStatusCss) }, rest),
ModalHeader,
React.createElement("div", { className: modalBodyCss }, rest.children),
ModalFooter)),
React.createElement(BlockButton, { tabIndex: -1, className: cx(modalBackdrop, 'fade-in'), onClick: (e) => (closeOnOutsideClick && onRequestHide ? onRequestHide(e) : null) })));
return ReactDOM.createPortal(modalNode, document.body);
};
//# sourceMappingURL=Modal.js.map