@wix/design-system
Version:
@wix/design-system
179 lines • 9.08 kB
JavaScript
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import ReactModal from 'react-modal';
import defaultTo from 'lodash/defaultTo';
import { st, classes } from './Modal.st.css.js';
import { ariaDescribedBy, dataHooks, flexPositions, labels } from './constants';
import { ZIndex } from '../common/ZIndex';
import uniqueId from 'lodash/uniqueId';
import WixDesignSystemProvider from '../WixDesignSystemProvider';
import { ariaLabels } from '../common/accessibility/ariaLabels';
import CloseButton from '../CloseButton';
import IconButton from '../IconButton';
import { ArrowLeft, ArrowRight } from '@wix/wix-ui-icons-common';
import Tooltip from '../Tooltip';
class Modal extends PureComponent {
constructor(props) {
super(props);
this.handleOverlayClick = (event) => {
const { shouldCloseOnOverlayClick, onRequestClose } = this.props;
if (shouldCloseOnOverlayClick &&
event.target.id === this.CHILDREN_WRAPPER_DIV_ID &&
onRequestClose) {
onRequestClose();
}
};
this.renderCloseButton = () => {
return (React.createElement(CloseButton, { dataHook: dataHooks.modalCloseButton, className: classes.closeButton, onClick: this.props.onRequestClose, size: "large", skin: "light", "aria-label": labels.close }));
};
this.renderNavigationControls = () => {
const DIRECTIONS = { prev: 'prev', next: 'next' };
const TOOLTIP_GAP = 9;
const { showNavigationPreviousButton, showNavigationNextButton, onNavigationClickPrevious, onNavigationClickNext, navigationPreviousLabel, navigationNextLabel, } = this.props;
const buildButton = (dir, className) => {
const isPrevious = dir === DIRECTIONS.prev;
return (React.createElement(IconButton, { className: className, priority: "secondary", size: "large", onClick: isPrevious ? onNavigationClickPrevious : onNavigationClickNext, dataHook: isPrevious
? dataHooks.navigationPrevButton
: dataHooks.navigationNextButton }, isPrevious ? React.createElement(ArrowLeft, null) : React.createElement(ArrowRight, null)));
};
return (React.createElement(React.Fragment, null,
showNavigationPreviousButton &&
(navigationPreviousLabel ? (React.createElement(Tooltip, { className: classes.navPrev, content: navigationPreviousLabel, moveBy: { y: TOOLTIP_GAP }, "aria-describedby": ariaDescribedBy.navigationPrev, dataHook: dataHooks.navigationPrevTooltip }, buildButton(DIRECTIONS.prev))) : (buildButton(DIRECTIONS.prev, classes.navPrev))),
showNavigationNextButton &&
(navigationNextLabel ? (React.createElement(Tooltip, { className: classes.navNext, content: navigationNextLabel, moveBy: { y: TOOLTIP_GAP }, "aria-describedby": ariaDescribedBy.navigationNext, dataHook: dataHooks.navigationNextTooltip }, buildButton(DIRECTIONS.next))) : (buildButton(DIRECTIONS.next, classes.navNext)))));
};
this.CHILDREN_WRAPPER_DIV_ID = uniqueId('wsr-modal');
}
render() {
const { dataHook, horizontalPosition, verticalPosition, height, scrollableContent, borderRadius, zIndex, scrollable, isOpen, shouldCloseOnOverlayClick, shouldDisplayCloseButton, onRequestClose, onAfterClose, onAfterOpen, contentLabel, closeTimeoutMS, children, appElement, overlayPosition, parentSelector, screen, showNavigationPreviousButton, showNavigationNextButton, onNavigationClickPrevious, onNavigationClickNext, } = this.props;
let { maxHeight } = this.props;
const justifyContent =
// @ts-expect-error Typescript doesn't know about Modal.defaultProps
flexPositions[horizontalPosition];
const alignItems =
// @ts-expect-error Typescript doesn't know about Modal.defaultProps
flexPositions[verticalPosition];
maxHeight = scrollableContent && maxHeight === 'auto' ? '100vh' : maxHeight;
const modalStyles = {
overlay: {
// Overriding defaults
position: overlayPosition,
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: defaultTo(zIndex, ZIndex.modal),
backgroundColor: undefined, // undefined disables the property, use css instead
// Overriding defaults - END
display: 'flex',
justifyContent,
alignItems,
overflowY: scrollable ? 'auto' : 'hidden',
},
content: {
// Overriding defaults
border: 'none',
overflowY: scrollableContent ? 'auto' : 'initial',
overflowX: scrollableContent ? 'hidden' : 'initial',
height,
maxHeight,
width: '100%',
// stylelint-disable-line
WebkitOverflowScrolling: 'touch',
outline: 'none',
borderRadius,
padding: '0px',
// Overriding defaults - END
backgroundColor: 'transparent',
marginBottom: '0px',
position: 'relative',
},
};
if (appElement) {
ReactModal.setAppElement(appElement);
}
else {
ReactModal.setAppElement('body');
}
return (React.createElement("div", { "data-hook": dataHook, onKeyDown: e => {
const arrows = {
left: 'ArrowLeft',
right: 'ArrowRight',
};
if (e && e.key === arrows.left) {
showNavigationPreviousButton &&
onNavigationClickPrevious &&
onNavigationClickPrevious();
}
if (e && e.key === arrows.right) {
showNavigationNextButton &&
onNavigationClickNext &&
onNavigationClickNext();
}
} },
React.createElement(ReactModal, { portalClassName: st(classes.root, { scrollable }, `portal portal-${dataHook}`), isOpen: isOpen, shouldCloseOnOverlayClick: shouldCloseOnOverlayClick, onRequestClose: onRequestClose, onAfterOpen: onAfterOpen, onAfterClose: onAfterClose, style: modalStyles, className: classes.modal, closeTimeoutMS: closeTimeoutMS, parentSelector: parentSelector, ariaHideApp: false, contentLabel: contentLabel, aria: {
labelledby: ariaLabels.labelledBy,
describedby: ariaLabels.describedBy,
} },
React.createElement(WixDesignSystemProvider, null,
isOpen && shouldDisplayCloseButton && this.renderCloseButton(),
React.createElement("div", { "data-scrollable": scrollable || null, id: this.CHILDREN_WRAPPER_DIV_ID, className: st(classes.childrenContainer, {
screen,
}), onClick: this.handleOverlayClick },
(showNavigationPreviousButton || showNavigationNextButton) &&
this.renderNavigationControls(),
children)))));
}
}
Modal.propTypes = {
dataHook: PropTypes.string,
isOpen: PropTypes.bool.isRequired,
borderRadius: PropTypes.number,
contentLabel: PropTypes.string,
children: PropTypes.any,
zIndex: PropTypes.number,
shouldCloseOnOverlayClick: PropTypes.bool,
shouldDisplayCloseButton: PropTypes.bool,
onRequestClose: PropTypes.func,
onAfterOpen: PropTypes.func,
onAfterClose: PropTypes.func,
horizontalPosition: PropTypes.oneOf(['start', 'center', 'end']),
verticalPosition: PropTypes.oneOf(['start', 'center', 'end']),
closeTimeoutMS: PropTypes.number,
scrollable: PropTypes.bool,
scrollableContent: PropTypes.bool,
maxHeight: PropTypes.string,
height: PropTypes.string,
overlayPosition: PropTypes.oneOf([
'static',
'relative',
'absolute',
'fixed',
'sticky',
]),
parentSelector: PropTypes.func,
appElement: PropTypes.string,
screen: PropTypes.oneOf(['full', 'desktop', 'mobile']),
showNavigationPreviousButton: PropTypes.bool,
showNavigationNextButton: PropTypes.bool,
onNavigationClickPrevious: PropTypes.func,
onNavigationClickNext: PropTypes.func,
navigationPreviousLabel: PropTypes.string,
navigationNextLabel: PropTypes.string,
};
Modal.defaultProps = {
borderRadius: 0,
shouldCloseOnOverlayClick: false,
shouldDisplayCloseButton: false,
horizontalPosition: 'center',
verticalPosition: 'center',
closeTimeoutMS: 500,
scrollable: true,
scrollableContent: false,
height: '100%',
maxHeight: 'auto',
overlayPosition: 'fixed',
screen: 'desktop',
};
export default Modal;
//# sourceMappingURL=Modal.js.map