UNPKG

tuya-panel-kit

Version:

a functional component library for developing tuya device panels!

207 lines (200 loc) 5.25 kB
import PropTypes from 'prop-types'; import React from 'react'; import { StyleSheet, View, ViewPropTypes, I18nManager } from 'react-native'; import IconFont from '../iconfont/svg'; import TYText from '../TYText'; import svgs from '../iconfont/svg/defaultSvg'; export default class UnitTextSvg extends React.PureComponent { static propTypes = { /** * 内容样式 */ style: ViewPropTypes.style, /** * 字体尺寸大小,valueSize 或 unitSize 的缩写版 * 其中 valueSize 将会和与 size 相同,unitSize 将会为 size 值的一半。 */ size: PropTypes.number, /** * 值的大小 */ valueSize: PropTypes.number, /** * 可以用来定制每个值的颜色 */ valueColors: PropTypes.array, /** * 值的颜色 */ valueColor: PropTypes.string, /** * 单位,字符串为内置的 svg name */ unit: PropTypes.string, /** * 单位的大小 */ unitSize: PropTypes.number, /** * 单位的颜色 */ unitColor: PropTypes.string, /** * 单位的左边距 */ unitPaddingLeft: PropTypes.number, /** * 单位的上边距 */ unitPaddingTop: PropTypes.number, /** * 单位的类型 */ unitType: PropTypes.oneOf(['icon', 'text']), /** * 值 */ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, /** * 自定义文字的宽度 */ letterWidth: PropTypes.number, /** * 自定义符号的宽度(如.,:等) */ symbolWidth: PropTypes.number, /** * 哪些字符串被认作为symbol,并被应用与symbolWidth */ symbols: PropTypes.array, /** * 额外的svg路径映射表,用于拓展内部的svg path或覆盖内部的svg path */ svgMap: PropTypes.object, }; static defaultProps = { style: null, unit: '', valueSize: null, unitSize: null, size: 82, valueColors: [], valueColor: 'white', unitColor: 'white', unitPaddingLeft: 0, unitPaddingTop: 0, letterWidth: 0.55, symbolWidth: 0.35, symbols: ['.', ':', ','], svgMap: {}, unitType: 'icon', }; getLetterPadding(letterWidth) { const letterPadding = (1 - letterWidth) / 2; return letterPadding; } renderUnit() { const { unit, unitSize, valueSize, size, unitColor, unitPaddingLeft, unitPaddingTop, letterWidth, svgMap, unitType, } = this.props; if (!unit) { return null; } const uSize = unitSize || size / 2; const isRtl = I18nManager.isRTL; const marginType = isRtl ? 'marginRight' : 'marginLeft'; const vSize = valueSize || size; const letterPadding = this.getLetterPadding(letterWidth); const uNeedLeft = (vSize + uSize) * (letterPadding - 0.025); const unitStyle = [{ marginTop: unitPaddingTop, [marginType]: -uNeedLeft + unitPaddingLeft }]; const allSvgs = { ...svgs, ...svgMap }; return unitType === 'icon' ? ( <IconFont d={allSvgs[unit] || unit} size={uSize} style={unitStyle} color={unitColor} /> ) : ( <TYText style={[ { fontSize: uSize, color: unitColor, }, unitStyle, ]} > {unit} </TYText> ); } render() { const { style, size, valueSize, valueColor, valueColors, unit, unitSize, unitColor, unitPaddingLeft, unitPaddingTop, value, letterWidth, symbolWidth, symbols, svgMap, ...rest } = this.props; const isRtl = I18nManager.isRTL; const letter = `${value}`.split(''); if (!letter || !letter.length) return null; const vSize = valueSize || size; const marginType = isRtl ? 'marginRight' : 'marginLeft'; const wrapperStyle = [ styles.wrapperStyle, { flexDirection: isRtl ? 'row-reverse' : 'row' }, style, ]; const allSvgs = { ...svgs, ...svgMap }; const symbolIdx = letter .map((l, lIdx) => (symbols.includes(l) ? lIdx : undefined)) .filter(i => !!i); return ( <View {...rest} style={wrapperStyle}> {letter.map((l, i) => { const letterPadding = this.getLetterPadding(letterWidth); let needLeft = vSize * (letterPadding * 2 - 0.05); // 如果为 symbol 则需要缩减其渲染大小 if (symbolIdx.includes(i) || symbolIdx.includes(i - 1)) { const specialLetterPadding = this.getLetterPadding(symbolWidth); needLeft = vSize * (specialLetterPadding * 2 - 0.05); } const letterStyle = [i !== 0 && { [marginType]: -needLeft }]; const color = valueColors[i] ? valueColors[i] : valueColor; return ( <IconFont d={allSvgs[l]} size={vSize} style={letterStyle} key={`TYUnitText_${l}_${i + 1}`} color={color} /> ); })} {this.renderUnit()} </View> ); } } const styles = StyleSheet.create({ wrapperStyle: { justifyContent: 'center', }, });