import { Observable } from "@hibas123/utils"; import { h, Component } from "preact"; import { X } from "preact-feather"; export default abstract class Modal { // Static private static modalObservableServer = new Observable<{ modal: Modal; close: boolean; }>(); public static modalObservable = Modal.modalObservableServer.getPublicApi(); protected abstract title: string; // Private private onResult: (result: T | null) => void; private closeOnResult: boolean; private noClose: boolean = false; // Protected protected result(value: T | null) { if (this.closeOnResult) this.close(); if (this.onResult) this.onResult(value); } //Public /** * This function shows the modal * Do not call when using getResult() */ public show(noClose = true) { this.noClose = noClose; Modal.modalObservableServer.send({ modal: this, close: false }); } /** * Shows the modal and waits for result. * * Call close when successful */ public async getResult(close = true) { this.closeOnResult = close; this.show(false); return new Promise((yes) => (this.onResult = yes)); } public close() { Modal.modalObservableServer.send({ modal: this, close: true }); } public abstract getComponent(): JSX.Element; public static BaseModal = class BaseModal extends Component< { modal: Modal }, {} > { render() { return ( ); } }; } export class ModalComponent extends Component< {}, { modal: Modal | undefined; component: JSX.Element | undefined } > { constructor(props) { super(props); this.onModal = this.onModal.bind(this); } onModal({ modal, close }: { modal: Modal; close: boolean }) { if (!close && this.state.modal !== modal) { this.setState({ modal: modal, component: modal.getComponent() }); } else { if (this.state.modal === modal && close) // Only close if the same this.setState({ modal: undefined, component: undefined }); } } componentWillMount() { Modal.modalObservable.subscribe(this.onModal); } componentWillUnmount() { Modal.modalObservable.unsubscribe(this.onModal); } render() { return
{this.state.component}
; } }