UNPKG

@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
/**** 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: ' ' // }; // }