Skip to content

Commit

Permalink
feat!: upgrade to popper 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Phoebe Gao authored and phwebi committed Oct 27, 2021
1 parent c0e8a68 commit 35840ef
Show file tree
Hide file tree
Showing 15 changed files with 182 additions and 139 deletions.
4 changes: 2 additions & 2 deletions docs/lib/Components/DropdownsPage.js
Expand Up @@ -98,8 +98,8 @@ DropdownMenu.propTypes = {
flip: PropTypes.bool, // default: true,
className: PropTypes.string,
cssModule: PropTypes.object,
// Custom modifiers that are passed to DropdownMenu.js, see https://popper.js.org/popper-documentation.html#modifiers
modifiers: PropTypes.object,
// Custom modifiers that are passed to Popper.js, see https://popper.js.org/docs/v2/modifiers/
modifiers: PropTypes.array,
persist: PropTypes.bool, // presist the popper, even when closed. See #779 for reasoning
// passed to popper, see https://popper.js.org/popper-documentation.html#Popper.Defaults.positionFixed
positionFixed: PropTypes.bool,
Expand Down
19 changes: 8 additions & 11 deletions docs/lib/Components/PopoversPage.js
Expand Up @@ -11,8 +11,8 @@ import PopoverFocusExample from '../examples/PopoverFocus';
const PopoverFocusExampleSource = require('!!raw-loader!../examples/PopoverFocus');
import UncontrolledPopoverExample from '../examples/PopoverUncontrolled';
const UncontrolledPopoverExampleSource = require('!!raw-loader!../examples/PopoverUncontrolled');
import PopoverScheduleUpdateExample from '../examples/PopoverScheduleUpdate';
const PopoverScheduleUpdateExampleSource = require('!!raw-loader!../examples/PopoverScheduleUpdate');
import PopoverUpdateExample from '../examples/PopoverUpdate';
const PopoverUpdateExampleSource = require('!!raw-loader!../examples/PopoverUpdate');

export default class PopoversPage extends React.Component {
render() {
Expand Down Expand Up @@ -77,15 +77,12 @@ export default class PopoversPage extends React.Component {
'left-start',
'left-end',
]),
// Custom modifiers that are passed to Popper.js, see https://popper.js.org/popper-documentation.html#modifiers
modifiers: PropTypes.object,
// Custom modifiers that are passed to Popper.js, see https://popper.js.org/docs/v2/modifiers/
modifiers: PropTypes.array,
// Whether the element the tooltip is pointing to has "position: fixed" styling. This is passed to Popper.js and
// will make the tooltip itself have "position: fixed" as well
positionFixed: PropTypes.bool,
offset: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]),
offset: PropTypes.arrayOf(PropTypes.number),
// Whether to show/hide the popover with a fade effect
// (default: true)
Expand Down Expand Up @@ -129,15 +126,15 @@ export default class PopoversPage extends React.Component {
<SectionTitle>Repositioning Popovers</SectionTitle>
<p>
If you need to reposition a popover due to content changes or target placement changes, use
the <code>scheduleUpdate</code> function to manually reposition it. This function is exposed
the <code>update</code> function to manually reposition it. This function is exposed
as a render prop for <code>children</code>.
</p>
<div className="docs-example">
<PopoverScheduleUpdateExample />
<PopoverUpdateExample />
</div>
<pre>
<PrismCode className="language-jsx">
{PopoverScheduleUpdateExampleSource}
{PopoverUpdateExampleSource}
</PrismCode>
</pre>
</div>
Expand Down
19 changes: 8 additions & 11 deletions docs/lib/Components/TooltipsPage.js
Expand Up @@ -11,8 +11,8 @@ import TooltipExampleMulti from '../examples/TooltipMulti';
const TooltipExampleMultiSource = require('!!raw-loader!../examples/TooltipMulti');
import TooltipExampleUncontrolled from '../examples/TooltipUncontrolled';
const TooltipExampleUncontrolledSource = require('!!raw-loader!../examples/TooltipUncontrolled');
import TooltipScheduleUpdateExample from '../examples/TooltipScheduleUpdate';
const TooltipScheduleUpdateExampleSource = require('!!raw-loader!../examples/TooltipScheduleUpdate');
import TooltipUpdateExample from '../examples/TooltipUpdate';
const TooltipUpdateExampleSource = require('!!raw-loader!../examples/TooltipUpdate');

export default class TooltipsPage extends React.Component {
render() {
Expand Down Expand Up @@ -82,15 +82,12 @@ export default class TooltipsPage extends React.Component {
'left-start',
'left-end',
]),
// Custom modifiers that are passed to Popper.js, see https://popper.js.org/popper-documentation.html#modifiers
modifiers: PropTypes.object,
// Custom modifiers that are passed to Popper.js, see https://popper.js.org/docs/v2/modifiers/
modifiers: PropTypes.array,
// Whether the element the tooltip is pointing to has "position: fixed" styling. This is passed to Popper.js and
// will make the tooltip itself have "position: fixed" as well
positionFixed: PropTypes.bool,
offset: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]),
offset: PropTypes.arrayOf(PropTypes.number),
// Custom ref handler that will be assigned to the "ref" of the <div> wrapping the tooltip elements
innerRef: PropTypes.oneOfType([
PropTypes.func,
Expand Down Expand Up @@ -142,15 +139,15 @@ export default class TooltipsPage extends React.Component {
<SectionTitle>Repositioning Tooltips</SectionTitle>
<p>
If you need to reposition a tooltip due to content changes or target placement changes, use
the <code>scheduleUpdate</code> function to manually reposition it. This function is exposed
the <code>update</code> function to manually reposition it. This function is exposed
as a render prop for <code>children</code>.
</p>
<div className="docs-example">
<TooltipScheduleUpdateExample />
<TooltipUpdateExample />
</div>
<pre>
<PrismCode className="language-jsx">
{TooltipScheduleUpdateExampleSource}
{TooltipUpdateExampleSource}
</PrismCode>
</pre>
</div>
Expand Down
@@ -1,15 +1,15 @@
import React, { useState } from 'react';
import { Button, UncontrolledPopover, PopoverHeader, PopoverBody, Collapse } from 'reactstrap';

const PopoverContent = ({ scheduleUpdate }) => {
const PopoverContent = ({ update }) => {
const [isOpen, setIsOpen] = useState(false);

return (
<>
<PopoverHeader>Schedule Update</PopoverHeader>
<PopoverHeader>Update</PopoverHeader>
<PopoverBody>
<Button onClick={() => setIsOpen(!isOpen)}>Click me</Button>
<Collapse isOpen={isOpen} onEntered={scheduleUpdate} onExited={scheduleUpdate}>
<Collapse isOpen={isOpen} onEntered={update} onExited={update}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
Expand All @@ -22,12 +22,12 @@ const PopoverContent = ({ scheduleUpdate }) => {
const Example = (props) => {
return (
<div className="text-center">
<Button id="ScheduleUpdateButton" type="button">
<Button id="updateButton" type="button">
Open Popover
</Button>
<UncontrolledPopover trigger="click" placement="top" target="ScheduleUpdateButton">
{({ scheduleUpdate }) => (
<PopoverContent scheduleUpdate={scheduleUpdate} />
<UncontrolledPopover trigger="click" placement="top" target="updateButton">
{({ update }) => (
<PopoverContent update={update} />
)}
</UncontrolledPopover>
</div>
Expand Down
Expand Up @@ -2,15 +2,15 @@ import React, { useState, useEffect } from 'react';
import { Button, UncontrolledTooltip } from 'reactstrap';

const shortText = 'Hi';
const longText = 'Long tooltip content to test scheduleUpdate';
const longText = 'Long tooltip content to test update';

const TooltipContent = ({ scheduleUpdate }) => {
const TooltipContent = ({ update }) => {
const [text, setText] = useState(shortText);

useEffect(() => {
const intervalId = setInterval(() => {
setText(text === shortText ? longText : shortText);
scheduleUpdate();
update();
}, 2000);

return () => clearInterval(intervalId);
Expand All @@ -24,10 +24,10 @@ const TooltipContent = ({ scheduleUpdate }) => {
const Example = () => {
return (
<div className="text-center">
<Button id="ScheduleUpdateTooltip">Click me</Button>
<UncontrolledTooltip placement="top" target="ScheduleUpdateTooltip" trigger="click">
{({ scheduleUpdate }) => (
<TooltipContent scheduleUpdate={scheduleUpdate} />
<Button id="updateTooltip">Click me</Button>
<UncontrolledTooltip placement="top" target="updateTooltip" trigger="click">
{({ update }) => (
<TooltipContent update={update} />
)}
</UncontrolledTooltip>
</div>
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -260,9 +260,10 @@
"homepage": "https://github.com/reactstrap/reactstrap#readme",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@popperjs/core": "^2.6.0",
"classnames": "^2.2.3",
"prop-types": "^15.5.8",
"react-popper": "^1.3.6",
"react-popper": "^2.2.4",
"react-transition-group": "^3.0.0"
},
"peerDependencies": {
Expand Down
21 changes: 11 additions & 10 deletions src/DropdownMenu.js
Expand Up @@ -12,7 +12,7 @@ const propTypes = {
dark: PropTypes.bool,
right: PropTypes.bool,
flip: PropTypes.bool,
modifiers: PropTypes.object,
modifiers: PropTypes.array,
className: PropTypes.string,
cssModule: PropTypes.object,
persist: PropTypes.bool,
Expand All @@ -23,10 +23,9 @@ const propTypes = {
const defaultProps = {
tag: 'div',
flip: true,
modifiers: [],
};

const noFlipModifier = { flip: { enabled: false } };

const directionPositionMap = {
up: 'top',
left: 'left',
Expand Down Expand Up @@ -75,17 +74,19 @@ class DropdownMenu extends React.Component {
const position1 = directionPositionMap[this.context.direction] || 'bottom';
const position2 = right ? 'end' : 'start';
const poperPlacement = `${position1}-${position2}`;
const poperModifiers = !flip ? {
const poperModifiers = [
...modifiers,
...noFlipModifier,
} : modifiers;
const popperPositionFixed = !!positionFixed;
{
name: 'flip',
enabled: !!flip,
},
];

const popper = (
<Popper
placement={poperPlacement}
modifiers={poperModifiers}
positionFixed={popperPositionFixed}
strategy={positionFixed ? 'fixed' : undefined}
>
{({ ref, style, placement }) => {
let combinedStyle = { ...this.props.style, ...style };
Expand All @@ -108,7 +109,7 @@ class DropdownMenu extends React.Component {
style={combinedStyle}
aria-hidden={!this.context.isOpen}
className={classes}
x-placement={placement}
data-popper-placement={placement}
/>
);
}}
Expand All @@ -129,7 +130,7 @@ class DropdownMenu extends React.Component {
{...attrs}
aria-hidden={!this.context.isOpen}
className={classes}
x-placement={attrs.placement}
data-popper-placement={attrs.placement}
/>
);
}
Expand Down
50 changes: 33 additions & 17 deletions src/PopperContent.js
Expand Up @@ -18,12 +18,12 @@ const propTypes = {
tag: tagPropType,
isOpen: PropTypes.bool.isRequired,
cssModule: PropTypes.object,
offset: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
fallbackPlacement: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
offset: PropTypes.arrayOf(PropTypes.number),
fallbackPlacements: PropTypes.array,
flip: PropTypes.bool,
container: targetPropType,
target: targetPropType.isRequired,
modifiers: PropTypes.object,
modifiers: PropTypes.array,
positionFixed: PropTypes.bool,
boundariesElement: PropTypes.oneOfType([PropTypes.string, DOMElement]),
onClosed: PropTypes.func,
Expand All @@ -36,11 +36,10 @@ const defaultProps = {
placement: 'auto',
hideArrow: false,
isOpen: false,
offset: 0,
fallbackPlacement: 'flip',
offset: [0, 0],
flip: true,
container: 'body',
modifiers: {},
modifiers: [],
onClosed: noop,
fade: true,
transition: {
Expand Down Expand Up @@ -101,7 +100,7 @@ class PopperContent extends React.Component {
flip,
target,
offset,
fallbackPlacement,
fallbackPlacements,
placementPrefix,
arrowClassName: _arrowClassName,
hideArrow,
Expand All @@ -126,12 +125,29 @@ class PopperContent extends React.Component {
placementPrefix ? `${placementPrefix}-auto` : ''
), this.props.cssModule);

const extendedModifiers = {
offset: { offset },
flip: { enabled: flip, behavior: fallbackPlacement },
preventOverflow: { boundariesElement },
...modifiers,
};
const modifierNames = modifiers.map(m => m.name);
const baseModifiers = [
{
name: 'offset',
options: {
offset,
},
},
{
name: 'flip',
enabled: flip,
options: {
fallbackPlacements,
},
},
{
name: 'preventOverflow',
options: {
boundary: boundariesElement,
},
},
].filter(m => !modifierNames.includes(m.name));
const extendedModifiers = [ ...baseModifiers, ...modifiers];

const popperTransition = {
...Fade.defaultProps,
Expand All @@ -152,11 +168,11 @@ class PopperContent extends React.Component {
referenceElement={this.targetNode}
modifiers={extendedModifiers}
placement={placement}
positionFixed={positionFixed}
strategy={positionFixed ? 'fixed' : undefined}
>
{({ ref, style, placement, outOfBoundaries, arrowProps, scheduleUpdate }) => (
<div ref={ref} style={style} className={popperClassName} x-placement={placement} x-out-of-boundaries={outOfBoundaries ? 'true' : undefined}>
{typeof children === 'function' ? children({ scheduleUpdate }) : children}
{({ ref, style, placement: popperPlacement, isReferenceHidden, arrowProps, update }) => (
<div ref={ref} style={style} className={popperClassName} data-popper-placement={popperPlacement} data-popper-reference-hidden={isReferenceHidden ? 'true' : undefined}>
{typeof children === 'function' ? children({ update }) : children}
{!hideArrow && <span ref={arrowProps.ref} className={arrowClassName} style={arrowProps.style} />}
</div>
)}
Expand Down
8 changes: 4 additions & 4 deletions src/TooltipPopoverWrapper.js
Expand Up @@ -31,9 +31,9 @@ export const propTypes = {
PropTypes.shape({ show: PropTypes.number, hide: PropTypes.number }),
PropTypes.number
]),
modifiers: PropTypes.object,
modifiers: PropTypes.array,
positionFixed: PropTypes.bool,
offset: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
offset: PropTypes.arrayOf(PropTypes.number),
innerRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.string,
Expand Down Expand Up @@ -381,7 +381,7 @@ class TooltipPopoverWrapper extends React.Component {
fade={fade}
flip={flip}
>
{({ scheduleUpdate }) => (
{({ update }) => (
<div
{...attributes}
ref={this.getRef}
Expand All @@ -391,7 +391,7 @@ class TooltipPopoverWrapper extends React.Component {
onMouseLeave={this.onMouseLeaveTooltipContent}
onKeyDown={this.onEscKeyDown}
>
{typeof children === 'function' ? children({ scheduleUpdate }) : children}
{typeof children === 'function' ? children({ update }) : children}
</div>
)}

Expand Down

0 comments on commit 35840ef

Please sign in to comment.