import * as React from 'react' import { createPortal } from 'react-dom' import { lock, unlock, clearBodyLocks } from '../../utils/body-scroll-lock' import { Container, PanelContainer, PanelContentContainer, } from './index.style' interface Props { show: boolean; height?: string; /** * 弹出内容左右两侧的间距,默认为rem(24),string,带单位的字符串 */ gapWidth?: string; isEdit: boolean; close: () => any; scrollRef?: HTMLElement | undefined; children: React.ReactNode; background?: { topImage?: { url: string, }; centerImage?: { url: string, }; bottomImage?: { url: string, }; }; maskBg?: string; overflow?: 'visible' | 'hidden'; } export interface State { panelShow: boolean; aniType: 'unfold' | 'fold' | '' } let isBodyLocked = false; class PopupCom extends React.Component { constructor(props: Props) { super(props); this.randomId = 'PopupCom_' + Math.random(); } state: State = { aniType: '', panelShow: false, } randomId: string; panelContent: HTMLElement; currentScroller: HTMLElement; componentWillReceiveProps(nextProps: Props) { if (this.state.panelShow && nextProps.scrollRef && nextProps.scrollRef !== this.props.scrollRef) { this.updateLock(nextProps.scrollRef); } } updateLock = (scroller: HTMLElement) => { this.unlock(); this.lock(scroller); } lock = (scoller?: HTMLElement) => { if (this.props.isEdit) { return; } if (isBodyLocked) { // console.log('Body alread has lock, unlock first.'); clearBodyLocks(); } this.currentScroller = scoller || this.props.scrollRef || this.panelContent; // console.log('lock', this.currentScroller); isBodyLocked = true; lock(this.currentScroller) } unlock = () => { if (this.props.isEdit || !this.currentScroller) { return; } // console.log('unlock', this.randomId, this.currentScroller); isBodyLocked = false; unlock(this.currentScroller); } componentDidMount() { if (this.props.show) { this.lock(); this.setState({ panelShow: true }) setTimeout(() => { this.setState({ aniType: 'unfold' }) }, 10) } else { this.unlock() this.setState({ aniType: 'fold' }) setTimeout(() => { this.setState({ panelShow: false }) }, 300) } } componentDidUpdate(preProps: any) { // console.log('prepProps', preProps, this.props); const { show: prevShow } = preProps; const { show: currentShow } = this.props; if (prevShow !== currentShow) { if (currentShow === false) { this.unlock(); this.setState({ aniType: 'fold' }) setTimeout(() => { this.setState({ panelShow: false }) }, 300) } if (currentShow === true) { this.lock(); this.setState({ panelShow: true }) setTimeout(() => { this.setState({ aniType: 'unfold' }) }, 10) } } } handleClosePanel = (e: React.MouseEvent) => { // @ts-ignore if (e.target.getAttribute('id') === this.randomId) { this.props.close() } } render() { const { children, height, gapWidth, isEdit, background, overflow, maskBg, } = this.props const { aniType, panelShow } = this.state return ( createPortal(( this.panelContent = ref}> {children} ), isEdit && document.getElementById('viewport') ? document.getElementById('viewport') : document.getElementById('app')!) ) } } const Popup = React.memo(PopupCom); export { Popup }