Skip to content

Commit d52e00f

Browse files
authored
chore: Release 5.7.0 (#160)
1 parent 8a1e104 commit d52e00f

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { getViewportSize } from '../../commons/dom';
2+
export default function detectModalStack(options) {
3+
options = options || {};
4+
const modalPercent = options.modalPercent || 0.75;
5+
6+
// there is no "definitive" way to code a modal so detecting when one is open
7+
// is a bit of a guess. a modal won't always be accessible, so we can't rely
8+
// on the `role` attribute, and relying on a class name as a convention is
9+
// unreliable. we also cannot rely on the body/html not scrolling.
10+
//
11+
// because of this, we will look for two different types of modals:
12+
// "definitely a modal" and "could be a modal."
13+
//
14+
// "definitely a modal" is any visible element that is coded to be a modal
15+
// by using one of the following criteria:
16+
//
17+
// - has the attribute `role=dialog`
18+
// - has the attribute `aria-modal=true`
19+
// - is the dialog element
20+
//
21+
// "could be a modal" is a visible element that takes up more than 75% of
22+
// the screen (though typically full width/height) and is the top-most element
23+
// in the viewport. since we aren't sure if it is or is not a modal this is
24+
// just our best guess of being one based on convention.
25+
26+
const definiteModals = Array.from(
27+
document.querySelectorAll(
28+
'dialog[open], [role="dialog"], [role="alertdialog"], [aria-modal="true"]'
29+
)
30+
);
31+
32+
// to find a "could be a modal" we will take the element stack from each of
33+
// four corners and one from the middle of the viewport (total of 5). if each
34+
// stack contains an element whose width/height is >= 75% of the screen, we
35+
// found a "could be a modal"
36+
const viewport = getViewportSize(window);
37+
const percentWidth = viewport.width * modalPercent;
38+
const percentHeight = viewport.height * modalPercent;
39+
const x = (viewport.width - percentWidth) / 2;
40+
const y = (viewport.height - percentHeight) / 2;
41+
42+
const points = [
43+
// top-left corner
44+
{ x, y },
45+
// top-right corner
46+
{ x: viewport.width - x, y },
47+
// center
48+
{ x: viewport.width / 2, y: viewport.height / 2 },
49+
// bottom-left corner
50+
{ x, y: viewport.height - y },
51+
// bottom-right corner
52+
{ x: viewport.width - x, y: viewport.height - y }
53+
];
54+
55+
const stacks = points.map(point => {
56+
return Array.from(document.elementsFromPoint(point.x, point.y));
57+
});
58+
59+
return { definiteModals, stacks };
60+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { getViewportSize } from '../../commons/dom';
2+
3+
export default function getOverlayFromStack(elm, options) {
4+
options = options || {};
5+
const modalPercent = options.modalPercent || 0.75;
6+
7+
const viewport = getViewportSize(window);
8+
const percentWidth = viewport.width * modalPercent;
9+
const percentHeight = viewport.height * modalPercent;
10+
11+
if (elm instanceof window.Element) {
12+
const style = window.getComputedStyle(elm);
13+
const rect = elm.getBoundingClientRect();
14+
if (
15+
rect.width >= percentWidth &&
16+
rect.height >= percentHeight &&
17+
style?.getPropertyValue('pointer-events') !== 'none' &&
18+
(style?.position === 'absolute' || style?.position === 'fixed')
19+
) {
20+
return true;
21+
}
22+
}
23+
return false;
24+
}

lib/core/utils/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,5 @@ export { default as uniqueArray } from './unique-array';
8686
export { default as uuid } from './uuid';
8787
export { default as validInputTypes } from './valid-input-type';
8888
export { default as isValidLang, validLangs } from './valid-langs';
89+
export { default as detectModalStack } from './detect-modal-stack';
90+
export { default as getOverlayFromStack } from './get-overlay-from-stack';

0 commit comments

Comments
 (0)