Add confirm popup component

This commit is contained in:
MrKBear 2022-03-23 17:44:37 +08:00
parent 8b44ae953e
commit 89ae499d4b
5 changed files with 125 additions and 23 deletions

View File

@ -0,0 +1,8 @@
import { Popup } from "@Context/Popups";
import "./ConfirmPopup.scss";
class ConfirmPopup extends Popup {
}
export { ConfirmPopup }

View File

@ -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;

View File

@ -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()}

View File

@ -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;