type Modal = { ref: HTMLElement | null; prevStyle?: CSSStyleDeclaration };
type Parent = {
modals: Modal[];
parentNode: Modal;
};
export default class Handler {
// track all the modals mounted
private parent: Parent[];
constructor() {
this.parent = [];
}
static handleStyle(parentNode: Modal) {
if (parentNode.ref) {
parentNode.prevStyle = { ...parentNode.ref.style };
// Apply styles here
parentNode.ref.style.overflow = 'hidden';
}
}
static restoreStyle(parentNode: Modal) {
if (parentNode.ref && parentNode.prevStyle) {
// remove all styles here
/**
* Case:- In safari browsers undefined is not setting the css for overflow styly so added the "" as a fallback.
*/
parentNode.ref.style.overflow = parentNode.prevStyle.overflow || '';
}
}
mount(modal: Modal, parentNode: Modal = { ref: null }) {
// add modal with parent
if (parentNode.ref) {
const parentIndex = this.parent.findIndex((node) => node.parentNode === parentNode);
if (parentIndex !== -1) {
this.parent[parentIndex].modals.push(modal);
} else {
this.parent.push({
parentNode,
modals: [modal],
});
}
Handler.handleStyle(parentNode);
} else {
// get top modal, if not get the body;
const parent = this.getTopModal();
parent.modals.push(modal);
Handler.handleStyle(parent.parentNode);
if (parent.parentNode.ref !== document.body) {
this.parent.push({
parentNode: modal,
modals: [],
});
} else {
this.parent.push(parent);
}
}
}
getTopModal(): Parent {
if (this.parent.length) {
return this.parent[this.parent.length - 1];
} else {
return { parentNode: { ref: document.body, prevStyle: document.body.style }, modals: [] };
}
}
remove(modal: Modal) {
const parentNode = this.parent.find((node) => node.modals.find((_modal) => _modal.ref === modal.ref));
if (parentNode) {
Handler.restoreStyle(parentNode.parentNode);
}
}
}