| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 | 
							- /* eslint-disable react/destructuring-assignment, prefer-const, @typescript-eslint/no-unused-vars */
 
- import React, { CSSProperties, LegacyRef, ReactNode } from 'react';
 
- import { cssClasses, strings } from '@douyinfe/semi-foundation/modal/constants';
 
- import Button from '../button';
 
- import ModalFoundation, { ModalAdapter, ModalProps, ModalState } from '@douyinfe/semi-foundation/modal/modalFoundation';
 
- import ModalContent from './ModalContent';
 
- import Portal from '../_portal';
 
- import LocaleConsumer from '../locale/localeConsumer';
 
- import cls from 'classnames';
 
- import PropTypes from 'prop-types';
 
- import { noop } from 'lodash';
 
- import '@douyinfe/semi-foundation/modal/modal.scss';
 
- import BaseComponent from '../_base/baseComponent';
 
- import confirm, { withConfirm, withError, withInfo, withSuccess, withWarning } from './confirm';
 
- import { Locale } from '../locale/interface';
 
- import useModal from './useModal';
 
- import { ButtonProps } from '../button/Button';
 
- import { MotionObject } from "@douyinfe/semi-foundation/utils/type";
 
- export const destroyFns: any[] = [];
 
- export type ConfirmType = 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
 
- export type Directions = 'ltr' | 'rtl';
 
- export interface ModalReactProps extends ModalProps {
 
-     cancelButtonProps?: ButtonProps;
 
-     children?: React.ReactNode;
 
-     okButtonProps?: ButtonProps;
 
-     bodyStyle?: CSSProperties;
 
-     maskStyle?: CSSProperties;
 
-     style?: CSSProperties;
 
-     icon?: ReactNode;
 
-     closeIcon?: ReactNode;
 
-     title?: ReactNode;
 
-     content?: ReactNode;
 
-     footer?: ReactNode;
 
-     header?: ReactNode;
 
-     onCancel?: (e: React.MouseEvent) => void | Promise<any>;
 
-     onOk?: (e: React.MouseEvent) => void | Promise<any>;
 
- }
 
- export {
 
-     ModalState
 
- };
 
- class Modal extends BaseComponent<ModalReactProps, ModalState> {
 
-     static propTypes = {
 
-         mask: PropTypes.bool,
 
-         closable: PropTypes.bool,
 
-         centered: PropTypes.bool,
 
-         visible: PropTypes.bool,
 
-         width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
 
-         height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
 
-         confirmLoading: PropTypes.bool,
 
-         cancelLoading: PropTypes.bool,
 
-         okText: PropTypes.string,
 
-         okType: PropTypes.string,
 
-         cancelText: PropTypes.string,
 
-         maskClosable: PropTypes.bool,
 
-         onCancel: PropTypes.func,
 
-         onOk: PropTypes.func,
 
-         afterClose: PropTypes.func,
 
-         okButtonProps: PropTypes.object,
 
-         cancelButtonProps: PropTypes.object,
 
-         style: PropTypes.object,
 
-         className: PropTypes.string,
 
-         maskStyle: PropTypes.object,
 
-         bodyStyle: PropTypes.object,
 
-         zIndex: PropTypes.number,
 
-         title: PropTypes.node,
 
-         icon: PropTypes.node,
 
-         header: PropTypes.node,
 
-         footer: PropTypes.node,
 
-         hasCancel: PropTypes.bool,
 
-         motion: PropTypes.oneOfType([PropTypes.bool, PropTypes.func, PropTypes.object]),
 
-         children: PropTypes.node,
 
-         getPopupContainer: PropTypes.func,
 
-         getContainerContext: PropTypes.func,
 
-         maskFixed: PropTypes.bool,
 
-         closeIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
 
-         closeOnEsc: PropTypes.bool,
 
-         size: PropTypes.oneOf(strings.SIZE),
 
-         keepDOM: PropTypes.bool,
 
-         lazyRender: PropTypes.bool,
 
-         direction: PropTypes.oneOf(strings.directions),
 
-         fullScreen: PropTypes.bool,
 
-     };
 
-     static defaultProps = {
 
-         zIndex: 1000,
 
-         motion: true,
 
-         mask: true,
 
-         centered: false,
 
-         closable: true,
 
-         visible: false,
 
-         confirmLoading: false,
 
-         cancelLoading: false,
 
-         okType: 'primary',
 
-         maskClosable: true,
 
-         hasCancel: true,
 
-         onCancel: noop,
 
-         onOk: noop,
 
-         afterClose: noop,
 
-         maskFixed: false,
 
-         closeOnEsc: true,
 
-         size: 'small',
 
-         keepDOM: false,
 
-         lazyRender: true,
 
-         fullScreen: false,
 
-     };
 
-     static useModal = useModal;
 
-     foundation: ModalFoundation;
 
-     private readonly modalRef: LegacyRef<ModalContent>;
 
-     private bodyOverflow: string;
 
-     private scrollBarWidth: number;
 
-     private originBodyWith: string;
 
-     private _active: boolean;
 
-     constructor(props: ModalReactProps) {
 
-         super(props);
 
-         this.state = {
 
-             hidden: !props.visible,
 
-             isFullScreen: props.fullScreen,
 
-         };
 
-         this.foundation = new ModalFoundation(this.adapter);
 
-         this.modalRef = React.createRef();
 
-         this.bodyOverflow = '';
 
-         this.scrollBarWidth = 0;
 
-         this.originBodyWith = '100%';
 
-     }
 
-     get adapter(): ModalAdapter {
 
-         return {
 
-             ...super.adapter,
 
-             getProps: () => this.props,
 
-             disabledBodyScroll: () => {
 
-                 const { getPopupContainer } = this.props;
 
-                 this.bodyOverflow = document.body.style.overflow || '';
 
-                 if (!getPopupContainer && this.bodyOverflow !== 'hidden') {
 
-                     document.body.style.overflow = 'hidden';
 
-                     document.body.style.width = `calc(${this.originBodyWith || '100%'} - ${this.scrollBarWidth}px)`;
 
-                 }
 
-             },
 
-             enabledBodyScroll: () => {
 
-                 const { getPopupContainer } = this.props;
 
-                 if (!getPopupContainer && this.bodyOverflow !== 'hidden') {
 
-                     document.body.style.overflow = this.bodyOverflow;
 
-                     document.body.style.width = this.originBodyWith;
 
-                 }
 
-             },
 
-             notifyCancel: (e: React.MouseEvent) => {
 
-                 this.props.onCancel(e);
 
-             },
 
-             notifyOk: (e: React.MouseEvent) => {
 
-                 this.props.onOk(e);
 
-             },
 
-             notifyClose: () => {
 
-                 (this.props.motion as MotionObject)?.didLeave?.();
 
-                 this.props.afterClose();
 
-             },
 
-             toggleHidden: (hidden: boolean, callback?: (hidden: boolean) => void) => {
 
-                 if (hidden !== this.state.hidden) {
 
-                     this.setState({ hidden }, callback || noop);
 
-                 }
 
-             },
 
-             notifyFullScreen: (isFullScreen: boolean) => {
 
-                 if (isFullScreen !== this.state.isFullScreen) {
 
-                     this.setState({ isFullScreen });
 
-                 }
 
-             },
 
-         };
 
-     }
 
-     static getDerivedStateFromProps(props: ModalReactProps, prevState: ModalState) {
 
-         const newState: Partial<ModalState> = {};
 
-         if (props.fullScreen !== prevState.isFullScreen) {
 
-             newState.isFullScreen = props.fullScreen;
 
-         }
 
-         return newState;
 
-     }
 
-     static getScrollbarWidth() {
 
-         if (globalThis && Object.prototype.toString.call(globalThis) === '[object Window]') {
 
-             return window.innerWidth - document.documentElement.clientWidth;
 
-         }
 
-         return 0;
 
-     }
 
-     static info = function (props: ModalReactProps) {
 
-         return confirm<ReturnType<typeof withInfo>>(withInfo(props));
 
-     };
 
-     static success = function (props: ModalReactProps) {
 
-         return confirm<ReturnType<typeof withSuccess>>(withSuccess(props));
 
-     };
 
-     static error = function (props: ModalReactProps) {
 
-         return confirm<ReturnType<typeof withError>>(withError(props));
 
-     };
 
-     static warning = function (props: ModalReactProps) {
 
-         return confirm<ReturnType<typeof withWarning>>(withWarning(props));
 
-     };
 
-     static confirm = function (props: ModalReactProps) {
 
-         return confirm<ReturnType<typeof withConfirm>>(withConfirm(props));
 
-     };
 
-     static destroyAll = function destroyAllFn() {
 
-         while (destroyFns.length) {
 
-             const close = destroyFns.pop();
 
-             if (close) {
 
-                 close();
 
-             }
 
-         }
 
-     };
 
-     componentDidMount() {
 
-         this.scrollBarWidth = Modal.getScrollbarWidth();
 
-         this.originBodyWith = document.body.style.width;
 
-         if (this.props.visible) {
 
-             this.foundation.beforeShow();
 
-             this._active = this._active || this.props.visible;
 
-         }
 
-     }
 
-     componentDidUpdate(prevProps: ModalReactProps, prevState: ModalState, snapshot: any) {
 
-         // hide => show
 
-         if (!prevProps.visible && this.props.visible) {
 
-             this.foundation.beforeShow();
 
-         }
 
-         // show => hide
 
-         if (prevProps.visible && !this.props.visible) {
 
-             this.foundation.afterHide();
 
-         }
 
-         if (!this.props.motion) {
 
-             this.updateHiddenState();
 
-         }
 
-     }
 
-     componentWillUnmount() {
 
-         if (this.props.visible) {
 
-             this.foundation.destroy();
 
-         }
 
-     }
 
-     handleCancel = (e: React.MouseEvent) => {
 
-         this.foundation.handleCancel(e);
 
-     };
 
-     handleOk = (e: React.MouseEvent) => {
 
-         this.foundation.handleOk(e);
 
-     };
 
-     updateHiddenState = () => {
 
-         const { visible } = this.props;
 
-         const { hidden } = this.state;
 
-         if (!visible && !hidden) {
 
-             this.foundation.toggleHidden(true, () => this.foundation.afterClose());
 
-         } else if (visible && this.state.hidden) {
 
-             this.foundation.toggleHidden(false);
 
-         }
 
-     };
 
-     renderFooter = (): ReactNode => {
 
-         const {
 
-             okText,
 
-             okType,
 
-             cancelText,
 
-             confirmLoading,
 
-             cancelLoading,
 
-             hasCancel,
 
-         } = this.props;
 
-         const getCancelButton = (locale: Locale['Modal']) => {
 
-             if (!hasCancel) {
 
-                 return null;
 
-             } else {
 
-                 return (
 
-                     <Button
 
-                         aria-label="cancel"
 
-                         onClick={this.handleCancel}
 
-                         loading={cancelLoading}
 
-                         type="tertiary"
 
-                         autoFocus={true}
 
-                         {...this.props.cancelButtonProps}
 
-                         x-semi-children-alias="cancelText"
 
-                     >
 
-                         {cancelText || locale.cancel}
 
-                     </Button>
 
-                 );
 
-             }
 
-         };
 
-         return (
 
-             <LocaleConsumer componentName="Modal">
 
-                 {(locale: Locale['Modal'], localeCode: Locale['code']) => (
 
-                     <div>
 
-                         {getCancelButton(locale)}
 
-                         <Button
 
-                             aria-label="confirm"
 
-                             type={okType}
 
-                             theme="solid"
 
-                             loading={confirmLoading}
 
-                             onClick={this.handleOk}
 
-                             {...this.props.okButtonProps}
 
-                             x-semi-children-alias="okText"
 
-                         >
 
-                             {okText || locale.confirm}
 
-                         </Button>
 
-                     </div>
 
-                 )}
 
-             </LocaleConsumer>
 
-         );
 
-     };
 
-     // getDialog = () => {
 
-     //     const {
 
-     //         footer,
 
-     //         ...restProps
 
-     //     } = this.props;
 
-     //     const renderFooter = 'footer' in this.props ? footer : this.renderFooter();
 
-     //     return <ModalContent {...restProps} footer={renderFooter} onClose={this.handleCancel}/>;
 
-     // };
 
-     renderDialog = () => {
 
-         let {
 
-             footer,
 
-             className,
 
-             motion,
 
-             maskStyle: maskStyleFromProps,
 
-             keepDOM,
 
-             style: styleFromProps,
 
-             zIndex,
 
-             getPopupContainer,
 
-             visible,
 
-             ...restProps
 
-         } = this.props;
 
-         let style = styleFromProps;
 
-         const maskStyle = maskStyleFromProps;
 
-         const renderFooter = 'footer' in this.props ? footer : this.renderFooter();
 
-         let wrapperStyle: {
 
-             zIndex?: CSSProperties['zIndex'];
 
-             position?: CSSProperties['position'];
 
-         } = {
 
-             zIndex,
 
-         };
 
-         if (getPopupContainer) {
 
-             wrapperStyle = {
 
-                 zIndex,
 
-                 position: 'static',
 
-             };
 
-         }
 
-         const classList = cls(className, {
 
-             [`${cssClasses.DIALOG}-displayNone`]: keepDOM && this.state.hidden && !visible,
 
-         });
 
-         const contentClassName = motion ? cls({
 
-             [`${cssClasses.DIALOG}-content-animate-hide`]: !visible,
 
-             [`${cssClasses.DIALOG}-content-animate-show`]: visible
 
-         }) : null;
 
-         const maskClassName = motion ? cls({
 
-             [`${cssClasses.DIALOG}-mask-animate-hide`]: !visible,
 
-             [`${cssClasses.DIALOG}-mask-animate-show`]: visible
 
-         }) : null;
 
-         return (
 
-             <Portal style={wrapperStyle} getPopupContainer={getPopupContainer}>
 
-                 <ModalContent
 
-                     {...restProps}
 
-                     isFullScreen={this.state.isFullScreen}
 
-                     contentClassName={contentClassName}
 
-                     maskClassName={maskClassName}
 
-                     className={classList}
 
-                     getPopupContainer={getPopupContainer}
 
-                     maskStyle={maskStyle}
 
-                     style={style}
 
-                     ref={this.modalRef}
 
-                     onAnimationEnd={() => {
 
-                         this.updateHiddenState();
 
-                     }}
 
-                     footer={renderFooter}
 
-                     onClose={this.handleCancel}
 
-                 />
 
-             </Portal>
 
-         );
 
-     };
 
-     render() {
 
-         const {
 
-             visible,
 
-             keepDOM,
 
-             lazyRender,
 
-         } = this.props;
 
-         this._active = this._active || visible;
 
-         const shouldRender = ((visible || keepDOM) && (!lazyRender || this._active)) || !this.state.hidden;
 
-         if (shouldRender) {
 
-             return this.renderDialog();
 
-         }
 
-         return null;
 
-     }
 
- }
 
- export default Modal;
 
 
  |