From 975164c885c1879a5a6b630108b5b84fac48f4d9 Mon Sep 17 00:00:00 2001 From: Buchheit Date: Thu, 12 Apr 2018 11:42:18 -0400 Subject: [PATCH] feat: Add specific padding to boundaries (#518) --- packages/popper/src/utils/getBoundaries.js | 10 +- packages/popper/src/utils/getWindowSizes.js | 8 +- packages/popper/tests/unit/getBoundaries.js | 98 +++++++++++++++++++ .../tests/unit/getBoundaries.padding.js | 72 ++++++++++++++ 4 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 packages/popper/tests/unit/getBoundaries.js create mode 100644 packages/popper/tests/unit/getBoundaries.padding.js diff --git a/packages/popper/src/utils/getBoundaries.js b/packages/popper/src/utils/getBoundaries.js index ae6583a042..6c7d3a7685 100644 --- a/packages/popper/src/utils/getBoundaries.js +++ b/packages/popper/src/utils/getBoundaries.js @@ -69,10 +69,12 @@ export default function getBoundaries( } // Add paddings - boundaries.left += padding; - boundaries.top += padding; - boundaries.right -= padding; - boundaries.bottom -= padding; + padding = padding || 0; + const isPaddingNumber = typeof padding === 'number'; + boundaries.left += isPaddingNumber ? padding : padding.left || 0; + boundaries.top += isPaddingNumber ? padding : padding.top || 0; + boundaries.right -= isPaddingNumber ? padding : padding.right || 0; + boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0; return boundaries; } diff --git a/packages/popper/src/utils/getWindowSizes.js b/packages/popper/src/utils/getWindowSizes.js index a81f106154..1437ad43e3 100644 --- a/packages/popper/src/utils/getWindowSizes.js +++ b/packages/popper/src/utils/getWindowSizes.js @@ -8,10 +8,10 @@ function getSize(axis, body, html, computedStyle) { html[`offset${axis}`], html[`scroll${axis}`], isIE(10) - ? html[`offset${axis}`] + - computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`] + - computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`] - : 0 + ? (parseInt(html[`offset${axis}`]) + + parseInt(computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`]) + + parseInt(computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`])) + : 0 ); } diff --git a/packages/popper/tests/unit/getBoundaries.js b/packages/popper/tests/unit/getBoundaries.js new file mode 100644 index 0000000000..02e8bb5b12 --- /dev/null +++ b/packages/popper/tests/unit/getBoundaries.js @@ -0,0 +1,98 @@ +import getBoundaries from '../../src/utils/getBoundaries'; +import isIE from '../../src/utils/isIE'; + +describe('utils/getBoundaries', () => { + let node; + let spacing; + let scrolling; + let scrollingChild; + let popper; + let scrollingPopper; + + function setCss(element, css) { + for (const key in css) { + if (css.hasOwnProperty(key)) { + element.style[key] = css[key]; + } + } + } + function expectBoundary(result, expected) { + const tolerance = 2; + expect(Math.abs(result.top - expected.top) <= tolerance).toBeTruthy(); + expect(Math.abs(result.right - expected.right) <= tolerance).toBeTruthy(); + expect(Math.abs(result.bottom - expected.bottom) <= tolerance).toBeTruthy(); + expect(Math.abs(result.left - expected.left) <= tolerance).toBeTruthy(); + } + + beforeEach(() => { + node = document.createElement('div'); + spacing = document.createElement('div'); + popper = document.createElement('div'); + scrollingPopper = document.createElement('div'); + + scrolling = document.createElement('div'); + setCss(scrolling, { + top: '150px', + left: '160px', + right: '300px', + bottom: '400px', + height: '150px', + width: '125px', + }); + + scrollingChild = document.createElement('div'); + setCss(scrollingChild, { + overflow: 'scroll', + top: '50px', + left: '60px', + right: '-100px', + bottom: '-200px', + height: '350px', + width: '625px', + position: 'absolute', + transform: 'translate3d(100px, 100px, 0)', + willChange: 'transform', + }); + + document.body.appendChild(node); + node.appendChild(spacing); + node.appendChild(scrolling); + node.appendChild(popper); + scrolling.appendChild(scrollingChild); + scrollingChild.appendChild(scrollingPopper); + }); + + afterEach(() => { + document.body.removeChild(node); + }); + + it('returns a boundary defined by the document element.', () => { + const result = getBoundaries(popper, node, 0, 'window', true); + expectBoundary(result, { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0, + }); + }); + + it('returns a boundary defined by the document element by way of a child reference.', () => { + const result = getBoundaries(popper, spacing, 0, 'scrollParent', true); + expectBoundary(result, { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0, + }); + }); + + it('returns a custom defined boundary within the page.', () => { + const result = getBoundaries(scrollingPopper, scrollingChild, 0, 'scrollParent', false); + expectBoundary(result, { + top: -150, + right: window.innerWidth - 160, + bottom: window.innerHeight - 150, + left: -160, + }); + }); +}); \ No newline at end of file diff --git a/packages/popper/tests/unit/getBoundaries.padding.js b/packages/popper/tests/unit/getBoundaries.padding.js new file mode 100644 index 0000000000..e1e6544649 --- /dev/null +++ b/packages/popper/tests/unit/getBoundaries.padding.js @@ -0,0 +1,72 @@ +import getBoundaries from '../../src/utils/getBoundaries'; + +describe('utils/getBoundaries-padding-offset', () => { + let node; + + beforeEach(() => { + node = document.createElement('div'); + document.body.appendChild(node); + }); + + afterEach(() => { + document.body.removeChild(node); + }); + + function expectBoundary(result, expected) { + const tolerance = 2; + expect(Math.abs(result.top - expected.top) <= tolerance).toBeTruthy(); + expect(Math.abs(result.right - expected.right) <= tolerance).toBeTruthy(); + expect(Math.abs(result.bottom - expected.bottom) <= tolerance).toBeTruthy(); + expect(Math.abs(result.left - expected.left) <= tolerance).toBeTruthy(); + } + + it('returns a boundary with a single value padding offset.', () => { + const padding = 50; + const result = getBoundaries(null, null, padding, 'viewport', true); + expectBoundary(result, { + top: 50, + right: window.innerWidth - 50, + bottom: window.innerHeight - 50, + left: 50, + }); + }); + + it('returns a boundary with a top and left componentized padding offset.', () => { + const padding = { + top: 50, + left: 100, + }; + const result = getBoundaries(null, null, padding, 'viewport', true); + expectBoundary(result, { + top: 50, + right: window.innerWidth, + bottom: window.innerHeight, + left: 100, + }); + }); + + it('returns a boundary with a bottom and right componentized padding offset.', () => { + const padding = { + bottom: 50, + right: 85, + }; + const result = getBoundaries(null, null, padding, 'viewport', true); + expectBoundary(result, { + top: 0, + right: window.innerWidth - 85, + bottom: window.innerHeight - 50, + left: 0, + }); + }); + + it('returns a boundary with a null padding offset.', () => { + const padding = null; + const result = getBoundaries(null, null, padding, 'viewport', true); + expectBoundary(result, { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0, + }); + }); +}); \ No newline at end of file