diff --git a/source/Component/ConfirmPopup/ConfirmPopup.scss b/source/Component/ConfirmPopup/ConfirmPopup.scss new file mode 100644 index 0000000..e69de29 diff --git a/source/Component/ConfirmPopup/ConfirmPopup.tsx b/source/Component/ConfirmPopup/ConfirmPopup.tsx new file mode 100644 index 0000000..4f378d7 --- /dev/null +++ b/source/Component/ConfirmPopup/ConfirmPopup.tsx @@ -0,0 +1,8 @@ +import { Popup } from "@Context/Popups"; +import "./ConfirmPopup.scss"; + +class ConfirmPopup extends Popup { + +} + +export { ConfirmPopup } \ No newline at end of file diff --git a/source/Component/Popup/Popup.scss b/source/Component/Popup/Popup.scss index a39b8d6..a588765 100644 --- a/source/Component/Popup/Popup.scss +++ b/source/Component/Popup/Popup.scss @@ -39,10 +39,17 @@ div.popup-mask { height: 100%; } +div.focus.popup-layer { + border: 0.8px solid #514feb; +} + div.popup-layer { position: absolute; border-radius: 3px; overflow: hidden; + transition: none; + box-sizing: border-box; + border: 0.8px solid transparent; div.popup-layer-header { min-height: $header-height; @@ -79,9 +86,16 @@ div.popup-layer { cursor: pointer; } } + + div.popup-layer-content { + height: calc( 100% - 32px ); + width: 100%; + overflow: hidden; + } } div.popup-layer.dark { + box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); div.popup-layer-header { background-color: $lt-bg-color-lvl3-dark; @@ -94,6 +108,7 @@ div.popup-layer.dark { } div.popup-layer.light { + box-shadow: 0 0 15px rgba(0, 0, 0, 0.15); div.popup-layer-header { background-color: $lt-bg-color-lvl3-light; diff --git a/source/Component/Popup/Popup.tsx b/source/Component/Popup/Popup.tsx index 2bfaefe..1b88b8c 100644 --- a/source/Component/Popup/Popup.tsx +++ b/source/Component/Popup/Popup.tsx @@ -10,7 +10,7 @@ interface IPopupProps {} @useStatusWithEvent("popupChange") class Popup extends Component { - 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"]; return { /> } - public renderRootMask(): ReactNode { + private renderRootMask(): ReactNode { if (this.props.status) { const needMask = this.props.status.popup.popups.some(popup => popup.needMask); if (!needMask) return null; @@ -38,7 +38,7 @@ class Popup extends Component { } } - public renderMaskList(): ReactNode { + private renderMaskList(): ReactNode { if (this.props.status) { return this.props.status.popup.popups .filter((popup) => { @@ -60,9 +60,19 @@ class Popup extends Component { } } - public renderHeader(popup: PopupModel): ReactNode { + private renderHeader(popup: PopupModel): ReactNode { return
-
+
{ + popup.isOnMouseDown = true; + popup.lastMouseLeft = e.clientX; + popup.lastMouseTop = e.clientY; + }} + onMouseUp={() => { + popup.isOnMouseDown = false; + }} + > {popup.onRenderHeader()}
{
} - public renderLayer(popup: PopupModel) { + private renderContent(popup: PopupModel) { + return
+ {popup.render()} +
+ } + + private renderLayer(popup: PopupModel) { const pageWidth = document.documentElement.clientWidth; const pageHeight = document.documentElement.clientHeight; - const top = (pageHeight - popup.height) / 2; - const left = (pageWidth - popup.width) / 2; + if (isNaN(popup.top)) { + popup.top = (pageHeight - popup.height) / 2; + } + if (isNaN(popup.left)) { + popup.left = (pageWidth - popup.width) / 2; + } return {this.renderHeader(popup)} + {this.renderContent(popup)} } + 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 { return <> {this.renderRootMask()} diff --git a/source/Context/Popups.ts b/source/Context/Popups.ts index 0b75ccd..2e74ea0 100644 --- a/source/Context/Popups.ts +++ b/source/Context/Popups.ts @@ -2,12 +2,16 @@ import { ReactNode, createElement } from "react"; import { Emitter } from "@Model/Emitter"; import { Localization } from "@Component/Localization/Localization"; -type IPopupConstructor = new (controller: PopupController, id: string) => Popup; - /** * 弹窗类型 */ -class Popup { +class Popup

{ + + public props: P; + + public constructor(props: P) { + this.props = props; + } public zIndex() { return this.index * 2 + this.controller.zIndex; @@ -17,9 +21,15 @@ class Popup { 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 { - return null; + return undefined; } /** @@ -81,15 +91,15 @@ class Popup { * 渲染节点 */ public render(): ReactNode { - this.reactNode = this.onRender(this); + this.reactNode = this.onRender(this) ?? this.reactNode; return this.reactNode; }; - public close() { + public close(): Popup | undefined { return this.controller.closePopup(this); } - public constructor(controller: PopupController, id: string) { + public init(controller: PopupController, id: string) { this.controller = controller; this.id = id; } @@ -134,8 +144,16 @@ class PopupController extends Emitter { /** * 实例化并开启一个弹窗 */ - public showPopup

(popup?: P): Popup { - let newPopup = new (popup ?? Popup)(this, `P-${this.idIndex ++}`); + public showPopup

>( + popup?: (new () => T) | Popup

, props?: P + ): Popup

{ + 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.sortPopup(); return newPopup;