Created
February 27, 2015 12:58
-
-
Save mtscout6/82badde3a3baf9ba6db8 to your computer and use it in GitHub Desktop.
Potential TODOs for the Panel Component in react-bootstrap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | |
// TODO: Evaluate extracting collapsable logic to CollapsablePanel, The | |
// Accordian would likewise manage collapsed state itself. | |
var Panel = React.createClass({ | |
mixins: [BootstrapMixin, CollapsableMixin], | |
propTypes: { | |
id: React.PropTypes.node, | |
onSelect: React.PropTypes.func, | |
header: React.PropTypes.node, | |
footer: React.PropTypes.node, | |
eventKey: React.PropTypes.any, | |
collapsable: React.PropTypes.bool, | |
fill: React.PropTypes.bool | |
}, | |
getDefaultProps: function () { | |
return { | |
bsClass: 'panel', | |
bsStyle: 'default' | |
}; | |
}, | |
handleSelect: function (e) { | |
if (this.props.onSelect) { | |
// TODO: This feels wonky why would a component try to update when the | |
// following function is called? Should probably be the concern of the | |
// caller to handle async work? | |
this._isChanging = true; | |
this.props.onSelect(this.props.eventKey); | |
this._isChanging = false; | |
} | |
// TODO: Allow dev to control this with return value from onSelect | |
e.preventDefault(); | |
// TODO: Should this still happen if onSelect result does not permit e.preventDefault? | |
this.setState({ | |
expanded: !this.state.expanded | |
}); | |
}, | |
shouldComponentUpdate: function () { | |
// TODO: This should go away, poor async handling | |
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(); | |
// TODO: Why? this.getBsClassSet() should already set this to true. Unless | |
// the bsClass provided is different. Is that expected? | |
classes.panel = true; | |
return ( | |
<div {...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()} | |
</div> | |
); | |
}, | |
renderCollapsableBody: function () { | |
// TODO: Do we need to add some kind of aria tag here when we collapse and uncollapse? | |
return ( | |
<div className={classSet(this.getCollapsableClassSet('panel-collapse'))} id={this.props.id} ref="panel"> | |
{this.renderBody()} | |
</div> | |
); | |
}, | |
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( | |
<div className="panel-body" {...getProps()}> | |
{children} | |
</div> | |
); | |
} | |
// 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, { | |
// TODO: inherit bsClass from prop | |
className: 'panel-title', | |
children: this.renderAnchor(header.props.children) | |
}); | |
} else { | |
header = cloneWithProps(header, { | |
// TODO: inherit bsClass from prop | |
className: 'panel-title' | |
}); | |
} | |
return ( | |
// TODO: inherit bsClass from prop | |
<div className="panel-heading"> | |
{header} | |
</div> | |
); | |
}, | |
// TODO: Potentially use button here to address accessibility concerns | |
renderAnchor: function (header) { | |
return ( | |
<a | |
href={'#' + (this.props.id || '')} | |
className={this.isExpanded() ? null : 'collapsed'} | |
onClick={this.handleSelect}> | |
{header} | |
</a> | |
); | |
}, | |
renderCollapsableTitle: function (header) { | |
return ( | |
// TODO: inherit bsClass from prop | |
// TODO: h4 may cause accessability concerns | |
<h4 className="panel-title"> | |
{this.renderAnchor(header)} | |
</h4> | |
); | |
}, | |
renderFooter: function () { | |
if (!this.props.footer) { | |
return null; | |
} | |
return ( | |
// TODO: inherit bsClass from prop | |
<div className="panel-footer"> | |
{this.props.footer} | |
</div> | |
); | |
} | |
}); | |
module.exports = Panel; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment