From 031477d693a5af3e6b0116e8703ea7ffd8327e4c Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 30 Aug 2024 17:40:09 +0800 Subject: [PATCH] * modal: show loading indicator on loading iframe modal. --- lib/modal/src/component/modal-dialog.tsx | 28 +++++++++++++++---- .../src/component/modal-iframe-content.tsx | 6 +++- lib/modal/src/style/modal-dialog.css | 7 +++++ lib/modal/src/types/index.ts | 1 + lib/modal/src/types/modal-dialog-options.ts | 1 + lib/modal/src/types/modal-dialog-state.ts | 3 ++ lib/modal/src/vanilla/modal.tsx | 1 + 7 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 lib/modal/src/types/modal-dialog-state.ts diff --git a/lib/modal/src/component/modal-dialog.tsx b/lib/modal/src/component/modal-dialog.tsx index 4fd68bcc27..fc8c658c76 100644 --- a/lib/modal/src/component/modal-dialog.tsx +++ b/lib/modal/src/component/modal-dialog.tsx @@ -1,13 +1,26 @@ -import {classes, CustomContent} from '@zui/core'; +import {classes, CustomContent, $} from '@zui/core'; import {Toolbar} from '@zui/toolbar/src/component/toolbar'; -import {Component, isValidElement} from 'preact'; -import {ModalDialogOptions} from '../types'; +import {Component, createRef, isValidElement} from 'preact'; +import {ModalDialogOptions, ModalDialogState} from '../types'; -export class ModalDialog extends Component { +export class ModalDialog extends Component { static defaultProps = {closeBtn: true}; + protected _ref = createRef(); + + constructor(props: ModalDialogOptions) { + super(props); + this.state = {showed: !props.waitShowEvent}; + } + componentDidMount() { - this.props.afterRender?.call(this, {firstRender: true}); + const {waitShowEvent, afterRender} = this.props; + afterRender?.call(this, {firstRender: true}); + if (waitShowEvent) { + $(this._ref.current).on(waitShowEvent, () => { + this.setState({showed: true}); + }); + } } componentDidUpdate(): void { @@ -103,10 +116,12 @@ export class ModalDialog extends Component { style, contentClass, children, + waitShowEvent, } = this.props; + const loading = waitShowEvent && !this.state.showed; return ( -
+
{this.renderHeader()} {this.renderActions()} @@ -114,6 +129,7 @@ export class ModalDialog extends Component { {children} {this.renderFooter()}
+ {loading ?
: null}
); } diff --git a/lib/modal/src/component/modal-iframe-content.tsx b/lib/modal/src/component/modal-iframe-content.tsx index 168d95373f..91362b7a44 100644 --- a/lib/modal/src/component/modal-iframe-content.tsx +++ b/lib/modal/src/component/modal-iframe-content.tsx @@ -1,9 +1,11 @@ +import {$} from '@zui/core'; import {Component, createRef} from 'preact'; export type ModalIframeContentProps = { url: string; watchHeight?: boolean; iframeBodyClass?: string; + onLoad?: (this: ModalIframeContent) => void; }; export type ModalIframeContentState = { @@ -45,7 +47,7 @@ export class ModalIframeContent extends Component { rob = new ResizeObserver(() => { const body = iframeDoc.body; const html = iframeDoc.documentElement; - const height = Math.ceil(Math.max(body.scrollHeight, body.offsetHeight, html.offsetHeight)) + 1; + const height = Math.ceil(Math.max(body.scrollHeight, body.offsetHeight, html.offsetHeight)); this.setState({height}); }); rob.observe(iframeDoc.body); @@ -68,6 +70,8 @@ export class ModalIframeContent extends Component { if (iframeBodyClass) { iframeDoc.body.classList.add(iframeBodyClass); } + + $(this._ref.current).trigger('modal-iframe-loaded'); }; render() { diff --git a/lib/modal/src/style/modal-dialog.css b/lib/modal/src/style/modal-dialog.css index fe27ce2a9f..98c2f5cf72 100644 --- a/lib/modal/src/style/modal-dialog.css +++ b/lib/modal/src/style/modal-dialog.css @@ -10,3 +10,10 @@ .loading > .modal-dialog > .modal-content { @apply -opacity-0 -invisible; } + +.modal-dialog.loading { + @apply -bg-transparent; +} +.modal-dialog.loading > .modal-content { + @apply -hidden; +} diff --git a/lib/modal/src/types/index.ts b/lib/modal/src/types/index.ts index df7c89b7ff..8bb4ae9050 100644 --- a/lib/modal/src/types/index.ts +++ b/lib/modal/src/types/index.ts @@ -5,4 +5,5 @@ export * from './modal-base-options'; export * from './modal-events'; export * from './modal-trigger-options'; export * from './modal-dialog-options'; +export * from './modal-dialog-state'; export * from './modal-options'; diff --git a/lib/modal/src/types/modal-dialog-options.ts b/lib/modal/src/types/modal-dialog-options.ts index 78ee580ca7..ad0bb266cc 100644 --- a/lib/modal/src/types/modal-dialog-options.ts +++ b/lib/modal/src/types/modal-dialog-options.ts @@ -17,6 +17,7 @@ export type ModalDialogOptions = { footer?: CustomContentType; footerClass?: ClassNameLike; footerActions?: ToolbarOptions; + waitShowEvent?: string; afterRender?: (info: {firstRender: boolean}) => void; beforeDestroy?: () => void; }; diff --git a/lib/modal/src/types/modal-dialog-state.ts b/lib/modal/src/types/modal-dialog-state.ts new file mode 100644 index 0000000000..ab92e3c31d --- /dev/null +++ b/lib/modal/src/types/modal-dialog-state.ts @@ -0,0 +1,3 @@ +export type ModalDialogState = { + showed?: boolean; +}; diff --git a/lib/modal/src/vanilla/modal.tsx b/lib/modal/src/vanilla/modal.tsx index a11497342a..34528a65c3 100644 --- a/lib/modal/src/vanilla/modal.tsx +++ b/lib/modal/src/vanilla/modal.tsx @@ -58,6 +58,7 @@ async function buildIframeModal(this: Modal, _element: HTMLElement, options: Mod return { title, ...custom, + waitShowEvent: 'modal-iframe-loaded', body: , }; }