1 | import { OPEN_UP, ANCHOR_RIGHT } from '../constants';
|
2 |
|
3 | /**
|
4 | * Calculate and return a CSS transform style to position a detached element
|
5 | * next to a reference element. The open and anchor direction indicate wether
|
6 | * it should be positioned above/below and/or to the left/right of the
|
7 | * reference element.
|
8 | *
|
9 | * Assuming r(0,0), r(1,1), d(0,0), d(1,1) for the bottom-left and top-right
|
10 | * corners of the reference and detached elements, respectively:
|
11 | * - openDirection = DOWN, anchorDirection = LEFT => d(0,1) == r(0,1)
|
12 | * - openDirection = UP, anchorDirection = LEFT => d(0,0) == r(0,0)
|
13 | * - openDirection = DOWN, anchorDirection = RIGHT => d(1,1) == r(1,1)
|
14 | * - openDirection = UP, anchorDirection = RIGHT => d(1,0) == r(1,0)
|
15 | *
|
16 | * By using a CSS transform, we allow to further position it using
|
17 | * top/bottom CSS properties for the anchor gutter.
|
18 | *
|
19 | * @param {string} openDirection The vertical positioning of the popup
|
20 | * @param {string} anchorDirection The horizontal position of the popup
|
21 | * @param {HTMLElement} referenceEl The reference element
|
22 | */
|
23 | export default function getDetachedContainerStyles(openDirection, anchorDirection, referenceEl) {
|
24 | const referenceRect = referenceEl.getBoundingClientRect();
|
25 | let offsetX = referenceRect.left;
|
26 | let offsetY = referenceRect.top;
|
27 |
|
28 | if (openDirection === OPEN_UP) {
|
29 | offsetY = -(window.innerHeight - referenceRect.bottom);
|
30 | }
|
31 |
|
32 | if (anchorDirection === ANCHOR_RIGHT) {
|
33 | offsetX = -(window.innerWidth - referenceRect.right);
|
34 | }
|
35 |
|
36 | return {
|
37 | transform: `translate3d(${Math.round(offsetX)}px, ${Math.round(offsetY)}px, 0)`,
|
38 | };
|
39 | }
|