@minix-iot/ui
Version:
基于Vue的移动端轻量级UI组件库
365 lines (354 loc) • 10.1 kB
JSX
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>
)
}
};