@tarojs/components
Version:
95 lines (92 loc) • 4.49 kB
JavaScript
import { __rest } from '../node_modules/.pnpm/@rollup_plugin-typescript@11.1.6_rollup@4.18.0_tslib@2.6.2_typescript@5.4.5/node_modules/tslib/tslib.es6.js';
import React from 'react';
import ReactDOM from 'react-dom';
import { defineCustomElement, setRef } from './utils/index.js';
import { dashToPascalCase } from './utils/case.js';
import { attachProps } from './utils/attachProps.js';
const createOverlayComponent = (tagName, controller, customElement) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const didDismissEventName = `on${displayName}DidDismiss`;
const didPresentEventName = `on${displayName}DidPresent`;
const willDismissEventName = `on${displayName}WillDismiss`;
const willPresentEventName = `on${displayName}WillPresent`;
let isDismissing = false;
class Overlay extends React.Component {
constructor(props) {
super(props);
if (typeof document !== 'undefined') {
this.el = document.createElement('div');
}
this.handleDismiss = this.handleDismiss.bind(this);
}
static get displayName() {
return displayName;
}
componentDidMount() {
if (this.props.isOpen) {
this.present();
}
}
componentWillUnmount() {
if (this.overlay) {
this.overlay.dismiss();
}
}
handleDismiss(event) {
if (this.props.onDidDismiss) {
this.props.onDidDismiss(event);
}
setRef(this.props.forwardedRef, null);
}
shouldComponentUpdate(nextProps) {
// Check if the overlay component is about to dismiss
if (this.overlay && nextProps.isOpen !== this.props.isOpen && nextProps.isOpen === false) {
isDismissing = true;
}
return true;
}
async componentDidUpdate(prevProps) {
if (this.overlay) {
attachProps(this.overlay, this.props, prevProps);
}
if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
this.present(prevProps);
}
if (this.overlay && prevProps.isOpen !== this.props.isOpen && this.props.isOpen === false) {
await this.overlay.dismiss();
isDismissing = false;
/**
* Now that the overlay is dismissed
* we need to render again so that any
* inner components will be unmounted
*/
this.forceUpdate();
}
}
async present(prevProps) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _a = this.props, { children, isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent } = _a, cProps = __rest(_a, ["children", "isOpen", "onDidDismiss", "onDidPresent", "onWillDismiss", "onWillPresent"]);
const elementProps = Object.assign(Object.assign({}, cProps), { ref: this.props.forwardedRef, [didDismissEventName]: this.handleDismiss, [didPresentEventName]: (e) => this.props.onDidPresent && this.props.onDidPresent(e), [willDismissEventName]: (e) => this.props.onWillDismiss && this.props.onWillDismiss(e), [willPresentEventName]: (e) => this.props.onWillPresent && this.props.onWillPresent(e) });
this.overlay = await controller.create(Object.assign(Object.assign({}, elementProps), { component: this.el, componentProps: {} }));
setRef(this.props.forwardedRef, this.overlay);
attachProps(this.overlay, elementProps, prevProps);
await this.overlay.present();
}
render() {
/**
* Continue to render the component even when
* overlay is dismissing otherwise component
* will be hidden before animation is done.
*/
return ReactDOM.createPortal(this.props.isOpen || isDismissing ? this.props.children : null, this.el);
}
}
return React.forwardRef((props, ref) => {
// Note: 组件库错误引入 vue 的 ts 类型,导致 ts 报错,这里先忽略
// @ts-ignore
return React.createElement(Overlay, Object.assign({}, props, { forwardedRef: ref }));
});
};
export { createOverlayComponent };
//# sourceMappingURL=createOverlayComponent.js.map