Commit de4e1a91 by Dominik Prokop

Refactored withPoper HOC to PopperController using render prop

parent 8e8b759b
import React, { PureComponent } from 'react';
import * as PopperJS from 'popper.js';
import { Manager, Popper as ReactPopper } from 'react-popper';
import Portal from 'app/core/components/Portal/Portal';
import { Manager, Popper as ReactPopper, Reference } from 'react-popper';
import Transition from 'react-transition-group/Transition';
const defaultTransitionStyles = {
......@@ -18,29 +19,23 @@ const transitionStyles = {
interface Props {
renderContent: (content: any) => any;
show: boolean;
placement?: any;
placement?: PopperJS.Placement;
content: string | ((props: any) => JSX.Element);
refClassName?: string;
referenceElement: PopperJS.ReferenceObject;
}
class Popper extends PureComponent<Props> {
render() {
const { children, renderContent, show, placement, refClassName } = this.props;
const { renderContent, show, placement } = this.props;
const { content } = this.props;
return (
<Manager>
<Reference>
{({ ref }) => (
<div className={`popper_ref ${refClassName || ''}`} ref={ref}>
{children}
</div>
)}
</Reference>
<Transition in={show} timeout={100} mountOnEnter={true} unmountOnExit={true}>
{transitionState => (
<Portal>
<ReactPopper placement={placement}>
<ReactPopper placement={placement} referenceElement={this.props.referenceElement}>
{({ ref, style, placement, arrowProps }) => {
return (
<div
......
import React from 'react';
import * as PopperJS from 'popper.js';
type PopperContent = string | (() => JSX.Element);
export interface UsingPopperProps {
showPopper: (prevState: object) => void;
hidePopper: (prevState: object) => void;
renderContent: (content: any) => any;
show?: boolean;
placement?: PopperJS.Placement;
content: PopperContent;
children: JSX.Element;
renderContent?: (content: PopperContent) => JSX.Element;
}
type PopperControllerRenderProp = (
showPopper: () => void,
hidePopper: () => void,
popperProps: {
show: boolean;
placement?: string;
placement: PopperJS.Placement;
content: string | ((props: any) => JSX.Element);
className?: string;
refClassName?: string;
}
renderContent: (content: any) => any;
}
) => JSX.Element;
interface Props {
placement?: string;
placement?: PopperJS.Placement;
content: PopperContent;
className?: string;
refClassName?: string;
content: string | ((props: any) => JSX.Element);
children: PopperControllerRenderProp;
}
interface State {
placement: string;
placement: PopperJS.Placement;
show: boolean;
}
export default function withPopper(WrappedComponent) {
return class extends React.Component<Props, State> {
constructor(props) {
class PopperController extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.setState = this.setState.bind(this);
this.state = {
placement: this.props.placement || 'auto',
show: false,
};
}
componentWillReceiveProps(nextProps) {
componentWillReceiveProps(nextProps: Props) {
if (nextProps.placement && nextProps.placement !== this.state.placement) {
this.setState(prevState => {
return {
......@@ -59,7 +69,7 @@ export default function withPopper(WrappedComponent) {
}));
};
renderContent(content) {
renderContent(content: PopperContent) {
if (typeof content === 'function') {
// If it's a function we assume it's a React component
const ReactComponent = content;
......@@ -69,20 +79,16 @@ export default function withPopper(WrappedComponent) {
}
render() {
const { children, content } = this.props;
const { show, placement } = this.state;
const className = this.props.className || '';
return (
<WrappedComponent
{...this.props}
showPopper={this.showPopper}
hidePopper={this.hidePopper}
renderContent={this.renderContent}
show={show}
placement={placement}
className={className}
/>
);
return children(this.showPopper, this.hidePopper, {
show,
placement,
content,
renderContent: this.renderContent,
});
}
};
}
export default PopperController;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment