ohif-viewer/platform/ui/src/utils/ModalProvider.js

123 lines
3.1 KiB
JavaScript
Raw Normal View History

2019-11-14 14:19:33 +01:00
import React, {
useState,
createContext,
useContext,
useEffect,
useCallback,
2019-11-14 14:19:33 +01:00
} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
const ModalContext = createContext(null);
const { Provider } = ModalContext;
export const useModal = () => useContext(ModalContext);
2019-11-14 14:19:33 +01:00
const ModalProvider = ({ children, modal: Modal, service }) => {
const DEFAULT_OPTIONS = {
component: null /* The component instance inside the modal. */,
header: null /* The content inside the modal header. */,
footer: null /* The content inside the modal footer. */,
backdrop: false /* Should the modal render a backdrop overlay. */,
keyboard: false /* Modal is dismissible via the esc key. */,
show: true /* Make the Modal visible or hidden. */,
closeButton: true /* Should the modal body render the close button. */,
title: null /* Should the modal render the title independently of the body content. */,
customClassName: null /* The custom class to style the modal. */,
};
const [options, setOptions] = useState(DEFAULT_OPTIONS);
2019-11-14 14:19:33 +01:00
/**
* Sets the implementation of a modal service that can be used by extensions.
*
* @returns void
*/
useEffect(() => {
if (service) {
service.setServiceImplementation({ hide, show });
}
2019-11-14 14:19:33 +01:00
}, [hide, service, show]);
/**
* Show the modal and override its configuration props.
*
* @returns void
*/
const show = useCallback(
(component, props = {}) =>
setOptions(Object.assign({}, options, props, { component })),
[options]
2019-11-14 15:42:25 +01:00
);
/**
* Hide the modal and set its properties to default.
*
* @returns void
*/
const hide = useCallback(() => setOptions(DEFAULT_OPTIONS), [
DEFAULT_OPTIONS,
]);
2019-11-14 21:40:37 +01:00
const { component: Component } = options;
return (
<Provider value={{ show, hide }}>
{options.component && (
<Modal
className={classNames(
options.customClassName,
options.component.className
)}
backdrop={options.backdrop}
keyboard={options.keyboard}
show={options.show}
title={options.title}
closeButton={options.closeButton}
footer={options.footer}
header={options.header}
2019-11-14 21:57:44 +01:00
onHide={hide}
>
2019-11-14 21:40:37 +01:00
<Component {...options} show={show} hide={hide} />
</Modal>
)}
{children}
</Provider>
);
};
ModalProvider.defaultProps = {
service: null,
};
ModalProvider.propTypes = {
2019-11-14 15:42:25 +01:00
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]).isRequired,
modal: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
PropTypes.func,
]).isRequired,
2019-11-14 14:19:33 +01:00
service: PropTypes.shape({
setServiceImplementation: PropTypes.func,
}),
};
/**
* Higher Order Component to use the modal methods through a Class Component.
*
* @returns
*/
export const withModal = Component => {
return function WrappedComponent(props) {
2019-11-14 21:25:09 +01:00
const { show, hide } = useModal();
return <Component {...props} modal={{ show, hide }} />;
};
};
export default ModalProvider;
export const ModalConsumer = ModalContext.Consumer;