Remove child flattening mechanism

pull/4041/head
Alex P 2018-07-26 16:35:24 -07:00
parent da75597999
commit 4537b890b1
5 changed files with 73 additions and 48 deletions

View File

@ -1,25 +1,31 @@
import React, {Component, CSSProperties, Fragment} from 'react'
// Librarries
import React, {Component, CSSProperties} from 'react'
import classnames from 'classnames'
import _ from 'lodash'
// Components
import {ClickOutside} from 'src/shared/components/ClickOutside'
import DropdownDivider from 'src/reusable_ui/components/dropdowns/DropdownDivider'
import DropdownItem from 'src/reusable_ui/components/dropdowns/DropdownItem'
import DropdownButton from 'src/reusable_ui/components/dropdowns/DropdownButton'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
// Types
import {
ComponentColor,
ComponentSize,
IconFont,
DropdownMenuColors,
} from 'src/reusable_ui/types'
import DropdownDivider from 'src/reusable_ui/components/dropdowns/DropdownDivider'
import DropdownItem from 'src/reusable_ui/components/dropdowns/DropdownItem'
import DropdownButton from 'src/reusable_ui/components/dropdowns/DropdownButton'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import {ErrorHandling} from 'src/shared/decorators/errors'
// Styles
import './Dropdown.scss'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
children: Array<JSX.Element | JSX.Element[]>
children: JSX.Element[]
onChange: (value: any) => void
selectedItem: string
selectedItemKey: string
color?: ComponentColor
menuColor?: DropdownMenuColors
size?: ComponentSize
@ -68,7 +74,7 @@ class Dropdown extends Component<Props, State> {
<ClickOutside onClickOutside={this.collapseMenu}>
<div className={this.containerClassName} style={{width}}>
{this.button}
{this.menu}
{this.menuItems}
</div>
</ClickOutside>
)
@ -93,24 +99,29 @@ class Dropdown extends Component<Props, State> {
}
private get button(): JSX.Element {
const {selectedItem, disabled, color, size, icon} = this.props
const {selectedItemKey, disabled, color, size, icon, children} = this.props
const {expanded} = this.state
const selectedChild = children.find(
child => child.props.itemKey === selectedItemKey
)
return (
<DropdownButton
label={selectedItem}
active={expanded}
color={color}
size={size}
icon={icon}
disabled={disabled}
onClick={this.toggleMenu}
/>
>
{selectedChild.props.children}
</DropdownButton>
)
}
private get menu(): JSX.Element {
const {selectedItem, maxMenuHeight, menuColor} = this.props
private get menuItems(): JSX.Element {
const {selectedItemKey, maxMenuHeight, menuColor, children} = this.props
const {expanded} = this.state
if (expanded) {
@ -125,11 +136,11 @@ class Dropdown extends Component<Props, State> {
maxHeight={maxMenuHeight}
>
<div className="dropdown--menu">
{this.flatChildren.map((child: JSX.Element) =>
{React.Children.map(children, (child: JSX.Element) =>
React.cloneElement(child, {
...child.props,
key: `dropdown-menu--${child.props.text}`,
selected: child.props.text === selectedItem,
key: child.props.itemKey,
selected: child.props.itemKey === selectedItemKey,
onClick: this.handleItemClick,
})
)}
@ -142,21 +153,6 @@ class Dropdown extends Component<Props, State> {
return null
}
private get flatChildren() {
const children = React.Children.toArray(this.props.children)
const childrenWithoutFragments = children.map((child: JSX.Element) => {
if (child.type === Fragment) {
const childArray = React.Children.toArray(child.props.children)
return childArray
}
return child
})
return _.flattenDeep(childrenWithoutFragments)
}
private get menuStyle(): CSSProperties {
const {wrapText, width} = this.props

View File

@ -1,17 +1,22 @@
import React, {Component} from 'react'
import classnames from 'classnames'
import {ComponentColor, ComponentSize, IconFont} from 'src/reusable_ui/types'
import {
ComponentColor,
ComponentSize,
IconFont,
DropdownChild,
} from 'src/reusable_ui/types'
import {ErrorHandling} from 'src/shared/decorators/errors'
import './DropdownButton.scss'
interface Props {
children: DropdownChild
onClick: () => void
disabled?: boolean
active?: boolean
color?: ComponentColor
size?: ComponentSize
icon?: IconFont
label: string
}
@ErrorHandling
@ -24,11 +29,11 @@ class DropdownButton extends Component<Props> {
}
public render() {
const {onClick, disabled, label} = this.props
const {onClick, disabled, children} = this.props
return (
<button className={this.classname} onClick={onClick} disabled={disabled}>
{this.icon}
<span className="dropdown--selected">{label}</span>
<span className="dropdown--selected">{children}</span>
<span className="dropdown--caret icon caret-down" />
</button>
)

View File

@ -1,16 +1,28 @@
import React, {SFC} from 'react'
import React, {Component} from 'react'
import classnames from 'classnames'
import {DropdownChild} from 'src/reusable_ui/types'
interface Props {
children: DropdownChild
itemKey: string
text?: string
}
const DropdownDivider: SFC<Props> = ({text}): JSX.Element => (
<div className={classnames('dropdown--divider', {line: !text})}>{text}</div>
)
class DropdownDivider extends Component<Props> {
public static defaultProps: Partial<Props> = {
text: '',
}
DropdownDivider.defaultProps = {
text: '',
public render() {
const {text} = this.props
return (
<div className={classnames('dropdown--divider', {line: !text})}>
{text}
</div>
)
}
}
export default DropdownDivider

View File

@ -1,12 +1,15 @@
import React, {Component} from 'react'
import classnames from 'classnames'
import {DropdownChild} from 'src/reusable_ui/types'
interface Props {
text: string
itemKey: string
children: DropdownChild
value: any
selected?: boolean
checkbox?: boolean
onClick?: (value: any) => void
value: any
}
class DropdownItem extends Component<Props> {
@ -15,8 +18,8 @@ class DropdownItem extends Component<Props> {
selected: false,
}
public render() {
const {text, selected, checkbox} = this.props
public render(): JSX.Element {
const {selected, checkbox} = this.props
return (
<div
@ -28,7 +31,7 @@ class DropdownItem extends Component<Props> {
>
{this.checkBox}
{this.dot}
{text}
{this.childElements}
</div>
)
}
@ -56,6 +59,12 @@ class DropdownItem extends Component<Props> {
return <div className="dropdown-item--dot" />
}
}
private get childElements(): JSX.Element {
const {children} = this.props
return <div className="dropdown-item--children">{children}</div>
}
}
export default DropdownItem

View File

@ -14,6 +14,8 @@ export enum DropdownMenuColors {
Onyx = 'onyx',
}
export type DropdownChild = Array<string | JSX.Element | Element>
export enum ComponentSize {
ExtraSmall = 'xs',
Small = 'sm',
@ -63,6 +65,7 @@ export enum IconFont {
CaretUp = 'caret-up',
Checkmark = 'checkmark',
Circle = 'circle',
CircleThick = 'circle-thick',
Clock = 'clock',
CogOutline = 'cog-outline',
CogThick = 'cog-thick',