Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: referenceNode support for reference objects (closes #800) #801

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/popper/index.d.ts
Expand Up @@ -133,6 +133,7 @@ declare namespace Popper {
export interface ReferenceObject {
clientHeight: number;
clientWidth: number;
referenceNode?: Node;

getBoundingClientRect(): ClientRect;
}
Expand Down
1 change: 1 addition & 0 deletions packages/popper/index.js.flow
Expand Up @@ -118,6 +118,7 @@ declare module 'popper.js' {
declare type ReferenceObject = {
+clientHeight: number,
+clientWidth: number,
+referenceNode?: Node,

getBoundingClientRect():
| ClientRect
Expand Down
3 changes: 2 additions & 1 deletion packages/popper/src/utils/getBoundaries.js
@@ -1,5 +1,6 @@
import getScrollParent from './getScrollParent';
import getParentNode from './getParentNode';
import getReferenceNode from './getReferenceNode';
import findCommonOffsetParent from './findCommonOffsetParent';
import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode';
import getViewportOffsetRectRelativeToArtbitraryNode from './getViewportOffsetRectRelativeToArtbitraryNode';
Expand Down Expand Up @@ -28,7 +29,7 @@ export default function getBoundaries(
// NOTE: 1 DOM access here

let boundaries = { top: 0, left: 0 };
const offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
const offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));

// Handle viewport case
if (boundariesElement === 'viewport' ) {
Expand Down
10 changes: 10 additions & 0 deletions packages/popper/src/utils/getReferenceNode.js
@@ -0,0 +1,10 @@
/**
* Returns the reference node of the reference object, or the reference object itself.
* @method
* @memberof Popper.Utils
* @param {Element|Object} reference - the reference element (the popper will be relative to this)
* @returns {Element} parent
*/
export default function getReferenceNode(reference) {
return reference && reference.referenceNode ? reference.referenceNode : reference;
}
3 changes: 2 additions & 1 deletion packages/popper/src/utils/getReferenceOffsets.js
@@ -1,6 +1,7 @@
import findCommonOffsetParent from './findCommonOffsetParent';
import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode';
import getFixedPositionOffsetParent from './getFixedPositionOffsetParent';
import getReferenceNode from './getReferenceNode';

/**
* Get offsets to the reference element
Expand All @@ -13,6 +14,6 @@ import getFixedPositionOffsetParent from './getFixedPositionOffsetParent';
* @returns {Object} An object containing the offsets which will be applied to the popper
*/
export default function getReferenceOffsets(state, popper, reference, fixedPosition = null) {
const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
}
44 changes: 44 additions & 0 deletions packages/popper/tests/functional/core.js
Expand Up @@ -1428,6 +1428,50 @@ const arrowSize = 5;
});
});

it('uses a reference object with a referenceNode to position its popper', done => {
// As above
if (isIE10) {
pending();
}

jasmineWrapper.innerHTML = `
<div id="reference" style="position: absolute; left: 10px; top: 10px; right: 10px; bottom: 10px;">
<div id="popper" style="background: purple;">popper</div>
</div>
`;

const popper = document.getElementById('popper');

const reference = {
getBoundingClientRect() {
return {
top: 10,
left: 100,
right: 150,
bottom: 90,
width: 50,
height: 80,
};
},
clientWidth: 50,
clientHeight: 80,
referenceNode: document.getElementById('reference'),
};

new Popper(reference, popper, {
placement: 'bottom-start',
onCreate() {
expect(getRect(popper).top).toBe(
reference.getBoundingClientRect().bottom
);
expect(getRect(popper).left).toBe(
reference.getBoundingClientRect().left
);
done();
},
});
});

it('checks cases where the reference element is fixed', done => {
jasmineWrapper.innerHTML = `
<div id="reference" style="position: fixed; top: 100px; left: 100px; background: pink">reference</div>
Expand Down