react-bootstrap
Version:
Bootstrap 3 components build with React
199 lines (163 loc) • 4.82 kB
JavaScript
var React = require('react');
var joinClasses = require('./utils/joinClasses');
var classSet = require('./utils/classSet');
var cloneWithProps = require('./utils/cloneWithProps');
var BootstrapMixin = require('./BootstrapMixin');
var CollapsableMixin = require('./CollapsableMixin');
var Panel = React.createClass({displayName: "Panel",
mixins: [BootstrapMixin, CollapsableMixin],
propTypes: {
onSelect: React.PropTypes.func,
header: React.PropTypes.node,
footer: React.PropTypes.node,
eventKey: React.PropTypes.any
},
getDefaultProps: function () {
return {
bsClass: 'panel',
bsStyle: 'default'
};
},
handleSelect: function (e) {
if (this.props.onSelect) {
this._isChanging = true;
this.props.onSelect(this.props.eventKey);
this._isChanging = false;
}
e.preventDefault();
this.setState({
expanded: !this.state.expanded
});
},
shouldComponentUpdate: function () {
return !this._isChanging;
},
getCollapsableDimensionValue: function () {
return this.refs.panel.getDOMNode().scrollHeight;
},
getCollapsableDOMNode: function () {
if (!this.isMounted() || !this.refs || !this.refs.panel) {
return null;
}
return this.refs.panel.getDOMNode();
},
render: function () {
var classes = this.getBsClassSet();
classes['panel'] = true;
return (
React.createElement("div", React.__spread({}, this.props, {className: joinClasses(this.props.className, classSet(classes)),
id: this.props.collapsable ? null : this.props.id, onSelect: null}),
this.renderHeading(),
this.props.collapsable ? this.renderCollapsableBody() : this.renderBody(),
this.renderFooter()
)
);
},
renderCollapsableBody: function () {
return (
React.createElement("div", {className: classSet(this.getCollapsableClassSet('panel-collapse')), id: this.props.id, ref: "panel"},
this.renderBody()
)
);
},
renderBody: function () {
var allChildren = this.props.children;
var bodyElements = [];
function getProps() {
return {key: bodyElements.length};
}
function addPanelChild (child) {
bodyElements.push(cloneWithProps(child, getProps()));
}
function addPanelBody (children) {
bodyElements.push(
React.createElement("div", React.__spread({className: "panel-body"}, getProps()),
children
)
);
}
// Handle edge cases where we should not iterate through children.
if (!Array.isArray(allChildren) || allChildren.length == 0) {
if (this.shouldRenderFill(allChildren)) {
addPanelChild(allChildren);
} else {
addPanelBody(allChildren);
}
} else {
var panelBodyChildren = [];
function maybeRenderPanelBody () {
if (panelBodyChildren.length == 0) {
return;
}
addPanelBody(panelBodyChildren);
panelBodyChildren = [];
}
allChildren.forEach(function(child) {
if (this.shouldRenderFill(child)) {
maybeRenderPanelBody();
// Separately add the filled element.
addPanelChild(child);
} else {
panelBodyChildren.push(child);
}
}.bind(this));
maybeRenderPanelBody();
}
return bodyElements;
},
shouldRenderFill: function (child) {
return React.isValidElement(child) && child.props.fill != null
},
renderHeading: function () {
var header = this.props.header;
if (!header) {
return null;
}
if (!React.isValidElement(header) || Array.isArray(header)) {
header = this.props.collapsable ?
this.renderCollapsableTitle(header) : header;
} else if (this.props.collapsable) {
header = cloneWithProps(header, {
className: 'panel-title',
children: this.renderAnchor(header.props.children)
});
} else {
header = cloneWithProps(header, {
className: 'panel-title'
});
}
return (
React.createElement("div", {className: "panel-heading"},
header
)
);
},
renderAnchor: function (header) {
return (
React.createElement("a", {
href: '#' + (this.props.id || ''),
className: this.isExpanded() ? null : 'collapsed',
onClick: this.handleSelect},
header
)
);
},
renderCollapsableTitle: function (header) {
return (
React.createElement("h4", {className: "panel-title"},
this.renderAnchor(header)
)
);
},
renderFooter: function () {
if (!this.props.footer) {
return null;
}
return (
React.createElement("div", {className: "panel-footer"},
this.props.footer
)
);
}
});
module.exports = Panel;