/* eslint-disable eqeqeq */ import React, { CSSProperties } from 'react'; import PropTypes from 'prop-types'; import cls from 'classnames'; import { cssClasses } from '@douyinfe/semi-foundation/modal/constants'; import ConfigContext from '../configProvider/context'; import Button from '../iconButton'; import Typography from '../typography'; import BaseComponent from '../_base/baseComponent'; // eslint-disable-next-line max-len import ModalContentFoundation, { ModalContentAdapter, ModalContentProps, ModalContentState } from '@douyinfe/semi-foundation/modal/modalContentFoundation'; import { noop, isFunction, get } from 'lodash'; import { IconClose } from '@douyinfe/semi-icons'; import { getActiveElement } from '../_utils'; let uuid = 0; export default class ModalContent extends BaseComponent { static contextType = ConfigContext; static propTypes = { close: PropTypes.func, getContainerContext: PropTypes.func, contentClassName: PropTypes.string, maskClassName: PropTypes.string, onAnimationEnd: PropTypes.func }; static defaultProps = { close: noop, getContainerContext: noop, contentClassName: '', maskClassName: '' }; dialogId: string; private timeoutId: NodeJS.Timeout; modalDialogRef: React.MutableRefObject; foundation: ModalContentFoundation; constructor(props: ModalContentProps) { super(props); this.state = { dialogMouseDown: false, prevFocusElement: getActiveElement(), }; this.foundation = new ModalContentFoundation(this.adapter); this.dialogId = `dialog-${uuid++}`; this.modalDialogRef = React.createRef(); } get adapter(): ModalContentAdapter { return { ...super.adapter, notifyClose: (e: React.MouseEvent) => { this.props.onClose(e); }, notifyDialogMouseDown: () => { this.setState({ dialogMouseDown: true }); }, notifyDialogMouseUp: () => { if (this.state.dialogMouseDown) { // Not setting setTimeout triggers close when modal external mouseUp this.timeoutId = setTimeout(() => { this.setState({ dialogMouseDown: false }); }, 0); } }, addKeyDownEventListener: () => { if (this.props.closeOnEsc) { document.addEventListener('keydown', this.foundation.handleKeyDown.bind(this.foundation)); } }, removeKeyDownEventListener: () => { if (this.props.closeOnEsc) { document.removeEventListener('keydown', this.foundation.handleKeyDown.bind(this.foundation)); } }, getMouseState: () => this.state.dialogMouseDown, modalDialogFocus: () => { let activeElementInDialog; if (this.modalDialogRef) { const activeElement = getActiveElement(); activeElementInDialog = this.modalDialogRef.current.contains(activeElement); } if (!activeElementInDialog) { this.modalDialogRef && this.modalDialogRef.current.focus(); } }, modalDialogBlur: () => { this.modalDialogRef && this.modalDialogRef.current.blur(); }, prevFocusElementReFocus: () => { const { prevFocusElement } = this.state; const focus = get(prevFocusElement, 'focus'); isFunction(focus) && prevFocusElement.focus(); } }; } componentDidMount() { this.foundation.handleKeyDownEventListenerMount(); this.foundation.modalDialogFocus(); } componentWillUnmount() { clearTimeout(this.timeoutId); this.foundation.destroy(); } onKeyDown = (e: React.MouseEvent) => { this.foundation.handleKeyDown(e); }; // Record when clicking the modal box onDialogMouseDown = () => { this.foundation.handleDialogMouseDown(); }; // Cancel recording when clicking the modal box at the end onMaskMouseUp = () => { this.foundation.handleMaskMouseUp(); }; // onMaskClick will judge dialogMouseDown before onMaskMouseUp updates dialogMouseDown onMaskClick = (e: React.MouseEvent) => { this.foundation.handleMaskClick(e); }; close = (e: React.MouseEvent) => { this.foundation.close(e); }; getMaskElement = () => { const { ...props } = this.props; const { mask, maskClassName } = props; if (mask) { const className = cls(`${cssClasses.DIALOG}-mask`, { // [`${cssClasses.DIALOG}-mask-hidden`]: !props.visible, }); return
; } return null; }; renderCloseBtn = () => { const { closable, closeIcon, } = this.props; let closer; if (closable) { const iconType = closeIcon || ; closer = (