Skip to content

Commit

Permalink
feat(atoms): change dropdown logic with context
Browse files Browse the repository at this point in the history
Close CW-975
  • Loading branch information
ej9x committed May 8, 2018
1 parent c80b162 commit 313c3c3
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 52 deletions.
27 changes: 14 additions & 13 deletions src/atoms/Dropdown/DropdownBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import onClickOutside from 'react-onclickoutside';
import { Popper } from 'react-popper';
import { Portal } from 'react-portal';

import { DropdownContext, withDropdownContext, type DropdownContextData } from './DropdownPlate'
import { createStyledTag, createTheme } from '../../utils'

/**
Expand Down Expand Up @@ -41,11 +42,6 @@ type DropdownBodyProps = {|
forceRender?: boolean,
withPortal?: boolean,
closeOnClickOutside: boolean,

/** cloned props */
isOpen: boolean,
onCloseDropdown: () => void,
targetWidth?: number,
|}

const name = 'dropdownBody';
Expand Down Expand Up @@ -109,7 +105,16 @@ const setOffset = (offset?: PropSizes) => offset && offset !== 'none'
: fp.identity;


class DropdownBodyBase extends PureComponent<DropdownBodyProps> {

const dropdownBodyEnhancer: HOC<*, DropdownBodyProps> = compose(
setDisplayName('DropdownBody'),
withDropdownContext,
onClickOutside,
);

type DropdownBodyEnhancedProps = HOCBase<typeof dropdownBodyEnhancer>;

class DropdownBodyBase extends PureComponent<DropdownBodyEnhancedProps> {
static zIndex = 2000;

static defaultProps = {
Expand Down Expand Up @@ -154,15 +159,15 @@ class DropdownBodyBase extends PureComponent<DropdownBodyProps> {
}

getBodyChildren = () => {
const { children, onCloseDropdown } = this.props;
const { children, dropdown: { closeDropdown } } = this.props;

return typeof children === 'function'
? children({ closeDropdown: onCloseDropdown })
? children({ closeDropdown })
: children;
}

render() {
const { isOpen, withPortal, forceRender, ...rest } = this.props;
const { withPortal, forceRender, dropdown: { isOpen }, ...rest } = this.props;

const popperPlacement = this.getPopperPlacement();
const popperModifiers = this.getPopperModifiers();
Expand Down Expand Up @@ -192,10 +197,6 @@ class DropdownBodyBase extends PureComponent<DropdownBodyProps> {
}
}

const dropdownBodyEnhancer: HOC<DropdownBodyProps, DropdownBodyProps> = compose(
setDisplayName('DropdownBody'),
onClickOutside,
);
const DropdownBody = dropdownBodyEnhancer(DropdownBodyBase)

export { DropdownBody, theme }
29 changes: 29 additions & 0 deletions src/atoms/Dropdown/DropdownContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @flow
import React, { createContext } from 'react';


type DropdownContextType = {|
targetWidth?: number,
isOpen: boolean,
toggleDropdown: () => void,
closeDropdown:() => void,
outsideClickIgnoreClass: string,
|}

const DropdownContext = createContext({
dropdown: {
outsideClickIgnoreClass: '',
},
});


const withDropdownContext: HOCProps<{ dropdown: DropdownContextType }> = (Component: React$Element<*>) => (props: *) => {
return (
<DropdownContext.Consumer>
{ dropdownData => <Component { ...props } dropdown={ dropdownData } /> }
</DropdownContext.Consumer>
);
};

export { DropdownContext, withDropdownContext };
export type { DropdownContextType };
19 changes: 15 additions & 4 deletions src/atoms/Dropdown/DropdownHead.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import React, { PureComponent } from 'react';
import { Target } from 'react-popper';
import { compose } from 'recompose';

import { withDropdownContext } from './DropdownContext'

import { createStyledTag, createTheme } from '../../utils';

Expand Down Expand Up @@ -54,17 +57,23 @@ const DropdownPopperTarget = createStyledTag(name, {
height:' 100%',
});

class DropdownHead extends PureComponent<DropdownHeadProps> {
const dropdownHeadEnhancer: HOC<*, DropdownHeadProps> = compose(
withDropdownContext,
)

type DropdownHeadPropsEnhanced = HOCBase<typeof dropdownHeadEnhancer>;

class DropdownHeadBase extends PureComponent<DropdownHeadPropsEnhanced> {

onClick = (event: MouseEvent) => {
const { onClick, stopClickPropagation } = this.props;
const { dropdown: { toggleDropdown }, stopClickPropagation } = this.props;

onClick && onClick(event);
toggleDropdown && toggleDropdown();
stopClickPropagation && event.stopPropagation();
}

render() {
const { outsideClickIgnoreClass = '', children, ...rest } = this.props;
const { dropdown: { outsideClickIgnoreClass }, children, ...rest } = this.props;

return (
<DropdownHeadTag { ...rest } tagName="div" className={ outsideClickIgnoreClass } onClick={ this.onClick }>
Expand All @@ -76,4 +85,6 @@ class DropdownHead extends PureComponent<DropdownHeadProps> {
}
}

const DropdownHead = dropdownHeadEnhancer(DropdownHeadBase);

export { DropdownHead, theme}
54 changes: 19 additions & 35 deletions src/atoms/Dropdown/DropdownPlate.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Manager } from 'react-popper';

import { DropdownHead } from './DropdownHead';
import { DropdownBody } from './DropdownBody';
import { DropdownContext } from './DropdownContext';

/**
* @prop {*} isOpen opened state of the dropdown
Expand Down Expand Up @@ -59,44 +60,25 @@ class DropdownPlateBase extends Component<DropdownControlledProps> {

getIgnoreClickOutsideClass = () => `ignore-react-onclickoutside-${this.instanceIndex}`;

getHeadComponent() {
const { children } = this.props;

return React.Children.map(children, child =>
(child.type.prototype instanceof DropdownHead || child.type === DropdownHead)
? React.cloneElement(child,
{
onClick: this.toggleDropdown,
outsideClickIgnoreClass: this.getIgnoreClickOutsideClass(),
})
: null,
);
}

getBodyComponent() {
render() {
const { children, onCloseDropdown, isOpen } = this.props;

return React.Children.map(children, child =>
(child.type.prototype instanceof DropdownBody || child.type === DropdownBody)
? React.cloneElement(child,
{
onCloseDropdown,
isOpen,
targetWidth: this.getDropdownWidth(),
outsideClickIgnoreClass: this.getIgnoreClickOutsideClass(),
})
: null,
);
}
const contextData: DropdownContextData = {
isOpen,
toggleDropdown: this.toggleDropdown,
closeDropdown: onCloseDropdown,
targetWidth: this.getDropdownWidth(),
outsideClickIgnoreClass: this.getIgnoreClickOutsideClass(),
}

render() {
return (
<div ref={ this.setDropdownRef }>
<Manager tag={ false }>
{ this.getHeadComponent() }
{ this.getBodyComponent() }
</Manager>
</div>
<DropdownContext.Provider value={ contextData }>
<div ref={ this.setDropdownRef }>
<Manager tag={ false }>
{ children }
</Manager>
</div>
</DropdownContext.Provider>
);
}
}
Expand All @@ -115,4 +97,6 @@ const dropDownEnhancer: { (any): React$ComponentType<DropdownControlledProps | D
),
);

export const DropdownPlate = dropDownEnhancer(DropdownPlateBase);
const DropdownPlate = dropDownEnhancer(DropdownPlateBase);

export { DropdownPlate };

0 comments on commit 313c3c3

Please sign in to comment.