lbry-desktop/js/component/common.js
Alex Liebowitz c8754e4351 Round up line heights in TruncatedText (workaround for Clamp.js bug)
Clamp.js doesn't handle fractional-pixel line heights reliably. It
always rounds down the line height when calculating the target height
for the element, and you end up with one less line than you asked for.
2017-02-09 19:14:06 -05:00

137 lines
3.7 KiB
JavaScript

import React from 'react';
import lbry from '../lbry.js';
import $clamp from 'clamp-js-main';
//component/icon.js
export let Icon = React.createClass({
propTypes: {
icon: React.PropTypes.string.isRequired,
className: React.PropTypes.string,
fixed: React.PropTypes.bool,
},
render: function() {
const {fixed, className, ...other} = this.props;
const spanClassName = ('icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') +
this.props.icon + ' ' + (this.props.className || ''));
return <span className={spanClassName} {... other}></span>
}
});
export let TruncatedText = React.createClass({
propTypes: {
lines: React.PropTypes.number,
height: React.PropTypes.string,
auto: React.PropTypes.bool,
},
getDefaultProps: function() {
return {
lines: null,
height: null,
auto: true,
}
},
componentDidMount: function() {
// Manually round up the line height, because clamp.js doesn't like fractional-pixel line heights.
// Need to work directly on the style object because setting the style prop doesn't update internal styles right away.
this.refs.span.style.lineHeight = Math.ceil(parseFloat(getComputedStyle(this.refs.span).lineHeight)) + 'px';
$clamp(this.refs.span, {
clamp: this.props.lines || this.props.height || 'auto',
});
},
render: function() {
return <span ref="span" className="truncated-text">{this.props.children}</span>;
}
});
export let BusyMessage = React.createClass({
propTypes: {
message: React.PropTypes.string
},
render: function() {
return <span>{this.props.message} <span className="busy-indicator"></span></span>
}
});
var creditAmountStyle = {
color: '#216C2A',
fontWeight: 'bold',
fontSize: '0.8em'
}, estimateStyle = {
fontSize: '0.8em',
color: '#aaa',
};
export let CurrencySymbol = React.createClass({
render: function() { return <span>LBC</span>; }
});
export let CreditAmount = React.createClass({
propTypes: {
amount: React.PropTypes.number,
precision: React.PropTypes.number
},
render: function() {
var formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision ? this.props.precision : 1);
return (
<span className="credit-amount">
<span style={creditAmountStyle}>{formattedAmount} {parseFloat(formattedAmount) == 1.0 ? 'credit' : 'credits'}</span>
{ this.props.isEstimate ? <span style={estimateStyle}> (est)</span> : null }
</span>
);
}
});
var addressStyle = {
fontFamily: '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace',
};
export let Address = React.createClass({
propTypes: {
address: React.PropTypes.string,
},
render: function() {
return (
<span style={addressStyle}>{this.props.address}</span>
);
}
});
export let Thumbnail = React.createClass({
_defaultImageUri: '/img/default-thumb.svg',
_maxLoadTime: 10000,
_isMounted: false,
propTypes: {
src: React.PropTypes.string,
},
handleError: function() {
if (this.state.imageUrl != this._defaultImageUri) {
this.setState({
imageUri: this._defaultImageUri,
});
}
},
getInitialState: function() {
return {
imageUri: this.props.src || this._defaultImageUri,
};
},
componentDidMount: function() {
this._isMounted = true;
setTimeout(() => {
if (this._isMounted && !this.refs.img.complete) {
this.setState({
imageUri: this._defaultImageUri,
});
}
}, this._maxLoadTime);
},
componentWillUnmount: function() {
this._isMounted = false;
},
render: function() {
return <img ref="img" onError={this.handleError} {... this.props} src={this.state.imageUri} />
},
});