openreplay/frontend/app/components/hocs/withOverlay.js
2025-03-25 17:39:14 +01:00

88 lines
2.3 KiB
JavaScript

import React from 'react';
let overlayedCount = 0;
const ID = 'openreplay-overlay';
const Z_BASE = 99990;
const overlay = document.createElement('div');
overlay.setAttribute('id', ID);
// TODO: use className (class attribute)
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
overlay.style.position = 'fixed';
overlay.style.left = 0;
overlay.style.right = 0;
overlay.style.bottom = 0;
overlay.style.top = 0;
overlay.style.zIndex = Z_BASE;
const withOverlay =
(
overlayedName = 'overlayed',
clickHandlerName = 'onOverlayClick',
zIndex = 0,
) =>
(BaseComponent) =>
class extends React.Component {
constructor(props) {
super(props);
this.baseRef = React.createRef();
if (props[overlayedName]) {
overlayedCount++;
}
}
componentDidMount() {
this.renderOverlay();
this.setOverlayedStyles();
}
componentDidUpdate(prevProps) {
if (prevProps[overlayedName] !== this.props[overlayedName]) {
if (!this.props[overlayedName]) {
overlayedCount--;
}
if (this.props[overlayedName]) {
overlayedCount++;
}
this.renderOverlay();
this.setOverlayedStyles();
}
}
clickHandler = () => {
const clickHandler = this.props[clickHandlerName];
if (clickHandler) clickHandler();
};
renderOverlay() {
if (overlayedCount > 0) {
if (overlay.parentNode === null) {
document.body.appendChild(overlay);
}
if (this.props[overlayedName]) {
overlay.addEventListener('click', this.clickHandler);
}
} else if (overlay.parentNode !== null) {
overlay.parentNode.removeChild(overlay);
}
}
setOverlayedStyles() {
const baseRoot = this.baseRef.current;
const overlayed = this.props[overlayedName];
const actualZIndex = Z_BASE + 1 + zIndex;
if (baseRoot) {
// TODO: care about styles rewriting case
baseRoot.style.position = 'relative';
baseRoot.style.zIndex = overlayed ? actualZIndex : 'initial';
}
}
render() {
return <BaseComponent {...this.props} ref={this.baseRef} />;
}
};
export default withOverlay;