All files / components/Panel Panel.jsx

100% Statements 8/8
100% Branches 4/4
100% Functions 1/1
100% Lines 8/8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131            134x   134x             134x                                                                                                                 268x                               39x   39x     39x       39x                                                                  
import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import { createClass, findTypes, omitProps } from '../../util/component-types';
 
const cx = lucidClassNames.bind('&-Panel');
 
const { bool, node, object, string } = PropTypes;
 
/**
 * {"categories": ["layout"]}
 *
 * Panel is used to wrap content to better organize elements in window.
 */
const Panel = createClass({
	displayName: 'Panel',
 
	components: {
		/**
		 * Content displayed at the top of the panel.
		 */
		Header: createClass({
			displayName: 'Panel.Header',
			propName: 'Header',
		}),
		/**
		 * Content displayed at the bottom of the panel.
		 */
		Footer: createClass({
			displayName: 'Panel.Footer',
			propName: 'Footer',
		}),
	},
 
	propTypes: {
		/**
		 * Appended to the component-specific class names set on the root element.
		 */
		className: string,
		/**
		 * *Child Element* - Header contents. Only one `Header` is used.
		 */
		Header: node,
		/**
		 * *Child Element* - Footer contents. Only one `Footer` is used.
		 */
		Footer: node,
		/**
		 * Generally you should only have a single child element so the centering
		 * works correctly.
		 */
		children: node,
		/**
		 * If set to true, creates a content section with no padding.
		 */
		isGutterless: bool,
		/**
		 * If set to false, removes margin around the Panel
		 */
		hasMargin: bool,
		/**
		 * Styles that are passed through to root element.
		 */
		style: object,
		/**
		 * If set to true, makes content overflow scrollable, when Panel has a set height.
		 */
		isScrollable: bool,
	},
 
	getDefaultProps() {
		return {
			isGutterless: false,
			hasMargin: true,
			isScrollable: true,
		};
	},
 
	render: function() {
		const {
			children,
			className,
			isGutterless,
			hasMargin,
			style,
			isScrollable,
			...passThroughs
		} = this.props;
 
		const headerChildProp = _.first(
			_.map(findTypes(this.props, Panel.Header), 'props')
		);
		const footerChildProp = _.first(
			_.map(findTypes(this.props, Panel.Footer), 'props')
		);
 
		return (
			<div
				{...omitProps(passThroughs, Panel)}
				className={cx('&', className, {
					'&-is-not-gutterless': !isGutterless,
					'&-has-margin': hasMargin,
					'&-is-scrollable': isScrollable,
				})}
				style={style}
			>
				{headerChildProp
					? <header
							{...headerChildProp}
							className={cx('&-Header', headerChildProp.className)}
						/>
					: null}
 
				<section className={cx('&-content')}>
					{children}
				</section>
 
				{footerChildProp
					? <footer
							{...footerChildProp}
							className={cx('&-Footer', footerChildProp.className)}
						/>
					: null}
			</div>
		);
	},
});
 
export default Panel;