UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

118 lines (117 loc) 4.7 kB
import _ from 'lodash'; import React from 'react'; import PropTypes from 'react-peek/prop-types'; import { lucidClassNames } from '../../util/style-helpers'; import { findTypes, omitProps, } from '../../util/component-types'; import { buildModernHybridComponent } from '../../util/state-management'; import ChevronIcon from '../Icon/ChevronIcon/ChevronIcon'; import Collapsible from '../Collapsible/Collapsible'; import * as reducers from './Expander.reducers'; import Button from '../Button/Button'; const cx = lucidClassNames.bind('&-Expander'); const { any, bool, func, node, object, oneOf, string } = PropTypes; const Label = (_props) => null; Label.displayName = 'Expander.Label'; Label.peek = { description: ` Renders a \`<span>\` to be shown next to the expander icon. `, }; Label.propName = 'Label'; Label.propTypes = { children: node ` Used to identify the purpose of this switch to the user -- can be any renderable content. `, }; const AdditionalLabelContent = (_props) => null; AdditionalLabelContent.displayName = 'Expander.AdditionalLabelContent'; AdditionalLabelContent.peek = { description: ` Renders a \`<span>\` to be shown next to the expander label. `, }; AdditionalLabelContent.propName = 'AdditionalLabelContent'; AdditionalLabelContent.propTypes = { children: node ` Used to display additional information or/and actions next to expander label. `, }; const defaultProps = { isExpanded: false, onToggle: _.noop, kind: 'simple', }; class Expander extends React.Component { constructor() { super(...arguments); this.handleToggle = (event) => { this.props.onToggle(!this.props.isExpanded, { event, props: this.props, }); }; } render() { const { children, className, isExpanded, style, kind, ...passThroughs } = this.props; const labelChildProp = _.first(_.map(findTypes(this.props, Expander.Label), 'props')); const additionalLabelContentChildProp = _.first(_.map(findTypes(this.props, Expander.AdditionalLabelContent), 'props')); return (React.createElement("div", Object.assign({}, omitProps(passThroughs, undefined, _.keys(Expander.propTypes)), { className: cx('&', { '&-is-expanded': isExpanded, '&-kind-highlighted': kind === 'highlighted', }, className), style: style }), React.createElement("header", { className: cx('&-header') }, React.createElement("div", { className: cx('&-header-toggle'), onClick: this.handleToggle }, React.createElement(Button, { className: cx('&-icon'), kind: 'invisible', hasOnlyIcon: true }, React.createElement(ChevronIcon, { direction: isExpanded ? 'up' : 'down' })), labelChildProp && (React.createElement("span", { className: cx('&-text') }, labelChildProp.children))), additionalLabelContentChildProp && (React.createElement("div", { className: cx('&-additional-content') }, additionalLabelContentChildProp.children))), React.createElement(Collapsible, { isExpanded: isExpanded, rootType: 'section', className: cx('&-content') }, children))); } } Expander.displayName = 'Expander'; Expander.propTypes = { children: node ` Expandable content. `, className: string ` Appended to the component-specific class names set on the root element. `, isExpanded: bool ` Indicates that the component is in the "expanded" state when true and in the "unexpanded" state when false. `, onToggle: func ` Called when the user clicks on the component's header. Signature: \`(isExpanded, { event, props }) => {}\` `, style: object ` Passed through to the root element. `, Label: any ` Child element whose children represents content to be shown next to the expander icon. `, AdditionalLabelContent: node ` Child element whose children respresent content to be shown inside Expander.Label and to the right of it `, kind: oneOf(['simple', 'highlighted']) ` Renders different variants of Expander. 'simple' is default. 'highlighted' is more prominant. `, }; Expander.defaultProps = defaultProps; Expander.reducers = reducers; Expander.Label = Label; Expander.AdditionalLabelContent = AdditionalLabelContent; Expander.peek = { description: ` This is a container that provides a toggle that controls when the content is shown. `, categories: ['layout'], madeFrom: ['ChevronIcon'], }; export default buildModernHybridComponent(Expander, { reducers }); export { Expander as ExpanderDumb };