lucid-ui
Version:
A UI component library from AppNexus.
118 lines (117 loc) • 4.7 kB
JavaScript
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 };