Skip to content

Commit

Permalink
Add/2793: Allow popover position to be overriden by prop getAnchorRect
Browse files Browse the repository at this point in the history
  • Loading branch information
tiny-james committed Nov 3, 2017
1 parent bbae623 commit b9871c6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 25 deletions.
20 changes: 18 additions & 2 deletions components/autocomplete/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export class Autocomplete extends Component {
this.reset = this.reset.bind( this );
this.search = this.search.bind( this );
this.setSelectedIndex = this.setSelectedIndex.bind( this );
this.getWordRect = this.getWordRect.bind( this );

this.state = this.constructor.getInitialState();
}
Expand Down Expand Up @@ -346,6 +347,21 @@ export class Autocomplete extends Component {
event.stopPropagation();
}

getWordRect( { isLeft, isRight } ) {
const { range } = this.state;
if ( ! range ) {
return;
}
if ( isLeft ) {
const rects = range.getClientRects();
return rects[ 0 ];
} else if ( isRight ) {
const rects = range.getClientRects();
return rects[ rects.length - 1 ];
}
return range.getBoundingClientRect();
}

toggleKeyEvents( isListening ) {
// This exists because we must capture ENTER key presses before Editable.
// It seems that react fires the simulated capturing events after the
Expand Down Expand Up @@ -373,7 +389,7 @@ export class Autocomplete extends Component {

render() {
const { children, instanceId } = this.props;
const { open, selectedIndex, range } = this.state;
const { open, selectedIndex } = this.state;
const { className } = open || {};
const classes = classnames( 'components-autocomplete__popover', className );
const filteredOptions = this.getFilteredOptions();
Expand All @@ -394,7 +410,7 @@ export class Autocomplete extends Component {
onClose={ this.reset }
position="top right"
className={ classes }
range={ range }
getAnchorRect={ this.getWordRect }
>
<ul
id={ listBoxId }
Expand Down
48 changes: 25 additions & 23 deletions components/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Popover extends Component {

this.focus = this.focus.bind( this );
this.bindNode = this.bindNode.bind( this );
this.getAnchorRect = this.getAnchorRect.bind( this );
this.setOffset = this.setOffset.bind( this );
this.throttledSetOffset = this.throttledSetOffset.bind( this );
this.maybeClose = this.maybeClose.bind( this );
Expand Down Expand Up @@ -132,36 +133,36 @@ class Popover extends Component {
this.rafHandle = window.requestAnimationFrame( this.setOffset );
}

setOffset() {
const { range } = this.props;
const { anchor, popover } = this.nodes;
getAnchorRect( ) {
const { anchor } = this.nodes;
if ( ! anchor || ! anchor.parentNode ) {
return;
}
const rect = anchor.parentNode.getBoundingClientRect();
// subtract padding
const { paddingTop, paddingBottom } = window.getComputedStyle( anchor.parentNode );
const topPad = parseInt( paddingTop, 10 );
const bottomPad = parseInt( paddingBottom, 10 );
return {
...rect,
top: rect.top + topPad,
bottom: rect.bottom - bottomPad,
height: rect.height - topPad - bottomPad,
};
}

setOffset() {
const { getAnchorRect = this.getAnchorRect } = this.props;
const { popover } = this.nodes;

const [ yAxis, xAxis ] = this.getPositions();
const isTop = 'top' === yAxis;
const isLeft = 'left' === xAxis;
const isRight = 'right' === xAxis;
let rect;
let topOffset = 0;
if ( range ) {
const rects = range.getClientRects();
if ( isLeft ) {
rect = rects[ 0 ];
} else if ( isRight ) {
rect = rects[ rects.length - 1 ];
} else {
rect = range.getBoundingClientRect();
}
} else {
rect = anchor.parentNode.getBoundingClientRect();
// Offset top positioning by padding
const { paddingTop, paddingBottom } = window.getComputedStyle( anchor.parentNode );
topOffset = parseInt( isTop ? paddingTop : paddingBottom, 10 );
if ( ! isTop ) {
topOffset *= -1;
}

const rect = getAnchorRect( { isTop, isLeft, isRight } );
if ( ! rect ) {
return;
}

if ( isRight ) {
Expand All @@ -174,7 +175,7 @@ class Popover extends Component {
}

// Set at top or bottom of parent node based on popover position
popover.style.top = ( rect[ yAxis ] + topOffset ) + 'px';
popover.style.top = rect[ yAxis ] + 'px';
}

setForcedPositions() {
Expand Down Expand Up @@ -238,6 +239,7 @@ class Popover extends Component {
position,
range,
focusOnOpen,
getAnchorRect,
/* eslint-enable no-unused-vars */
...contentProps
} = this.props;
Expand Down

0 comments on commit b9871c6

Please sign in to comment.