@zohodesk/components
Version:
Dot UI is a customizable React component library built to deliver a clean, accessible, and developer-friendly UI experience. It offers a growing set of reusable components designed to align with modern design systems and streamline application development
174 lines (150 loc) • 4.84 kB
JavaScript
/**** Libraries ****/
import React from 'react';
import { defaultProps } from "./props/defaultProps";
import { propTypes } from "./props/propTypes";
import Portal from "./Portal/Portal";
import { getLibraryConfig } from "../Provider/Config";
import style from "../AppContainer/AppContainer.module.css";
let createdPortalIds = [];
let newPortalPrefix = 'CPortal';
let portalChildrenTopIndexValues;
export default class Modal extends React.Component {
constructor(props) {
super(props);
this.handleAddPortalId = this.handleAddPortalId.bind(this);
this.handleRemovePortalId = this.handleRemovePortalId.bind(this);
this.handleInsertPortalDiv = this.handleInsertPortalDiv.bind(this);
this.setPortalDiv = this.setPortalDiv.bind(this);
this.getRootElement = this.getRootElement.bind(this);
this.getPortalPrefix = this.getPortalPrefix.bind(this);
this.state = {
isMounted: false
};
this.portalPrefix = this.getPortalPrefix();
this.portalId = props.portalId;
this.setRef = this.setRef.bind(this);
this.ref = null; // this.portalDiv = document.createDocumentFragment();
}
setRef(ele) {
this.ref = ele;
if (this.isZIndexAppendNeeded) {
this.ref.style.zIndex = this.zIndex;
this.isZIndexAppendNeeded = false;
}
}
getRootElement() {
const getRootElement = getLibraryConfig('getRootElement');
if (getRootElement && typeof getRootElement === 'function') {
const parent = getRootElement();
if (parent) {
return parent;
}
}
return null;
}
getPortalPrefix() {
const portalPrefix = getLibraryConfig('portalPrefix');
return portalPrefix !== '' ? portalPrefix : '';
}
setPortalDiv() {
const modalRoot = this.props.portalId ? document.querySelector(`[data-portal=${this.portalPrefix}${this.props.portalId}]`) : '';
if (!modalRoot) {
this.portalId = this.handleAddPortalId();
this.newModalRoot = document.createElement('div');
this.newModalRoot.className = style.container;
this.newModalRoot.setAttribute('data-portal', `${this.portalPrefix}${this.portalId}`);
this.containerDiv && this.containerDiv.appendChild(this.newModalRoot);
}
}
componentDidMount() {
this.containerDiv = this.getRootElement() || document.getElementsByTagName('desk')[0] || document.getElementsByTagName('body')[0];
this.setPortalDiv();
this.setState({
isMounted: true
}, () => {
this.handleInsertPortalDiv();
});
}
componentWillUnmount() {
if (this.newModalRoot) {
this.containerDiv && this.containerDiv.removeChild(this.newModalRoot);
this.handleRemovePortalId();
}
if (this.zIndex && portalChildrenTopIndexValues === this.zIndex) {
portalChildrenTopIndexValues -= 1;
}
}
componentDidUpdate(prevProps) {
if (prevProps.isActive != this.props.isActive) {
if (this.props.isActive) {
this.handleInsertPortalDiv();
} else if (this.zIndex && portalChildrenTopIndexValues === this.zIndex) {
portalChildrenTopIndexValues -= 1;
}
}
}
handleInsertPortalDiv() {
let {
autoZIndexNeeded
} = this.props;
if (autoZIndexNeeded) {
let {
isActive
} = this.props;
if (isActive) {
let newHighValue = Number(portalChildrenTopIndexValues || 10) + 1;
portalChildrenTopIndexValues = newHighValue;
this.zIndex = newHighValue;
if (this.ref) {
this.ref.style.zIndex = newHighValue;
} else {
this.isZIndexAppendNeeded = true;
}
}
}
}
handleAddPortalId() {
let createdPortalIdsLen = createdPortalIds.length;
let newPortalId = createdPortalIdsLen ? createdPortalIds[createdPortalIdsLen - 1] + 1 : 1;
createdPortalIds.push(newPortalId);
this.portalId = newPortalId;
this.isCustomPortalId = true;
return `${newPortalPrefix}${newPortalId}`;
}
handleRemovePortalId() {
if (this.isCustomPortalId) {
createdPortalIds = createdPortalIds.filter(id => id !== this.portalId);
}
}
render() {
let {
children
} = this.props,
{
isMounted
} = this.state;
let Element = children.type,
elementProps = children.props;
if (isMounted) {
if (Element) {
return /*#__PURE__*/React.createElement(Portal, {
portalId: `${this.portalPrefix}${this.portalId}`
}, /*#__PURE__*/React.createElement(Element, {
ref: this.setRef,
...elementProps
}));
}
return null;
}
return null;
}
}
Modal.defaultProps = defaultProps;
Modal.propTypes = propTypes; // if (__DOCS__) {
// Modal.docs = {
// componentGroup: 'Atom',
// folderName: 'Style Guide',
// external: false,
// description: ' '
// };
// }