import React from 'react'; import { isFunction } from '../utils'; import { createMountHandle } from '../imperative/mountComponent'; import type { RefComponentMountAdapter, RefComponentMountParams, RefComponentMountResult, } from '../types/refComponentMount'; import type { ModalRef } from '../types/modal'; let refContainerSeed = 0; /** * 默认 Web 挂载:创建/查找 DOM 容器并用 react-dom 渲染。 * @param params - 挂载参数 * @returns ref 与 destroy */ function mountWithDom< M extends ModalRef, P extends Record = Record, >( params: RefComponentMountParams, ): Promise> { const { RefComponent, props, options } = params; const { selector, container: _container, id, className, destroyDelay = 50, onDestroyComponent, onAppendContainer, onRemoveContainer, onRef, } = options; return new Promise((resolve, reject) => { let resolved = false; let destroyed = false; let needDestroy = false; let container = isFunction(_container) ? _container() : _container; if (!container) { if (selector) { container = document.querySelector(selector) as HTMLElement; } else if (id) { container = document.getElementById(id) as HTMLElement; } if (!container) { container = document.createElement('div'); container.classList.add(`ref-component-container-${++refContainerSeed}`); if (className) { container.classList.add(className); } if (id) { container.id = id; } if (onAppendContainer?.(container) !== true) { document.body.appendChild(container); } needDestroy = true; } } const mount = createMountHandle(container as HTMLElement); const destroy = () => { if (destroyed) { return; } destroyed = true; setTimeout(() => { if (onDestroyComponent?.(container as any) !== true) { mount.unmount(); } if (needDestroy && container?.parentNode) { if (onRemoveContainer?.(container) !== true) { container.parentNode.removeChild(container); } container = null; } }, destroyDelay); }; try { mount.render( React.createElement(RefComponent, { ...(props as any || {}), ref: (r: M | null) => { if (r && !resolved) { resolved = true; resolve([r, destroy]); if (onRef) onRef(r, destroy); } }, }), ); } catch (error) { reject(error); } }); } /** 内置 DOM + react-dom 挂载适配器 */ const defaultDomMountAdapter: RefComponentMountAdapter = { id: 'dom', mount: mountWithDom, }; export { defaultDomMountAdapter, mountWithDom, };