Skip to content

Commit

Permalink
chore: use hook with modal manager (#453)
Browse files Browse the repository at this point in the history
  • Loading branch information
pradel committed Nov 15, 2020
1 parent 9a06a62 commit b016ec4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 29 deletions.
19 changes: 11 additions & 8 deletions react-responsive-modal/src/index.tsx
Expand Up @@ -3,7 +3,7 @@ import ReactDom from 'react-dom';
import cx from 'classnames';
import CloseIcon from './CloseIcon';
import { FocusTrap } from './FocusTrap';
import modalManager from './modalManager';
import { modalManager, useModalManager } from './modalManager';
import { isBrowser, blockNoScroll, unblockNoScroll } from './utils';

const classes = {
Expand Down Expand Up @@ -172,8 +172,10 @@ export const Modal = ({
// it will match the server rendered content
const [showPortal, setShowPortal] = useState(false);

// Hook used to manage multiple modals opened at the same time
useModalManager(refModal, open, blockScroll);

const handleOpen = () => {
modalManager.add(refContainer.current!, blockScroll);
if (blockScroll) {
blockNoScroll();
}
Expand All @@ -188,8 +190,12 @@ export const Modal = ({
};

const handleClose = () => {
modalManager.remove(refContainer.current!);
if (blockScroll) {
// Restore the scroll only if there is no modal on the screen
// We filter the modals that are not affecting the scroll
if (
blockScroll &&
modalManager.modals().filter((modal) => modal.blockScroll).length === 0
) {
unblockNoScroll();
}
if (
Expand All @@ -204,10 +210,7 @@ export const Modal = ({

const handleKeydown = (event: KeyboardEvent) => {
// Only the last modal need to be escaped when pressing the esc key
if (
event.keyCode !== 27 ||
!modalManager.isTopModal(refContainer.current!)
) {
if (event.keyCode !== 27 || !modalManager.isTopModal(refModal)) {
return;
}

Expand Down
40 changes: 26 additions & 14 deletions react-responsive-modal/src/modalManager.ts
@@ -1,10 +1,12 @@
const modals: { element: HTMLDivElement; blockScroll: boolean }[] = [];
import { Ref, useEffect } from 'react';

let modals: { element: Ref<any>; blockScroll: boolean }[] = [];

/**
* Handle the order of the modals.
* Inspired by the material-ui implementation.
*/
export default {
export const modalManager = {
/**
* Return the modals array
*/
Expand All @@ -13,25 +15,35 @@ export default {
/**
* Register a new modal
*/
add: (newModal: HTMLDivElement, blockScroll: boolean) => {
if (modals.findIndex((modal) => modal.element === newModal) === -1) {
modals.push({ element: newModal, blockScroll });
}
add: (newModal: Ref<any>, blockScroll: boolean) => {
modals.push({ element: newModal, blockScroll });
},

/**
* Remove a modal
*/
remove: (oldModal: HTMLDivElement) => {
const index = modals.findIndex((modal) => modal.element === oldModal);
if (index !== -1) {
modals.splice(index, 1);
}
remove: (oldModal: Ref<any>) => {
modals = modals.filter((modal) => modal.element !== oldModal);
},

/**
* Check if the modal is the first one on the screen
* When multiple modals are rendered will return true if current modal is the last one
*/
isTopModal: (modal: HTMLDivElement) =>
!!modals.length && modals[modals.length - 1]?.element === modal,
isTopModal: (modal: Ref<any>) =>
!!modals.length && modals[modals.length - 1].element === modal,
};

export function useModalManager(
ref: Ref<any>,
open: boolean,
blockScroll: boolean
) {
useEffect(() => {
if (open) {
modalManager.add(ref, blockScroll);
}
return () => {
modalManager.remove(ref);
};
}, [open, ref]);
}
8 changes: 1 addition & 7 deletions react-responsive-modal/src/utils.ts
@@ -1,5 +1,4 @@
import noScroll from 'no-scroll';
import modalManager from './modalManager';

export const isBrowser = typeof window !== 'undefined';

Expand All @@ -8,10 +7,5 @@ export const blockNoScroll = () => {
};

export const unblockNoScroll = () => {
// Restore the scroll only if there is no modal on the screen
// We filter the modals that are not affecting the scroll
const modals = modalManager.modals().filter((modal) => modal.blockScroll);
if (modals.length === 0) {
noScroll.off();
}
noScroll.off();
};

0 comments on commit b016ec4

Please sign in to comment.