{"size": 23181, "ext": "js", "max_stars_repo_path": "source/List.js", "max_stars_repo_name": "hemamarisetty/react-responsive-ui", "max_stars_repo_stars_event_min_datetime": "2020-03-02T16:26:35.000Z", "max_stars_repo_stars_event_max_datetime": "2020-03-02T16:26:35.000Z", "max_issues_repo_path": "source/List.js", "max_issues_repo_name": "hemamarisetty/react-responsive-ui", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "source/List.js", "max_forks_repo_name": "hemamarisetty/react-responsive-ui", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 1, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 24.8190578158, "max_line_length": 179, "alphanum_fraction": 0.6595487684}
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'

import Divider from './Divider'

import { submitFormOnCtrlEnter } from './utility/dom'
import { onBlur, focus } from './utility/focus'

// `PureComponent` is only available in React >= 15.3.0.
const PureComponent = React.PureComponent || React.Component

export default class List extends PureComponent
{
	static propTypes =
	{
		// (optional) HTML `id` attribute.
		// Can be used for WAI-ARIA stuff.
		// Example: `<input role="combobox"/>` with `aria-owns={listId}`.
		id : PropTypes.string,

		value : PropTypes.any,
		onChange : PropTypes.func,

		// If a `<List/>` has `onChange` then it wraps `<List.Item/>`s with `<button/>`s.
		// The `onChange` added by `<ExpandableList/>` overrides the original `onChange`.
		// If there was no `onChange` — there will be one.
		// So to retain that info `hasOnChange` property is used as a workaround.
		// `undefined` means "ignore this property".
		hasOnChange : PropTypes.bool,

		// If `items` property is supplied then it's used to
		// detect "on items changed" event in `getDerivedStateFromProps`.
		// It seems to be the only usage of the `items` property.
		items : PropTypes.arrayOf(PropTypes.object),

		// Legacy method, use `onChange` instead.
		onSelectItem : PropTypes.func,
		highlightSelectedItem : PropTypes.bool.isRequired,

		onFocusIn : PropTypes.func,
		onFocusItem : PropTypes.func,
		onKeyDown : PropTypes.func,

		// ARIA `role` attribute.
		role : PropTypes.string,

		// If a `<List/>` is `expandable`
		// then it won't be `.rrui__list:not(.rrui__list--focus)`.
		// `.rrui__list:not(.rrui__list--focus)` is only for standalone lists.
		expandable : PropTypes.bool,

		// If `tabbable` is `true` (default behavior)
		// then the first item of the list
		// (or the last focused item of the list)
		// will be focused when the list gets focused.
		tabbable : PropTypes.bool.isRequired,

		// If `shouldFocus` is set to `false`
		// (which is not the default behavior)
		// then the list items won't actually
		// be `.focus()`ed (though they'll be
		// indicated as if they're focused).
		// This feature is used in `<Autocomplete/>`
		// that always keeps the actual focus on the `<input/>`.
		shouldFocus : PropTypes.bool.isRequired,

		// If `highlightFirstItem` is `true`
		// then by default the first item of the list
		// will be focused every time it's items change.
		// (and also when it's mounted)
		highlightFirstItem : PropTypes.bool.isRequired,

		createButtons : PropTypes.bool.isRequired,

		// For select options list keyboard navigation via typing.
		resetInputTimeout : PropTypes.number.isRequired
	}

	static defaultProps =
	{
		tabbable : true,
		shouldFocus : true,
		highlightFirstItem : false,
		createButtons : true,
		highlightSelectedItem : true,
		resetInputTimeout : 1000
	}

	state = {
		items: this.props.items
	}

	// `ref`s of all items currently rendered.
	itemRefs = []

	// For select options list keyboard navigation via typing.
	input = ''

	componentDidMount()
	{
		const {
			highlightFirstItem
		} = this.props

		if (highlightFirstItem) {
			this.focusItem(0)
		}

		this._isMounted = true
	}

	componentDidUpdate(prevProps, prevState)
	{
		const {
			value,
			items,
			children,
			highlightSelectedItem,
			highlightFirstItem
		} = this.props

		// If `items` property is supplied
		// then it's used to detect "on items changed" event.
		if (prevState.items && prevState.items !== items)
		{
			this.setState({ items })
			// `findItemIndexByValue()` must return `undefined` for "no such item".
			const selectedItemIndex = highlightSelectedItem ? findItemIndexByValue(value, children) : undefined
			this.focusItem(selectedItemIndex === undefined ? (highlightFirstItem ? 0 : undefined) : selectedItemIndex)
		}
	}

	componentWillUnmount()
	{
		this._isMounted = false
		clearTimeout(this.blurTimer)
		clearTimeout(this.resetInputTimer)
	}

	chooseFocusedItem() {
		const { focusedItemIndex } = this.state
		if (focusedItemIndex !== undefined) {
			const itemRef = this.itemRefs[focusedItemIndex]
			if (itemRef.click) {
				itemRef.click()
			}
		}
	}

	getFocusedItemIndex = () => this.state.focusedItemIndex
	clearFocus = () => this.focusItem()
	// Deprecated method name.
	unfocus = this.clearFocus

	// Focuses the list.
	focus = () => {
		const { focusedItemIndex } = this.state
		if (focusedItemIndex !== undefined) {
			return this.focusItem(focusedItemIndex)
		}
		this.list.focus()
	}

	getFirstFocusableItemIndex()
	{
		let i = 0
		while (i < this.itemRefs.length) {
			if (this.itemRefs[i]) {
				return i
			}
		}
	}

	getItemValue(index)
	{
		const { children } = this.props
		const item = React.Children.toArray(children)[index]
		return item.props.value
	}

	// Can be public API for programmatically focusing a certain `<List.Item/>`.
	focusItem = (focusedItemIndex, options = {}) =>
	{
		const { onFocusItem, shouldFocus } = this.props

		if (onFocusItem) {
			onFocusItem(focusedItemIndex, options)
		}

		this.setState({
			// Focus the item.
			focusedItemIndex,
			// Store the focused item value.
			// This is used for cases like autocomplete
			// where the list of options changes but
			// the focused option stays focused.
			focusedItemValue: focusedItemIndex === undefined ? undefined : this.getItemValue(focusedItemIndex)
		}, () => {
			// Actually focus the item.
			if (focusedItemIndex !== undefined) {
				if (shouldFocus && this._isMounted) {
					if (!focus(this.itemRefs[focusedItemIndex])) {
						console.error(`<List.Item/> #${focusedItemIndex + 1}'s child component doesn't have a ".focus()" method.`)
					}
				}
			}
		})
	}

	onKeyDown = (event) =>
	{
		const { onKeyDown, children } = this.props
		const { focusedItemIndex } = this.state

		if (onKeyDown) {
			onKeyDown(event)
		}

		if (event.defaultPrevented) {
			return
		}

		if (submitFormOnCtrlEnter(event, this.input)) {
			return
		}

		if (event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) {
			return
		}

		if (React.Children.count(children) > 0)
		{
			switch (event.keyCode)
			{
				// "Up" arrow.
				// Select the previous item (if present).
				case 38:
					event.preventDefault()

					const previousIndex = this.getPreviousFocusableItemIndex()

					if (previousIndex !== undefined) {
						this.focusItem(previousIndex, { interaction: true })
					}

					return

				// "Down" arrow.
				// Select the next item (if present).
				case 40:
					event.preventDefault()

					const nextIndex = this.getNextFocusableItemIndex()

					if (nextIndex !== undefined) {
						this.focusItem(nextIndex, { interaction: true })
					}

					return
			}
		}
	}

	onKeyPress = (event) => {
		const { resetInputTimeout } = this.props
		const characters = event.char || String.fromCharCode(event.charCode)
		if (characters) {
			this.input += characters
			this.onInput()
			clearTimeout(this.resetInputTimer)
			this.resetInputTimer = setTimeout(this.resetInput, resetInputTimeout)
		}
	}

	onInput() {
		const { children } = this.props
		const index = findItemIndexByLabel(this.input, children)
		if (index !== undefined) {
			this.focusItem(index)
		}
	}

	resetInput = () => this.input = ''
	isInputInProgress = () => this.input !== ''

	onInputSpacebar = () => {
		if (this.input) {
			this.input += ' '
		}
	}

	// Get the previous option (relative to the currently focused option)
	getPreviousFocusableItemIndex()
	{
		const { children } = this.props
		let { focusedItemIndex } = this.state

		if (focusedItemIndex === undefined) {
			focusedItemIndex = React.Children.count(children)
		}

		while (focusedItemIndex > 0) {
			focusedItemIndex--
			if (this.isFocusableItemIndex(focusedItemIndex)) {
				return focusedItemIndex
			}
		}
	}

	// Get the next option (relative to the currently focused option)
	getNextFocusableItemIndex()
	{
		const { children } = this.props
		let { focusedItemIndex } = this.state

		if (focusedItemIndex === undefined) {
			focusedItemIndex = -1
		}

		while (focusedItemIndex < React.Children.count(children) - 1) {
			focusedItemIndex++
			if (this.isFocusableItemIndex(focusedItemIndex)) {
				return focusedItemIndex
			}
		}
	}

	onItemFocus = (event) => {
		const { expandable } = this.props
		if (expandable) {
			return
		}
		this.onFocusIn()
	}

	onBlur = (event) => {
		const { expandable } = this.props
		if (expandable) {
			return
		}
		clearTimeout(this.blurTimer)
		const result = onBlur(event, this.onFocusOut, () => this.list)
		if (typeof result === 'number') {
			this.blurTimer = result
		}
	}

	onFocusIn = () => {
		const { onFocusIn } = this.props
		if (onFocusIn) {
			onFocusIn()
		}
		this.setState({
			isFocused: true
		})
	}

	onFocusOut = () => {
		const { value } = this.props
		if (value === undefined) {
			this.clearFocus()
		}
		this.setState({
			isFocused: false
		})
	}

	isFocusableItemIndex = (index) => this.itemRefs[index] !== undefined

	isFocusableItem = (item) => !isDivider(item)

	// `this.list` is also being accessed from `<ScrollableList/>`.
	storeListNode = (node) => this.list = node

	// Is only used by `<ScrollableList/>` so set `max-height` immediately,
	// without waiting for the next React render cycle.
	getDOMNode = () => this.list

	storeItemRef = (ref, i) => this.itemRefs[i] = ref

	render()
	{
		const
		{
			id,
			expandable,
			disabled,
			tabbable,
			value,
			hasOnChange,
			onChange,
			// `onSelectItem` is deprecated, use `onChange` instead.
			onSelectItem,
			highlightSelectedItem,
			createButtons,
			className,
			style,
			children
		}
		= this.props

		let { role } = this.props

		const {
			focusedItemIndex,
			isFocused
		} = this.state

		// ARIA (accessibility) roles info:
		// https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.html
		if (!role && (onChange || onSelectItem)) {
			role = 'listbox'
		}

		// if (this.props['aria-hidden']) {
		// 	role = undefined
		// }

		// `tabIndex={ -1 }` makes the `<ul/>` focusable.
		// So that `<Expandable/>` doesn't collapse on click inside it (top, bottom).

		return (
			<ul
				ref={ this.storeListNode }
				id={ id }
				role={ role }
				aria-label={ this.props['aria-label'] }
				aria-hidden={ this.props['aria-hidden'] }
				aria-required={ this.props['aria-required'] }
				aria-invalid={ this.props['aria-invalid'] }
				onFocus={ this.onFocusIn }
				onKeyDown={ this.onKeyDown }
				onKeyPress={ this.onKeyPress }
				tabIndex={ -1 }
				style={ style }
				className={ classNames(className, 'rrui__outline', 'rrui__list', {
					'rrui__list--focus': isFocused
				}) }>

				{ React.Children.map(children, (item, i) =>
				{
					// Workaround for `react-hot-loader`.
					// https://github.com/gaearon/react-hot-loader#checking-element-types
					if (item.type.displayName !== 'ListItem') {
						throw new Error(`Only <List.Item/>s can be placed inside a <List/> (and remove any whitespace).`)
					}

					return React.cloneElement(item,
					{
						key       : i,
						index     : i,
						itemRef   : this.isFocusableItem(item) ? this.storeItemRef : undefined,
						role      : role === 'listbox' ? 'option' : item.props.role,
						focus     : this.focusItem,
						focused   : (expandable || isFocused) && focusedItemIndex === i,
						disabled  : disabled || item.props.disabled,
						tabIndex  : tabbable && (focusedItemIndex === undefined ? i === 0 : i === focusedItemIndex) ? 0 : -1,
						createButton : createButtons,
						isInputInProgress : this.isInputInProgress,
						onInputSpacebar : this.onInputSpacebar,
						onItemFocus : this.onItemFocus,
						onItemBlur : this.onBlur,
						onSelectItem : onChange || onSelectItem,
						hasOnSelectItem : hasOnChange,
						selectedItemValue : value,
						highlightSelectedItem : (onChange || onSelectItem) && highlightSelectedItem
					})
				}) }
			</ul>
		)
	}
}

export class ListItem extends React.Component
{
	static propTypes =
	{
		// (optional) HTML `id` attribute.
		// Can be used for WAI-ARIA stuff.
		// Example: `<input role="combobox"/>` with `aria-activedescendant={focusedListItemId}`.
		id : PropTypes.string,

		value : PropTypes.any,
		index : PropTypes.number,
		focused : PropTypes.bool,
		onClick : PropTypes.func,
		// `onSelect` is deprecated, use `onClick` instead.
		onSelect : PropTypes.func,
		onSelectItem : PropTypes.func,
		// If a `<List/>` has `onChange` then it wraps `<List.Item/>`s with `<button/>`s.
		// The `onChange` added by `<ExpandableList/>` overrides the original `onChange`.
		// If there was no `onChange` — there will be one.
		// So to retain that info `hasOnChange` property is used as a workaround.
		// `undefined` means "ignore this property".
		hasOnSelectItem : PropTypes.bool,
		selectedItemValue : PropTypes.any,
		highlightSelectedItem : PropTypes.bool,
		createButton : PropTypes.bool,
		// Deprecated. Use `createButton` instead.
		shouldCreateButton : PropTypes.bool,
		// The button won't be pressed on "Space" key
		// if the user is currently typing.
		isInputInProgress : PropTypes.func,
		onInputSpacebar : PropTypes.func
	}

	onButtonKeyDown = (event) =>
	{
		const { isInputInProgress, onInputSpacebar } = this.props

		if (event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) {
			return
		}

		switch (event.keyCode) {
			// "Spacebar".
			case 32:
				// If the user is currently typing.
				if (isInputInProgress()) {
					// Don't press the option button.
					event.preventDefault()
					// Append space character.
					onInputSpacebar()
				}
		}
	}

	onMouseDown = (event) =>
	{
		const
		{
			value,
			index,
			focus,
			children
		}
		= this.props

		// If `<List.Item/>` child element gets wrapped in a `<button/>`
		// then call `onMouseDown` defined on the `<List.Item/>`.
		// If `<List.Item/>` child element doesn't get wrapped in a `<button/>`
		// then manually call `onMouseDown` defined on the `<List.Item/>` child element
		// because `onMouseDown` gets overridden for `<List.Item/>` child element.

		const onMouseDown = this.shouldCreateButton() ? this.props.onMouseDown : children.props.onMouseDown

		// Without this Safari (both mobile and desktop)
		// won't select any item in an expanded list
		// because it will collapse the list immediately
		// on `mouseDown` due to `blur` event being fired.
		event.preventDefault()

		if (this.isSelectable()) {
			focus(index)
		}

		if (onMouseDown) {
			onMouseDown(event)
		}
	}

	onFocus = (event) =>
	{
		const
		{
			focus,
			index,
			onItemFocus,
			children
		}
		= this.props

		// If `<List.Item/>` child element gets wrapped in a `<button/>`
		// then call `onFocus` defined on the `<List.Item/>`.
		// If `<List.Item/>` child element doesn't get wrapped in a `<button/>`
		// then manually call `onFocus` defined on the `<List.Item/>` child element
		// because `onFocus` gets overridden for `<List.Item/>` child element.

		const onFocus = this.shouldCreateButton() ? this.props.onFocus : children.props.onFocus

		if (this.isSelectable()) {
			focus(index)
		}

		if (onFocus) {
			onFocus(event)
		}

		if (onItemFocus) {
			onItemFocus(event)
		}
	}

	onBlur = (event) =>
	{
		const { onItemBlur, children } = this.props

		// If `<List.Item/>` child element gets wrapped in a `<button/>`
		// then call `onBlur` defined on the `<List.Item/>`.
		// If `<List.Item/>` child element doesn't get wrapped in a `<button/>`
		// then manually call `onFocus` defined on the `<List.Item/>` child element
		// because `onBlur` gets overridden for `<List.Item/>` child element.

		const onBlur = this.shouldCreateButton() ? this.props.onBlur : children.props.onBlur

		if (onBlur) {
			onBlur(event)
		}

		if (onItemBlur) {
			onItemBlur(event)
		}
	}

	onClick = (event) =>
	{
		const
		{
			onClick,
			onSelect,
			onSelectItem,
			index,
			value,
			children
		}
		= this.props

		// If `<List.Item/>` child element gets wrapped in a `<button/>`
		// then call `onClick` defined on the `<List.Item/>`.
		// If `<List.Item/>` child element doesn't get wrapped in a `<button/>`
		// then manually call `onClick` defined on the `<List.Item/>` child element
		// because `onClick` gets overridden for `<List.Item/>` child element,
		// and also call `onClick` defined on the `<List.Item/>` (if any).

		if (onClick) {
			onClick(event)
		}

		if (!this.shouldCreateButton()) {
			// Since `onClick` gets overridden
			// for `<List.Item/>` child element
			// call its original `onClick` manually here.
			if (children.props.onClick) {
				children.props.onClick(event)
			}
		}

		if (this.isSelectable())
		{
			if (onSelect) {
				onSelect(value, index)
			}
			if (onSelectItem) {
				onSelectItem(value, index)
			}
		}
	}

	isSelectable()
	{
		return isSelectableItem(this)
	}

	// Perhaps this is called by `focus()` utility function.
	// Something like: `focus(this.itemRefs[i])`.
	focus = () =>
	{
		const { children } = this.props
		focus(React.Children.toArray(children)[0])
	}

	storeRef = (ref) =>
	{
		const { itemRef, index } = this.props

		if (itemRef) {
			itemRef(ref, index)
		}
	}

	shouldCreateButton()
	{
		const {
			onClick,
			onSelect,
			onSelectItem,
			hasOnSelectItem,
			createButton,
			// Deprecated. Use `createButton` instead.
			shouldCreateButton
		} = this.props

		return this.isSelectable() && (
			onClick ||
			onSelect ||
			(
				onSelectItem &&
				(hasOnSelectItem === undefined ? true : hasOnSelectItem) &&
				(createButton || shouldCreateButton)
			)
		)
	}

	render()
	{
		const
		{
			id,
			value,
			icon,
			item,
			role,
			focused,
			disabled,
			className,
			tabIndex,
			highlightSelectedItem,
			selectedItemValue,
			component: Component,
			children
		}
		= this.props

		// Throws an error for some weird reason.
		// React.Children.only(children)

		if (!Component) {
			if (React.Children.count(children) !== 1) {
				throw new Error(`Each <List.Item/> must have a single child (and remove any whitespace).`)
			}
		}

		const isSelected = this.shouldCreateButton() && value === selectedItemValue
		const isDividerItem = !Component && isDivider(children)

		const properties =
		{
			ref          : isDividerItem ? undefined : this.storeRef,
			onMouseDown  : this.onMouseDown,
			onClick      : this.onClick,
			onFocus      : this.onFocus,
			onBlur       : this.onBlur,
			className    : classNames
			(
				className,
				'rrui__list__item',
				'rrui__text-line',
				{
					/* `--focused` modifier is deprecated, use `--focus` instead. */
					'rrui__list__item--focused'  : focused,
					'rrui__list__item--focus'    : focused,
					'rrui__list__item--selected' : isSelected && highlightSelectedItem,
					'rrui__list__item--disabled' : disabled,
					'rrui__list__item--divider'  : isDividerItem
				}
			)
		}

		if (id !== undefined) {
			properties.id = id
		}

		if (tabIndex !== undefined) {
			properties.tabIndex = tabIndex
		}

		let ItemComponent
		let itemChildren
		let label

		if (this.shouldCreateButton())
		{
			ItemComponent = 'button'
			label = getItemLabel(this)
			properties.type = 'button'
			properties.role = role
			properties['aria-selected'] = isSelected
			properties['aria-label'] = this.props.label || (Component ? undefined : (typeof children !== 'string' && children && children.props ? children.props['aria-label'] : undefined))
			properties.disabled = disabled
			properties.onKeyDown = this.onButtonKeyDown
			properties.className = classNames(
				properties.className,
				'rrui__button-reset',
				'rrui__outline',
				// `.rrui__list__item--button` only sets the fixed `height`.
				!Component && 'rrui__list__item--button'
			)

			itemChildren = Component ?
				<Component
					{...item}
					selected={isSelected && highlightSelectedItem}
					focused={focused}
					disabled={disabled}/> :
				renderListItemComponent({ value, label, icon, children })
		}
		else
		{
			// Don't overwrite `className` already defined on the `children`.
			properties.className = classNames(
				properties.className,
				children.props && children.props.className
			)
		}

		return (
			<li
				role={this.shouldCreateButton() || isDivider(children) ? 'presentation' : role}
				aria-selected={this.shouldCreateButton() ? undefined : (role && role !== 'presentation' ? isSelected : undefined)}
				aria-label={this.shouldCreateButton() ? undefined : label}
				className="rrui__list__list-item">
				{ ItemComponent && React.createElement(ItemComponent, properties, itemChildren) }
				{ !ItemComponent && React.cloneElement(children, properties) }
			</li>
		)
	}
}

// Workaround for `react-hot-loader`.
// https://github.com/gaearon/react-hot-loader#checking-element-types
ListItem.displayName = 'ListItem'

List.Item = ListItem


// Replace `itemChildren` array with `<React.Fragment/>`
// in some future when React >= 16.2.0 is common.
//
// <React.Fragment>
// 	{/* Icon. */}
// 	{icon &&
// 		<div className="rrui__list__item-icon">
// 			{ React.createElement(icon, { value, label }) }
// 		</div>
// 	}
// 	{/* Label (or content). */}
// 	{children}
// </React.Fragment>
function renderListItemComponent({
	value,
	label,
	icon,
	children
}) {
	// Label (or content).
	let itemChildren
	if (typeof children === 'string') {
		// `text-overflow: ellipsis` doesn't work on `<button/>`s.
		// https://stackoverflow.com/questions/9905409/is-it-possible-to-use-text-overflow-ellipsis-on-a-button-element
		itemChildren = [
			<span key="label" className="rrui__text-line">
				{children}
			</span>
		]
	} else {
		itemChildren = React.Children.toArray(children)
	}
	// Icon.
	if (icon) {
		itemChildren.unshift((
			<span key="icon" aria-hidden className="rrui__list__item-icon">
				{React.createElement(icon, { value, label })}
			</span>
		))
	}
	return itemChildren
}

function haveItemsChanged(props, prevProps)
{
	const items     = React.Children.toArray(props.children)
	const prevItems = React.Children.toArray(prevProps.children)

	if (items.length !== prevItems.length) {
		return true
	}

	let i = 0
	while (i < items.length)
	{
		if (items[i].props.value !== prevItems[i].props.value) {
			return true
		}
		i++
	}

	return false
}

export function findItemIndexByValue(value, children)
{
	const items = React.Children.toArray(children)

	let i = 0
	for (const item of items)
	{
		if (isSelectableItem(item) && item.props.value === value) {
			return i
		}
		i++
	}
}

function findItemIndexByLabel(value, children)
{
	const items = React.Children.toArray(children)

	let i = 0
	for (const item of items)
	{
		if (isSelectableItem(item)) {
			const itemLabel = getItemLabel(item)
			if (itemLabel && itemLabel.toLowerCase().indexOf(value.toLowerCase()) === 0) {
				return i
			}
		}
		i++
	}
}

function getItemLabel(item) {
	return item.props.label || (typeof item.props.children === 'string' ? item.props.children : undefined)
}

function isSelectableItem(item) {
	return item.props.component ? true : (item.props.children && !isDivider(item.props.children))
}

function isDivider(element) {
	// Workaround for `react-hot-loader`.
	// https://github.com/gaearon/react-hot-loader#checking-element-types
	return element.type && element.type.displayName === 'Divider'
}