UNPKG

@onehat/ui

Version:
204 lines (194 loc) 5.42 kB
import { forwardRef, useState, useRef } from 'react'; import { Box, Icon, Modal, ModalBackdrop, ModalHeader, ModalContent, ModalCloseButton, ModalBody, ModalFooter, Text, } from '@project-components/Gluestack'; import clsx from 'clsx'; import Button from '../Buttons/Button.js'; import Panel from '../Panel/Panel.js'; import Footer from '../Layout/Footer.js'; import useAdjustedWindowSize from '../../Hooks/useAdjustedWindowSize.js'; import testProps from '../../Functions/testProps.js'; import _ from 'lodash'; // This HOC enables usage of more complex dialogs in the wrapped component. // Use withAlert for simple alerts, confirmations, and info dialogs. export default function withModal(WrappedComponent) { return forwardRef((props, ref) => { if (props.disableWithModal || props.alreadyHasWithModal) { return <WrappedComponent {...props} ref={ref} />; } const [title, setTitle] = useState(''), [canClose, setCanClose] = useState(true), [includeCancel, setIncludeCancel] = useState(false), [isModalShown, setIsModalShown] = useState(false), [h, setHeight] = useState(), [w, setWidth] = useState(), [onOk, setOnOk] = useState(), [okBtnLabel, setOkBtnLabel] = useState(), [onYes, setOnYes] = useState(), [onNo, setOnNo] = useState(), [onCancel, setOnCancel] = useState(), [customButtons, setCustomButtons] = useState(), [body, setBody] = useState(), [whichModal, setWhichModal] = useState(), [testID, setTestID] = useState('Modal'), autoFocusRef = useRef(null), cancelRef = useRef(null), [windowWidth, windowHeight] = useAdjustedWindowSize(w, h), hideModal = () => { setIsModalShown(false); }, showModal = (args) => { let { title = null, body = null, canClose = false, includeCancel = false, onCancel = null, onOk = null, okBtnLabel = null, onYes = null, onNo = null, customButtons = null, h = null, w = null, whichModal = null, testID = null, formProps = null, // deprecated } = args; if (formProps) { // deprecated formProps bc we were getting circular dependencies throw new Error('withModal: formProps is deprecated. Instead, insert the <Form> in "body" directly from the component that called showModal.'); } if (!body) { throw new Error('withModal: body is required for showModal'); } setTitle(title); setBody(body); setCanClose(canClose); setIncludeCancel(includeCancel); setOnCancel(() => onCancel); setOnOk(onOk ? () => onOk : null); setOkBtnLabel(okBtnLabel || 'OK'); setOnYes(onYes ? () => onYes : null); setOnNo(onNo ? () => onNo : null); setCustomButtons(customButtons); setHeight(h); // || 250 setWidth(w); // || 400 setWhichModal(whichModal); setIsModalShown(true); if (testID) { setTestID(testID); } }, updateModalBody = (newBody) => { setBody(newBody); }; let modalBody, buttons = []; if (isModalShown) { // assemble buttons if (includeCancel) { buttons.push(<Button {...testProps('cancelBtn')} key="cancelBtn" onPress={onCancel || hideModal} colorScheme="coolGray" ref={cancelRef} className="mr-2" text="Cancel" variant="outline" // or unstyled />); } if (onNo) { buttons.push(<Button {...testProps('noBtn')} key="noBtn" onPress={onNo} className="text-grey-800 mr-2" text="No" variant="outline" />); } if (onOk) { buttons.push(<Button {...testProps('okBtn')} key="okBtn" ref={autoFocusRef} onPress={onOk} text={okBtnLabel} className="text-white" />); } if (onYes) { buttons.push(<Button {...testProps('yesBtn')} key="yesBtn" ref={autoFocusRef} onPress={onYes} text="Yes" className="text-white" />); } if (customButtons) { _.each(customButtons, (button) => { buttons.push(button); }); } // assemble body modalBody = body; if (h || w || title) { let footer = null; if (buttons && buttons.length > 0) { footer = <Footer className={clsx( 'justify-end', 'py-2', 'pr-4', 'bg-grey-100', )} >{buttons}</Footer>; } modalBody = <Panel title={title} isCollapsible={false} className="withModal-Panel bg-white" h={h > windowHeight ? windowHeight : h} w={w > windowWidth ? windowWidth : w} isWindow={true} disableAutoFlex={true} onClose={canClose ? hideModal : null} footer={footer} isScrollable={true} >{modalBody}</Panel> } } return <> <WrappedComponent {...props} disableWithModal={false} alreadyHasWithModal={true} ref={ref} showModal={showModal} hideModal={onCancel || hideModal} updateModalBody={updateModalBody} isModalShown={isModalShown} whichModal={whichModal} /> {isModalShown && <Modal isOpen={true} onClose={onCancel || (canClose ? hideModal : null)} className="withModal-Modal" {...testProps(testID)} > <ModalBackdrop className="withModal-ModalBackdrop" /> {modalBody} </Modal>} </>; }); }