Add pop-up system & delete confirmation pops up #25
							
								
								
									
										0
									
								
								source/Component/ConfirmPopup/ConfirmPopup.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								source/Component/ConfirmPopup/ConfirmPopup.scss
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										8
									
								
								source/Component/ConfirmPopup/ConfirmPopup.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								source/Component/ConfirmPopup/ConfirmPopup.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					import { Popup } from "@Context/Popups";
 | 
				
			||||||
 | 
					import "./ConfirmPopup.scss";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConfirmPopup extends Popup {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { ConfirmPopup }
 | 
				
			||||||
@ -39,10 +39,17 @@ div.popup-mask {
 | 
				
			|||||||
    height: 100%;
 | 
					    height: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					div.focus.popup-layer {
 | 
				
			||||||
 | 
					    border: 0.8px solid #514feb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
div.popup-layer {
 | 
					div.popup-layer {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    border-radius: 3px;
 | 
					    border-radius: 3px;
 | 
				
			||||||
    overflow: hidden;
 | 
					    overflow: hidden;
 | 
				
			||||||
 | 
					    transition: none;
 | 
				
			||||||
 | 
					    box-sizing: border-box;
 | 
				
			||||||
 | 
					    border: 0.8px solid transparent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    div.popup-layer-header {
 | 
					    div.popup-layer-header {
 | 
				
			||||||
        min-height: $header-height;
 | 
					        min-height: $header-height;
 | 
				
			||||||
@ -79,9 +86,16 @@ div.popup-layer {
 | 
				
			|||||||
            cursor: pointer;
 | 
					            cursor: pointer;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    div.popup-layer-content {
 | 
				
			||||||
 | 
					        height: calc( 100% - 32px );
 | 
				
			||||||
 | 
					        width: 100%;
 | 
				
			||||||
 | 
					        overflow: hidden;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
div.popup-layer.dark {
 | 
					div.popup-layer.dark {
 | 
				
			||||||
 | 
					    box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    div.popup-layer-header {
 | 
					    div.popup-layer-header {
 | 
				
			||||||
        background-color: $lt-bg-color-lvl3-dark;
 | 
					        background-color: $lt-bg-color-lvl3-dark;
 | 
				
			||||||
@ -94,6 +108,7 @@ div.popup-layer.dark {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
div.popup-layer.light {
 | 
					div.popup-layer.light {
 | 
				
			||||||
 | 
					    box-shadow: 0 0 15px rgba(0, 0, 0, 0.15);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    div.popup-layer-header {
 | 
					    div.popup-layer-header {
 | 
				
			||||||
        background-color: $lt-bg-color-lvl3-light;
 | 
					        background-color: $lt-bg-color-lvl3-light;
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ interface IPopupProps {}
 | 
				
			|||||||
@useStatusWithEvent("popupChange")
 | 
					@useStatusWithEvent("popupChange")
 | 
				
			||||||
class Popup extends Component<IPopupProps & IMixinStatusProps> {
 | 
					class Popup extends Component<IPopupProps & IMixinStatusProps> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public renderMask(index?: number, click?: () => void, key?: string): ReactNode {
 | 
					    private renderMask(index?: number, click?: () => void, key?: string): ReactNode {
 | 
				
			||||||
        const classList: string[] = ["popup-mask", "show-fade"];
 | 
					        const classList: string[] = ["popup-mask", "show-fade"];
 | 
				
			||||||
        return <Theme
 | 
					        return <Theme
 | 
				
			||||||
            key={key}
 | 
					            key={key}
 | 
				
			||||||
@ -22,7 +22,7 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> {
 | 
				
			|||||||
        />
 | 
					        />
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public renderRootMask(): ReactNode {
 | 
					    private renderRootMask(): ReactNode {
 | 
				
			||||||
        if (this.props.status) {
 | 
					        if (this.props.status) {
 | 
				
			||||||
            const needMask = this.props.status.popup.popups.some(popup => popup.needMask);
 | 
					            const needMask = this.props.status.popup.popups.some(popup => popup.needMask);
 | 
				
			||||||
            if (!needMask) return null;
 | 
					            if (!needMask) return null;
 | 
				
			||||||
@ -38,7 +38,7 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public renderMaskList(): ReactNode {
 | 
					    private renderMaskList(): ReactNode {
 | 
				
			||||||
        if (this.props.status) {
 | 
					        if (this.props.status) {
 | 
				
			||||||
            return this.props.status.popup.popups
 | 
					            return this.props.status.popup.popups
 | 
				
			||||||
            .filter((popup) => {
 | 
					            .filter((popup) => {
 | 
				
			||||||
@ -60,9 +60,19 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public renderHeader(popup: PopupModel): ReactNode {
 | 
					    private renderHeader(popup: PopupModel): ReactNode {
 | 
				
			||||||
        return <div className="popup-layer-header">
 | 
					        return <div className="popup-layer-header">
 | 
				
			||||||
            <div className="header-text">
 | 
					            <div
 | 
				
			||||||
 | 
					                className="header-text"
 | 
				
			||||||
 | 
					                onMouseDown={(e) => {
 | 
				
			||||||
 | 
					                    popup.isOnMouseDown = true;
 | 
				
			||||||
 | 
					                    popup.lastMouseLeft = e.clientX;
 | 
				
			||||||
 | 
					                    popup.lastMouseTop = e.clientY;
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                onMouseUp={() => {
 | 
				
			||||||
 | 
					                    popup.isOnMouseDown = false;
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
                {popup.onRenderHeader()}
 | 
					                {popup.onRenderHeader()}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div
 | 
					            <div
 | 
				
			||||||
@ -76,28 +86,79 @@ class Popup extends Component<IPopupProps & IMixinStatusProps> {
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public renderLayer(popup: PopupModel) {
 | 
					    private renderContent(popup: PopupModel) {
 | 
				
			||||||
 | 
					        return <div className="popup-layer-content">
 | 
				
			||||||
 | 
					            {popup.render()}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private renderLayer(popup: PopupModel) {
 | 
				
			||||||
        const pageWidth = document.documentElement.clientWidth;
 | 
					        const pageWidth = document.documentElement.clientWidth;
 | 
				
			||||||
        const pageHeight = document.documentElement.clientHeight;
 | 
					        const pageHeight = document.documentElement.clientHeight;
 | 
				
			||||||
        const top = (pageHeight - popup.height) / 2;
 | 
					        if (isNaN(popup.top)) {
 | 
				
			||||||
        const left = (pageWidth - popup.width) / 2;
 | 
					            popup.top = (pageHeight - popup.height) / 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (isNaN(popup.left)) {
 | 
				
			||||||
 | 
					            popup.left = (pageWidth - popup.width) / 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return <Theme
 | 
					        return <Theme
 | 
				
			||||||
            style={{
 | 
					            style={{
 | 
				
			||||||
                width: popup.width,
 | 
					                width: popup.width,
 | 
				
			||||||
                height: popup.height,
 | 
					                height: popup.height,
 | 
				
			||||||
                zIndex: popup.zIndex(),
 | 
					                zIndex: popup.zIndex(),
 | 
				
			||||||
                top: top,
 | 
					                top: popup.top,
 | 
				
			||||||
                left: left
 | 
					                left: popup.left
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            key={popup.id}
 | 
					            key={popup.id}
 | 
				
			||||||
            backgroundLevel={BackgroundLevel.Level4}
 | 
					            backgroundLevel={BackgroundLevel.Level4}
 | 
				
			||||||
            className="popup-layer show-scale"
 | 
					            className="popup-layer show-scale"
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            {this.renderHeader(popup)}
 | 
					            {this.renderHeader(popup)}
 | 
				
			||||||
 | 
					            {this.renderContent(popup)}
 | 
				
			||||||
        </Theme>
 | 
					        </Theme>
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private isMouseDown: boolean = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private handelMouseDown = () => {
 | 
				
			||||||
 | 
					        this.isMouseDown = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private handelMouseUp = () => {
 | 
				
			||||||
 | 
					        this.isMouseDown = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private handelMouseMove = (e: MouseEvent) => {
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					            this.isMouseDown &&
 | 
				
			||||||
 | 
					            this.props.status &&
 | 
				
			||||||
 | 
					            this.props.status.popup.popups.some(popup => popup.isOnMouseDown)
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            this.props.status.popup.popups.forEach((popup) => {
 | 
				
			||||||
 | 
					                if (popup.isOnMouseDown) {
 | 
				
			||||||
 | 
					                    popup.top += e.clientY - popup.lastMouseTop;
 | 
				
			||||||
 | 
					                    popup.left += e.clientX - popup.lastMouseLeft;
 | 
				
			||||||
 | 
					                    popup.lastMouseLeft = e.clientX;
 | 
				
			||||||
 | 
					                    popup.lastMouseTop = e.clientY;
 | 
				
			||||||
 | 
					                    this.forceUpdate();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public componentDidMount() {
 | 
				
			||||||
 | 
					        window.addEventListener("mousemove", this.handelMouseMove);
 | 
				
			||||||
 | 
					        window.addEventListener("mousedown", this.handelMouseDown);
 | 
				
			||||||
 | 
					        window.addEventListener("mouseup", this.handelMouseUp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public componentWillUnmount() {
 | 
				
			||||||
 | 
					        window.removeEventListener("mousemove", this.handelMouseMove);
 | 
				
			||||||
 | 
					        window.removeEventListener("mousedown", this.handelMouseDown);
 | 
				
			||||||
 | 
					        window.removeEventListener("mouseup", this.handelMouseUp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public render(): ReactNode {
 | 
					    public render(): ReactNode {
 | 
				
			||||||
        return <>
 | 
					        return <>
 | 
				
			||||||
            {this.renderRootMask()}
 | 
					            {this.renderRootMask()}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,16 @@ import { ReactNode, createElement } from "react";
 | 
				
			|||||||
import { Emitter } from "@Model/Emitter";
 | 
					import { Emitter } from "@Model/Emitter";
 | 
				
			||||||
import { Localization } from "@Component/Localization/Localization";
 | 
					import { Localization } from "@Component/Localization/Localization";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IPopupConstructor = new (controller: PopupController, id: string) => Popup;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 弹窗类型
 | 
					 * 弹窗类型
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class Popup {
 | 
					class Popup<P extends any = any> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public props: P;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public constructor(props: P) {
 | 
				
			||||||
 | 
					        this.props = props;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public zIndex() {
 | 
					    public zIndex() {
 | 
				
			||||||
        return this.index * 2 + this.controller.zIndex;
 | 
					        return this.index * 2 + this.controller.zIndex;
 | 
				
			||||||
@ -17,9 +21,15 @@ class Popup {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public height: number = 200;
 | 
					    public height: number = 200;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public top: number = 0;
 | 
					    public top: number = NaN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public left: number = 0;
 | 
					    public left: number = NaN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public lastMouseTop: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public lastMouseLeft: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public isOnMouseDown: boolean = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 是否关闭
 | 
					     * 是否关闭
 | 
				
			||||||
@ -39,12 +49,12 @@ class Popup {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 唯一标识符
 | 
					     * 唯一标识符
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public id: string;
 | 
					    public id: string = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 控制器
 | 
					     * 控制器
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public controller: PopupController;
 | 
					    public controller: PopupController = undefined as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 渲染层级
 | 
					     * 渲染层级
 | 
				
			||||||
@ -67,7 +77,7 @@ class Popup {
 | 
				
			|||||||
     * 渲染函数
 | 
					     * 渲染函数
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public onRender(p: Popup): ReactNode {
 | 
					    public onRender(p: Popup): ReactNode {
 | 
				
			||||||
        return null;
 | 
					        return undefined;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -81,15 +91,15 @@ class Popup {
 | 
				
			|||||||
     * 渲染节点
 | 
					     * 渲染节点
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public render(): ReactNode {
 | 
					    public render(): ReactNode {
 | 
				
			||||||
        this.reactNode = this.onRender(this);
 | 
					        this.reactNode = this.onRender(this) ?? this.reactNode;
 | 
				
			||||||
        return this.reactNode;
 | 
					        return this.reactNode;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public close() {
 | 
					    public close(): Popup | undefined {
 | 
				
			||||||
        return this.controller.closePopup(this);
 | 
					        return this.controller.closePopup(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public constructor(controller: PopupController, id: string) {
 | 
					    public init(controller: PopupController, id: string) {
 | 
				
			||||||
        this.controller = controller;
 | 
					        this.controller = controller;
 | 
				
			||||||
        this.id = id;
 | 
					        this.id = id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -134,8 +144,16 @@ class PopupController extends Emitter<IPopupControllerEvent> {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 实例化并开启一个弹窗
 | 
					     * 实例化并开启一个弹窗
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public showPopup<P extends IPopupConstructor>(popup?: P): Popup {
 | 
					    public showPopup<P extends any, T extends Popup<P>>(
 | 
				
			||||||
        let newPopup = new (popup ?? Popup)(this, `P-${this.idIndex ++}`);
 | 
					        popup?: (new () => T) | Popup<P>, props?: P
 | 
				
			||||||
 | 
					    ): Popup<P> {
 | 
				
			||||||
 | 
					        let newPopup: Popup;
 | 
				
			||||||
 | 
					        if (popup instanceof Popup) {
 | 
				
			||||||
 | 
					            newPopup = popup;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            newPopup = new (popup ?? Popup)(props);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        newPopup.init(this, `P-${this.idIndex ++}`);
 | 
				
			||||||
        this.popups.push(newPopup);
 | 
					        this.popups.push(newPopup);
 | 
				
			||||||
        this.sortPopup();
 | 
					        this.sortPopup();
 | 
				
			||||||
        return newPopup;
 | 
					        return newPopup;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user