UNPKG

principles-ui-components

Version:

Supporting UI controller for Tizen TV web application, which developed base on React Framework.

255 lines (230 loc) 9.87 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { is, Map, fromJS } from 'immutable'; import { MAIN_TEXT_FONT, TextItemFamily, AnimationEffect, KEY } from './common/CommonDefine'; import './css/Tooltip.css'; import CommonAPI from './common/CommonAPI'; import ScrollText from './common/ScrollText'; import Image from './common/Image'; const tailResource = { normal: { bg: 'url(./images/tooltip/c_tooltip_white_bubble_bg_9patch.png) 24 14 fill stretch', top: 'url(./images/tooltip/c_tooltip_white_bubble_arrow_top.png)', bottom: 'url(./images/tooltip/c_tooltip_white_bubble_arrow_bottom.png)', left: 'url(./images/tooltip/c_tooltip_white_bubble_arrow_left.png)', right: 'url(./images/tooltip/c_tooltip_white_bubble_arrow_right.png)', }, highContrast: { bg: 'url(./images/tooltip/c_tooltip_highcontrast_bubble_bg_9patch.png) 24 14 fill stretch', top: 'url(./images/tooltip/c_tooltip_highcontrast_bubble_arrow_top.png)', bottom: 'url(./images/tooltip/c_tooltip_highcontrast_bubble_arrow_bottom.png)', left: 'url(./images/tooltip/c_tooltip_highcontrast_bubble_arrow_left.png)', right: 'url(./images/tooltip/c_tooltip_highcontrast_bubble_arrow_right.png)', }, }; const patchT = 24; const patchL = 14; const TOOLTIP_MIN_LENGTH = 132; const TOOLTIP_MAX_LENGTH = 902; export default class Tooltip extends Component { constructor(props) { super(props); this.balloonTextFont = MAIN_TEXT_FONT; this.balloonTextSize = TextItemFamily.TITLE2_TEXT_SIZE; this.bodyGap = TextItemFamily.BODY_TEXT_GAP; } componentWillMount() { } componentWillReceiveProps(nextProps) { } shouldComponentUpdate(nextProps, nextState) { // return true -->render() return (JSON.stringify(nextProps) !== JSON.stringify(this.props)); } componentDidUpdate(prevProps, prevState) { } componentWillUnmount() { } process() { const { OSD, showFlag, tailDirection, tailPostion, highContrast, enlarge, tailW, tailH } = this.props; const BalloonStyle = {}; BalloonStyle.position = 'relative'; BalloonStyle.left = OSD.layout.l; BalloonStyle.top = OSD.layout.t; BalloonStyle.height = OSD.layout.h; if (OSD.layout.w < TOOLTIP_MIN_LENGTH) { // TOOLTIP_MIN_LENGTH is min width BalloonStyle.width = TOOLTIP_MIN_LENGTH; } else if (OSD.layout.w > TOOLTIP_MAX_LENGTH) { // TOOLTIP_MAX_LENGTH is max width BalloonStyle.width = TOOLTIP_MAX_LENGTH; } else { BalloonStyle.width = OSD.layout.w; } if (showFlag) { BalloonStyle.animationName = 'Appear'; BalloonStyle.animationFillMode = 'forwards'; BalloonStyle.animationDuration = '1.10s'; BalloonStyle.animationTimingFunction = AnimationEffect.Elastic; } else { BalloonStyle.animationName = 'Disappear'; BalloonStyle.animationFillMode = 'forwards'; BalloonStyle.animationDuration = '0.85s'; BalloonStyle.animationTimingFunction = AnimationEffect.Out; } // calculate tail position const ArrowStyle = {}; ArrowStyle.position = 'absolute'; ArrowStyle.width = tailW; ArrowStyle.height = tailH; if (tailPostion === 'center') { if (tailDirection === 'top') { ArrowStyle.left = (BalloonStyle.width - this.props.tailW) / 2; ArrowStyle.top = 0; } else if (tailDirection === 'bottom') { ArrowStyle.left = (BalloonStyle.width - this.props.tailW) / 2; ArrowStyle.top = BalloonStyle.height - patchT; } else if (tailDirection === 'left') { ArrowStyle.left = -this.props.tailW + patchL; ArrowStyle.top = (BalloonStyle.height - this.props.tailH) / 2; } else if (tailDirection === 'right') { ArrowStyle.left = BalloonStyle.width - patchL; ArrowStyle.top = (BalloonStyle.height - this.props.tailH) / 2; } } else if (tailPostion === 'start') { ArrowStyle.left = this.props.tailOffset; if (tailDirection === 'top') { ArrowStyle.top = 0; } else if (tailDirection === 'bottom') { ArrowStyle.top = BalloonStyle.height - patchT; } else { ArrowStyle.top = 0; } } else if (tailPostion === 'end') { ArrowStyle.left = BalloonStyle.width - this.props.tailOffset - this.props.tailW; if (tailDirection === 'top') { ArrowStyle.top = 0; } else if (tailDirection === 'bottom') { ArrowStyle.top = BalloonStyle.height - patchT; } else { ArrowStyle.top = 0; } } if (highContrast) { ArrowStyle.backgroundImage = tailResource.highContrast[tailDirection]; } else { ArrowStyle.backgroundImage = tailResource.normal[tailDirection]; } const TextBGStyle = {}; TextBGStyle.position = 'absolute'; TextBGStyle.height = OSD.layout.h; TextBGStyle.width = OSD.layout.w; TextBGStyle.left = 0; TextBGStyle.borderStyle = 'solid'; TextBGStyle.borderWidth = '24px 14px'; TextBGStyle.borderImage = highContrast ? tailResource.highContrast.bg : tailResource.normal.bg; if (tailDirection === 'top') { TextBGStyle.top = this.props.tailH - patchT; } else if (tailDirection === 'bottom') { TextBGStyle.top = 0; } else { TextBGStyle.top = 0; } // icon compotent let iconComponentList = null; if (typeof OSD.icon !== 'undefined') { iconComponentList = (<Image key={'icon'} OSD={OSD.icon} />); } // text compotent const textComponentList = []; const TextStyle = {}; if (typeof OSD.icon !== 'undefined') { TextStyle.left = 14 + OSD.icon.w + 6; TextStyle.width = BalloonStyle.width - 25 - 28 - 6 - OSD.icon.w; } else { TextStyle.left = 11; TextStyle.width = BalloonStyle.width - 50; } const len = OSD.text.length; // OSD.text marked required if (len === 1) { TextStyle.height = TextItemFamily.TITLE2_TEXT_HEIGHT; TextStyle.lineHeight = TextItemFamily.TITLE2_TEXT_HEIGHT; } else { TextStyle.height = TextItemFamily.TITLE_TEXT_HEIGHT; TextStyle.lineHeight = TextItemFamily.TITLE_TEXT_HEIGHT; } const aligntext = (len === 1 && typeof OSD.icon === 'undefined') ? 'center' : 'left'; for (let idx = 0; idx < len; idx++) { TextStyle.top = ((OSD.layout.h - (2 * patchT) - (len * TextStyle.height)) / 2) + (idx * TextStyle.height); // console.log(`TextStyle.top: ${TextStyle.top} idx: ${idx}`); textComponentList.push( <ScrollText key={`text${idx}`} scroll={len === 1} fontSize={enlarge ? (this.balloonTextSize * 1.2) : this.balloonTextSize} fontFamily={this.balloonTextFont} textGap={this.bodyGap} width={TextStyle.width} height={TextStyle.height} top={TextStyle.top} left={TextStyle.left} lineHeight={`${TextStyle.lineHeight}px`} textAlign={aligntext} > {OSD.text[idx]} </ScrollText>); } return ( <div style={BalloonStyle}> <div style={ArrowStyle} /> <div style={TextBGStyle}> {textComponentList} {iconComponentList} </div> </div> ); } render() { return this.process(); } } Tooltip.defaultProps = { showFlag: true, tailW: 42, tailH: 30, tailOffset: 22, highContrast: false, enlarge: false, OSD: { layout: { l: 0, t: 0, w: 414, h: 116, }, icon: null, }, }; Tooltip.propTypes = { showFlag: PropTypes.bool, tailDirection: PropTypes.oneOf(['top', 'bottom', 'left', 'right']).isRequired, // tailDirection:top/bottom/left/right tailPostion: PropTypes.oneOf(['start', 'center', 'end']).isRequired, // tailPostion: start/center/end tailW: PropTypes.number, // tail width tailH: PropTypes.number, // tail height tailOffset: PropTypes.number, // The tail's offset distance relative to popup balloon's edge. highContrast: PropTypes.bool, enlarge: PropTypes.bool, OSD: PropTypes.shape({ // UI content layout: PropTypes.shape({ l: PropTypes.number, // tooltip left value t: PropTypes.number, // tooltip top value w: PropTypes.number, // tooltip width value h: PropTypes.number, //tooltip height value }), icon: PropTypes.shape({ l: PropTypes.number, t: PropTypes.number, w: PropTypes.number, h: PropTypes.number, url: PropTypes.string, }), text: PropTypes.array.isRequired, }), };