lucid-ui
Version:
A UI component library from AppNexus.
109 lines (108 loc) • 4.36 kB
JavaScript
import _ from 'lodash';
import React from 'react';
import PropTypes from 'react-peek/prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import { getFirst, omitProps } from '../../util/component-types';
import { buildModernHybridComponent } from '../../util/state-management';
import ChevronIcon from '../Icon/ChevronIcon/ChevronIcon';
import Collapsible from '../Collapsible/Collapsible';
import Button from '../Button/Button';
import Panel from '../Panel/Panel';
import * as reducers from '../Expander/Expander.reducers';
const cx = lucidClassNames.bind('&-ExpanderPanel');
const { any, bool, func, node, object, string } = PropTypes;
const Header = (_props) => null;
Header.displayName = 'ExpanderPanel.Header';
Header.peek = {
description: `
Renders a \`<span>\` of content next to the \`ChevronIcon\` in the
\`Panel.Header\`
`,
};
Header.propName = 'Header';
Header.propTypes = {
children: node `
Used to identify the purpose of this switch to the user -- can be any
renderable content.
`,
};
class ExpanderPanel extends React.Component {
constructor() {
super(...arguments);
this.handleToggle = (event) => {
if (!this.props.isDisabled) {
this.props.onToggle(!this.props.isExpanded, {
event,
props: this.props,
});
}
};
}
render() {
const { children, className, isExpanded, isDisabled, hasPadding, onRest, onRestAppliedOnCollapse, style, ...passThroughs } = this.props;
const headerChildProps = _.get(getFirst(this.props, ExpanderPanel.Header), 'props');
const cleanedOnRest = (onRestAppliedOnCollapse || isExpanded) ? onRest : undefined;
return (React.createElement(Panel, Object.assign({}, omitProps(passThroughs, undefined, _.keys(ExpanderPanel.propTypes), false), { className: cx('&', {
'&-is-collapsed': !isExpanded,
'&-is-disabled': isDisabled,
}, className), style: style, isGutterless: !hasPadding }),
React.createElement(Panel.Header, { className: cx('&-header'), onClick: this.handleToggle },
React.createElement(Button, { className: cx('&-icon'), kind: 'invisible', hasOnlyIcon: true },
React.createElement(ChevronIcon, { direction: isExpanded ? 'up' : 'down' })),
React.createElement("span", Object.assign({}, headerChildProps))),
React.createElement(Collapsible, { isExpanded: isExpanded, className: cx('&-content', {
'&-content-is-expanded': isExpanded,
}), onRest: cleanedOnRest },
React.createElement("div", { className: cx('&-content-inner') }, children))));
}
}
ExpanderPanel.displayName = 'ExpanderPanel';
ExpanderPanel.Header = Header;
ExpanderPanel.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.
`,
isDisabled: bool `
Indicates that the component is in the "disabled" state when true and in
the "enabled" state when false.
`,
hasPadding: bool `
Controls the presence of padding on the inner content.
`,
onToggle: func `
Called when the user clicks on the component's header.
Signature: \`(isExpanded, { event, props }) => {}\`
`,
style: object `
Passed through to the root element.
`,
onRest: func `Optional. The callback that fires when the animation comes to a rest.`,
onRestAppliedOnCollapse: bool `Applies on onRest callback when rest state is closed.`,
Header: any `
prop alternative to Header child component passed through to the
underlying ExpanderPanel
`,
};
ExpanderPanel.peek = {
description: `
This is a container that provides a toggle that controls when the
content is shown.
`,
categories: ['layout'],
madeFrom: ['ChevronIcon', 'Expander', 'Panel'],
};
ExpanderPanel.defaultProps = {
isExpanded: false,
onToggle: _.noop,
hasPadding: true,
isDisabled: false,
};
export default buildModernHybridComponent(ExpanderPanel, { reducers });
export { ExpanderPanel as ExpanderPanelDumb };