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(Popper) react-popper migration v1.3 #1376

Closed
wants to merge 2 commits into from
Closed
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
17 changes: 0 additions & 17 deletions __mocks__/react-popper.js

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -105,7 +105,7 @@
"lodash.tonumber": "^4.0.3",
"prop-types": "^15.5.8",
"react-lifecycles-compat": "^3.0.4",
"react-popper": "^0.10.4",
"react-popper": "^1.3.2",
"react-transition-group": "^2.3.1"
},
"peerDependencies": {
Expand Down
11 changes: 8 additions & 3 deletions src/Dropdown.js
Expand Up @@ -38,7 +38,7 @@ const defaultProps = {
};

const childContextTypes = {
toggle: PropTypes.func.isRequired,
toggle: PropTypes.func,
isOpen: PropTypes.bool.isRequired,
direction: PropTypes.oneOf(['up', 'down', 'left', 'right']).isRequired,
inNavbar: PropTypes.bool.isRequired,
Expand Down Expand Up @@ -206,12 +206,13 @@ class Dropdown extends React.Component {
setActiveFromChild,
active,
addonType,
tag,
...attrs
} = omit(this.props, ['toggle', 'disabled', 'inNavbar', 'direction']);

const direction = (this.props.direction === 'down' && dropup) ? 'up' : this.props.direction;

attrs.tag = attrs.tag || (nav ? 'li' : 'div');
const Tag = tag || (nav ? 'li' : 'div');

let subItemIsActive = false;
if (setActiveFromChild) {
Expand All @@ -237,7 +238,11 @@ class Dropdown extends React.Component {
}
), cssModule);

return <Manager {...attrs} className={classes} onKeyDown={this.handleKeyDown} />;
return (
<Manager>
<Tag {...attrs} className={classes} onKeyDown={this.handleKeyDown} />
</Manager>
);
}
}

Expand Down
25 changes: 21 additions & 4 deletions src/DropdownMenu.js
Expand Up @@ -49,16 +49,33 @@ const DropdownMenu = (props, context) => {
let Tag = tag;

if (persist || (context.isOpen && !context.inNavbar)) {
Tag = Popper;

const position1 = directionPositionMap[context.direction] || 'bottom';
const position2 = right ? 'end' : 'start';
attrs.placement = `${position1}-${position2}`;
const placement = `${position1}-${position2}`;

attrs.component = tag;
attrs.modifiers = !flip ? {

const popperModifiers = !flip ? {
...modifiers,
...noFlipModifier,
} : modifiers;

return (
<Popper modifiers={popperModifiers} placement={placement}>
{({ ref, style, placement }) => (
<Tag
tabIndex="-1"
ref={ref}
role="menu"
{...attrs}
style={{ ...attrs.style, ...style }}
aria-hidden={!context.isOpen}
className={classes}
x-placement={placement}
/>
)}
</Popper>
)
}

return (
Expand Down
28 changes: 18 additions & 10 deletions src/DropdownToggle.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Target } from 'react-popper';
import { Reference } from 'react-popper';
import { mapToCssModules, tagPropType } from './utils';
import Button from './Button';

Expand Down Expand Up @@ -33,7 +33,6 @@ const contextTypes = {
class DropdownToggle extends React.Component {
constructor(props) {
super(props);

this.onClick = this.onClick.bind(this);
}

Expand Down Expand Up @@ -80,6 +79,8 @@ class DropdownToggle extends React.Component {
Tag = tag;
}

const isStringTag = typeof Tag === 'string';

if (this.context.inNavbar) {
return (
<Tag
Expand All @@ -93,14 +94,21 @@ class DropdownToggle extends React.Component {
}

return (
<Target
{...props}
className={classes}
component={Tag}
onClick={this.onClick}
aria-expanded={this.context.isOpen}
children={children}
/>
<Reference>
{({ ref }) => (
<Tag
{ ...props }
{
...{ [ isStringTag ? 'ref' : 'innerRef' ]: ref }
// TODO: After https://github.com/reactstrap/reactstrap/pull/1356
}
className={classes}
onClick={this.onClick}
aria-expanded={this.context.isOpen}
children={children}
/>
)}
</Reference>
);
}
}
Expand Down
20 changes: 16 additions & 4 deletions src/PopperContent.js
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import { Arrow, Popper as ReactPopper } from 'react-popper';
import { Popper as ReactPopper } from 'react-popper';
import { getTarget, targetPropType, mapToCssModules, DOMElement, tagPropType } from './utils';
import Fade from './Fade';

Expand Down Expand Up @@ -172,9 +172,21 @@ class PopperContent extends React.Component {
onExited={this.onClosed}
tag={tag}
>
<ReactPopper modifiers={extendedModifiers} className={popperClassName} x-placement={this.state.placement || attrs.placement} placement={this.state.placement || attrs.placement}>
{children}
{!hideArrow && <Arrow className={arrowClassName} />}
<ReactPopper referenceElement={ target && document.getElementById(target) } modifiers={extendedModifiers} placement={this.state.placement || attrs.placement}>
{
({ ref, style, placement, arrowProps }) => (
<div ref={ref} style={style} className={popperClassName} x-placement={placement}>
{children}
{!hideArrow && (
<span
className={'arrow'}
ref={arrowProps.ref}
style={arrowProps.style}
/>
)}
</div>
)
}
</ReactPopper>
</Fade>
);
Expand Down
24 changes: 12 additions & 12 deletions src/__tests__/Dropdown.spec.js
@@ -1,6 +1,6 @@
import React from 'react';
import { mount, shallow } from 'enzyme';
import { Popper, Target } from 'react-popper';
import { Popper, Reference } from 'react-popper';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from '../';
import { keyCodes } from '../utils';

Expand Down Expand Up @@ -975,8 +975,8 @@ describe('Dropdown', () => {
</Dropdown>
);

expect(wrapper.find('.dropdown-toggle').first().type()).toEqual('a');
expect(wrapper.find('.dropdown-menu').first().type()).toEqual('div');
expect(wrapper.childAt(0).find('.dropdown-toggle').first().type()).toEqual('a');
expect(wrapper.childAt(0).find('.dropdown-menu').first().type()).toEqual('div');
});

it('should open with popper without inNavbar prop', () => {
Expand All @@ -989,17 +989,17 @@ describe('Dropdown', () => {
</DropdownMenu>
</Dropdown>
);

expect(wrapper.find('.dropdown-toggle').first().type()).toEqual(Target);
expect(wrapper.find('.dropdown-menu').first().type()).toEqual(Popper);
expect(wrapper.find(Reference).childAt(0).childAt(0).hasClass('dropdown-toggle')).toEqual(true);
expect(wrapper.find(Popper).childAt(0).childAt(0).hasClass('dropdown-menu')).toEqual(true);
});
});

describe('active', () => {
it('should render an active class', () => {
const wrapper = shallow(<Dropdown active nav />);

expect(wrapper.hasClass('active')).toBe(true);
expect(wrapper.childAt(0).hasClass('active')).toBe(true);
});

it('should render an active class when a child DropdownItem is active IF setActiveFromChild is true', () => {
Expand All @@ -1016,7 +1016,7 @@ describe('Dropdown', () => {
</Dropdown>
);

expect(wrapper.hasClass('active')).toBe(true);
expect(wrapper.childAt(0).hasClass('active')).toBe(true);
});
});

Expand All @@ -1026,9 +1026,9 @@ describe('Dropdown', () => {
const dropleft = shallow(<Dropdown direction="left" />);
const dropright = shallow(<Dropdown direction="right" />);

expect(dropup.hasClass('dropup')).toBe(true);
expect(dropupProp.hasClass('dropup')).toBe(true);
expect(dropleft.hasClass('dropleft')).toBe(true);
expect(dropright.hasClass('dropright')).toBe(true);
expect(dropup.childAt(0).hasClass('dropup')).toBe(true);
expect(dropupProp.childAt(0).hasClass('dropup')).toBe(true);
expect(dropleft.childAt(0).hasClass('dropleft')).toBe(true);
expect(dropright.childAt(0).hasClass('dropright')).toBe(true);
});
});