All files / app/ui/modal Modal.tsx

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 10383x 83x 83x 83x     83x 83x                               83x 186x 186x 186x 186x 186x 186x 186x 186x 186x 186x   186x 1x     186x                                                                                                                           83x  
import classNames from 'classnames';
import { noop } from 'lodash';
import React, { useCallback, FunctionComponent, KeyboardEvent, MouseEvent, ReactNode } from 'react';
import ReactModal from 'react-modal';
import { Omit } from 'utility-types';
 
import { preventDefault } from '../../common/dom';
import { IconClose } from '../icon';
 
export type ModalProps = Omit<
    ReactModal.Props,
    'bodyOpenClassName' | 'className' | 'closeTimeoutMS' | 'overlayClassName'
> & {
    children: ReactNode;
    closeButtonLabel?: string | ReactNode;
    footer?: ReactNode;
    header?: ReactNode;
    additionalHeaderClassName?: string;
    additionalBodyClassName?: string;
    additionalModalClassName?: string;
    shouldShowCloseButton?: boolean;
};
 
const Modal: FunctionComponent<ModalProps> = ({
    children,
    closeButtonLabel = 'Close',
    footer,
    header,
    additionalHeaderClassName,
    additionalBodyClassName,
    additionalModalClassName,
    onRequestClose = noop,
    shouldShowCloseButton = false,
    ...rest
}) => {
    const handleClose = useCallback((event: MouseEvent | KeyboardEvent) => {
        onRequestClose(event);
    }, [onRequestClose]);
 
    return <ReactModal
        { ...rest }
        ariaHideApp={ process.env.NODE_ENV !== 'test' }
        bodyOpenClassName="has-activeModal"
        className={ {
            base: classNames(
                'modal optimizedCheckout-contentPrimary',
                additionalModalClassName
            ),
            afterOpen: 'modal--afterOpen',
            beforeClose: 'modal--beforeClose',
        } }
        closeTimeoutMS={ 200 }
        onRequestClose={ onRequestClose }
        overlayClassName={ {
            base: 'modalOverlay',
            afterOpen: 'modalOverlay--afterOpen',
            beforeClose: 'modalOverlay--beforeClose',
        } }
        shouldCloseOnOverlayClick={ false }
    >
        <div
            className={ classNames(
                'modal-header',
                additionalHeaderClassName
            ) }
        >
            { header }
 
            { shouldShowCloseButton && <a
                className="modal-close"
                data-test="modal-close-button"
                href="#"
                onClick={ preventDefault(handleClose) }
            >
                { closeButtonLabel && <span className="is-srOnly">
                    { closeButtonLabel }
                </span> }
 
                <IconClose />
            </a> }
        </div>
 
        <div
            className={ classNames(
                'modal-body',
                additionalBodyClassName
            ) }
            data-test="modal-body"
        >
            { children }
        </div>
 
        { footer && <div
            className="modal-footer"
            data-test="modal-footer"
        >
            { footer }
        </div> }
    </ReactModal>;
};
 
export default Modal;