wix-style-react
Version:
wix-style-react
135 lines • 7.76 kB
JavaScript
import React, { useEffect } from 'react';
import { generateDataAttr } from '../utils/generateDataAttr';
import PropTypes from 'prop-types';
import throttle from 'lodash/throttle';
import Header from './HeaderLayout';
import Footer from './FooterLayout';
import { st, classes } from './MessageBoxFunctionalLayout.st.css';
import { dataHooks } from './constants';
import { WixStyleReactContext } from '../WixStyleReactProvider/context';
/** MessageBoxFunctionalLayout */
const MessageBoxFunctionalLayout = ({ theme = 'blue', buttonsHeight = 'small', disableCancel = false, disableConfirmation = false, noBodyPadding = false, fullscreen = false, withEmptyState = false, dataHook, title, onCancel, onOk, onClose, confirmText, confirmPrefixIcon, confirmSuffixIcon, cancelText, cancelPrefixIcon, cancelSuffixIcon, hideFooter, footerBottomChildren, closeButton, width, margin, sideActions, withFooterAction, noPadding, image, maxHeight, children, }) => {
const [state, setState] = React.useState({
hasScroll: false,
scrolledToBottom: false,
});
const ref = React.useRef(null);
const handleMessageBoxScroll = throttle(() => {
const scrolledToBottom = ref.current.scrollTop + ref.current.clientHeight ===
ref.current.scrollHeight;
if (scrolledToBottom !== state.scrolledToBottom) {
setState({ scrolledToBottom });
}
}, 16);
useEffect(() => {
if (ref && ref.current.scrollHeight > ref.current.clientHeight) {
ref.current.addEventListener('scroll', handleMessageBoxScroll);
setState({ hasScroll: true });
}
return () => {
handleMessageBoxScroll.cancel();
// TODO: fix ESLint error
// eslint-disable-next-line react-hooks/exhaustive-deps
ref.current.removeEventListener('scroll', handleMessageBoxScroll);
};
// TODO: fix ESLint error
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ref]);
const Content = ({ newColorsBranding }) => {
const { hasScroll, scrolledToBottom } = state;
const ContentLayout = () => (React.createElement("div", { ref: ref, "data-hook": dataHooks.content, className: st(classes.content, {
scrollable: typeof maxHeight !== 'undefined',
noPadding: noBodyPadding,
newColorsBranding,
fullscreenBody: fullscreen,
noFooter: hideFooter,
footerBorder: hasScroll && !scrolledToBottom,
withEmptyState,
}), style: { maxHeight } }, children));
if (image && !withEmptyState && !newColorsBranding) {
return (React.createElement("div", { className: classes.contentWithImage },
React.createElement("div", { className: st(classes.image, {
withFooterAction,
noPadding,
}) }, image),
React.createElement(ContentLayout, null)));
}
return React.createElement(ContentLayout, null);
};
return (React.createElement(WixStyleReactContext.Consumer, null, ({ newColorsBranding }) => (React.createElement("div", { "data-hook": dataHook, className: st(classes.root, {
fullscreen,
newColorsBranding: newColorsBranding && !image,
hasImage: newColorsBranding && !!image,
}), style: { width, margin }, ...generateDataAttr({ noBodyPadding, theme }, [
'noBodyPadding',
'theme',
]) },
React.createElement("div", { className: st(classes.topAreaContainer, { newColorsBranding }) },
newColorsBranding && image ? (React.createElement("div", { className: classes.imageContainer }, image)) : null,
React.createElement("div", { className: st(classes.contentAreaContainer, {
newColorsBranding,
}) },
React.createElement(Header, { title: title, onCancel: onClose ? onClose : onCancel, theme: !newColorsBranding ? theme : 'newColorsBranding', closeButton: closeButton, size: newColorsBranding ? 'large' : 'medium', newColorsBranding: newColorsBranding }),
React.createElement(Content, { newColorsBranding: newColorsBranding }))),
!hideFooter ? (React.createElement(Footer, { newColorsBranding: newColorsBranding, bottomChildren: footerBottomChildren, enableCancel: !disableCancel, enableOk: !disableConfirmation, buttonsHeight: buttonsHeight, confirmText: confirmText, confirmPrefixIcon: confirmPrefixIcon, confirmSuffixIcon: confirmSuffixIcon, cancelText: cancelText, cancelPrefixIcon: cancelPrefixIcon, cancelSuffixIcon: cancelSuffixIcon, onCancel: onCancel, onOk: onOk, theme: theme, sideActions: sideActions })) : null))));
};
MessageBoxFunctionalLayout.displayName = 'MessageBoxFunctionalLayout';
MessageBoxFunctionalLayout.propTypes = {
/** applied as data-hook HTML attribute that can be used to create driver in testing */
dataHook: PropTypes.string,
/** Hides the footer that contains the action buttons */
hideFooter: PropTypes.bool,
/** Defines the main action button text */
confirmText: PropTypes.node,
/** Add a prefix icon for the main action button */
confirmPrefixIcon: PropTypes.element,
/** Add a suffix icon for the main action button */
confirmSuffixIcon: PropTypes.element,
/** Defines the secondary action button text */
cancelText: PropTypes.node,
/** Add a prefix icon for the secondary action button */
cancelPrefixIcon: PropTypes.element,
/** Add a suffix icon for the secondary action button */
cancelSuffixIcon: PropTypes.element,
/** modal theme color */
theme: PropTypes.oneOf(['red', 'blue', 'purple']),
/** Called when the main action (confirm) is clicked */
onOk: PropTypes.func,
/** Called when the secondary action (cancel) is clicked */
onCancel: PropTypes.func,
/** Called when the close button is clicked */
onClose: PropTypes.func,
/** Specify exact width */
width: PropTypes.string,
/** Specify exact margin. Use to fine tune position inside other elements.
* When used inside `<Modal>`, beware that `<Modal>` is a flex container, therefore specific flex item CSS rules apply for this margin. */
margin: PropTypes.string,
/** Defines the modals's header title */
title: PropTypes.node,
/** The content to be displayed. can be text or some node */
children: PropTypes.any,
/** Max height. When supplied - will allow internal scroll to the component */
maxHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/** Defines the buttons size */
buttonsHeight: PropTypes.oneOf(['tiny', 'small', 'medium', 'large']),
/** Show/hide the close button */
closeButton: PropTypes.bool,
/** Defines the secondary action button */
disableCancel: PropTypes.bool,
/** Defines the main action button */
disableConfirmation: PropTypes.bool,
/** Removes the content padding. Used in custom modal that defines it's own padding*/
noBodyPadding: PropTypes.bool,
/** A render slot to display a foot note */
footerBottomChildren: PropTypes.node,
/** Stretches the component to a full screen mode (with some padding) */
fullscreen: PropTypes.bool,
/** Changes the internal padding to be used with `<EmptyState/>` component */
withEmptyState: PropTypes.bool,
/** Used to display some side component in the footer, for example `<Checkbox/>` */
sideActions: PropTypes.node,
/** Used to display an illustration on the left side */
image: PropTypes.node,
};
export default MessageBoxFunctionalLayout;
//# sourceMappingURL=MessageBoxFunctionalLayout.js.map