UNPKG

@minix-iot/ui

Version:

基于Vue的移动端轻量级UI组件库

365 lines (354 loc) 10.1 kB
import Icon from '../icon/icon.jsx'; import Switch from '../switch/switch.jsx'; import Tag from '../tag/tag.jsx'; import { Namespace } from '../../utils/namespace'; const namespace = Namespace.Create('cell'); export default { name: namespace.name, components: { Icon, [Switch.name]:Switch, Tag }, props: { value: { type: Boolean, default: false }, theme: { type: String, default: '' }, icon: { type: String, default: '' }, iconShape: { type: String, default: 'square' }, iconColor: { type: String, default: '' }, iconSize: { type: String, default: '' }, iconDot: { type: Boolean, default: false }, size: { type: String, default: 'small' }, title: { type: String | Number, required: true }, subtitle: { type: String, default: '' }, tags: { type: Array, default: () => [] }, desc: { type: String, default: '' }, stamp: { type: String, default: '' }, type: { type: String, default: 'normal' }, card: { type: Boolean, default: false }, disabled: { type: Boolean, default: false } }, model: { prop: 'value', event: 'change' }, data() { return { active: false, bodyHeaderStyle: '', collapse: false }; }, computed: { valueInner: { get() { return this.value; }, set(val) { this.$emit('change', val); } }, cls() { return namespace.derive({ disabled: this.disabled, collapse: this.collapse }); }, headerCls() { return namespace.derive('header', [ this.size, { active: this.active } ]); }, headerLeftCls() { return namespace.derive('header-left', { pdr: this.icon || this.$slots.left || this.isRadio }); }, iconCls(){ return namespace.derive('icon') }, headerRightWrapperCls() { return namespace.derive('header-right-wrapper'); }, headerRightCls() { return namespace.derive('header-right', { stamp: this.stamp }); }, prefixCls() { return namespace.derive('header-right-prefix'); }, middleCls() { return namespace.derive('header-right-middle', { prefix: this.desc || this.$slots.desc }); }, suffixCls() { return namespace.derive('header-right-suffix'); }, spliterCls() { return namespace.derive('spliter', { card: this.card }); }, titleCls() { return namespace.derive('title', { mgb: this.subtitle || this.$slots.subtitle }); }, titleTextCls() { return namespace.derive('title-text'); }, titleTagCls() { return namespace.derive('title-tag'); }, subtitleCls() { return namespace.derive('subtitle'); }, descCls() { return namespace.derive('desc', [ { more: !this.icon } ]); }, stampCls() { return namespace.derive('stamp', { small: this.size === 'large' }); }, linkCls() { return namespace.derive('arrow'); }, collapseCls() { return namespace.derive('collapse', { collapse: this.collapse }); }, bodyCls() { return namespace.derive('body'); }, isSmall() { return this.size === 'small'; }, isSwitch() { return this.type === 'switch'; }, isLink() { return this.type === 'link'; }, isCollapse() { return this.type === 'collapse'; }, iconSizeDict() { return { small: 20, middle: 28, large: 32, super: 48 }; }, iconSizePixel() { const size = this.iconSize ? this.iconSize : this.size; if (this.size === 'small') { return this.iconSizeDict.small; } return this.iconSizeDict[size]; }, isIconRound(){ return this.iconShape !== 'square' }, switchTheme() { return this.theme || 'brand'; }, transitionName() { return namespace.derive('slide'); } }, methods: { onClick() { this.$emit('click'); }, onTouchStart() { if (this.disabled) { return; } this.active = true; }, onTouchEnd() { if (this.disabled) { return; } this.active = false; }, onArrowClick() { console.log('click'); if (this.type === 'link') { return; } this.collapse = !this.collapse; if (!this.bodyHeaderStyle) { const width = this.$refs.hLeft.clientWidth; this.bodyHeaderStyle = `width: ${width}px`; } } }, render(){ const renderHeaderLeft = ()=>{ if(this.$slots.left){ return this.$slots.left } return this.icon && <Icon class={this.iconCls} theme={this.theme} name={this.icon} dot={this.iconDot} color={this.iconColor} size={this.iconSizePixel} round={this.isIconRound} /> } const renderPrefix = ()=>( <div class={this.prefixCls}> <div class={this.titleCls}> {renderTitle()} </div> <div class={this.subtitleCls}> {renderSubtitle()} </div> </div> ) const renderTitle = ()=>{ if(this.$slots.title){ return this.$slots.title } return [ <div class={this.titleTextCls}>{this.title}</div>, renderTags() ] } const renderTags = ()=> this.tags.map(x=><Tag theme="gray">{x}</Tag>) const renderSubtitle = ()=>{ if(this.$slots.subtitle){ return this.$slots.subtitle } return !this.isSmall && this.subtitle } const renderMiddle = ()=>( <div class={this.middleCls}> { this.$slots.desc || <div class={this.descCls}>{ this.desc }</div> } </div> ) const renderSuffix = ()=>( <div class={this.suffixCls}> { this.$slots.suffix || ( (this.stamp && <div class={this.stampCls}>{this.stamp}</div>) || (this.isSwitch && <mx-switch theme={this.switchTheme} vModel= {this.valueInner}/>) || (this.isLink && <Icon name= "arrow-right" size={10} />) || (this.isCollapse &&( <div class={this.collapseCls} onClick={this.onArrowClick}> <Icon name= "arrow-right" size={10} /> </div> )) ) } </div> ) const renderHeader = ()=> ( <div class={this.headerCls} onClick={this.onClick} onTouchstart={this.onTouchStart} onTouchend={this.onTouchEnd} onTouchcancel={this.onTouchEnd} > <div class={this.headerLeftCls} ref="hLeft"> {renderHeaderLeft()} </div> <div class={this.headerRightWrapperCls}> <div class={this.headerRightCls}> {renderPrefix()} {renderMiddle()} {renderSuffix()} </div> <div class={this.spliterCls}></div> </div> </div> ) const renderBody = ()=>( <Transition name={this.transitionName}> { this.collapse && <div class={this.bodyCls}> { this.$slots.body || [ <div style={this.bodyHeaderStyle}> {this.$slots['body-header']} </div>, <div> {this.$slots['body-content']} </div> ] } </div> } </Transition> ) return ( <div class={this.cls}> {renderHeader()} {renderBody()} </div> ) } };