feat: Grid component

This commit is contained in:
chenjiahan
2020-07-06 16:49:07 +08:00
parent 3bf64717b5
commit 660e535811
12 changed files with 1012 additions and 8 deletions
+151
View File
@@ -0,0 +1,151 @@
// Utils
import { createNamespace, addUnit } from '../utils';
import { BORDER } from '../utils/constant';
import { route, routeProps } from '../utils/router';
// Mixins
import { ChildrenMixin } from '../mixins/relation';
// Components
import Info from '../info';
import Icon from '../icon';
const [createComponent, bem] = createNamespace('grid-item');
export default createComponent({
mixins: [ChildrenMixin('vanGrid')],
props: {
...routeProps,
dot: Boolean,
text: String,
icon: String,
iconPrefix: String,
badge: [Number, String],
},
emits: ['click'],
computed: {
style() {
const { square, gutter, columnNum } = this.parent;
const percent = `${100 / columnNum}%`;
const style = {
flexBasis: percent,
};
if (square) {
style.paddingTop = percent;
} else if (gutter) {
const gutterValue = addUnit(gutter);
style.paddingRight = gutterValue;
if (this.index >= columnNum) {
style.marginTop = gutterValue;
}
}
return style;
},
contentStyle() {
const { square, gutter } = this.parent;
if (square && gutter) {
const gutterValue = addUnit(gutter);
return {
right: gutterValue,
bottom: gutterValue,
height: 'auto',
};
}
},
},
methods: {
onClick(event) {
this.$emit('click', event);
route(this.$router, this);
},
genIcon() {
if (this.$slots.icon) {
return (
<div class={bem('icon-wrapper')}>
{this.$slots.icon()}
<Info dot={this.dot} info={this.badge} />
</div>
);
}
if (this.icon) {
return (
<Icon
name={this.icon}
dot={this.dot}
info={this.badge}
size={this.parent.iconSize}
class={bem('icon')}
classPrefix={this.iconPrefix}
/>
);
}
},
getText() {
if (this.$slots.text) {
return this.$slots.text();
}
if (this.text) {
return <span class={bem('text')}>{this.text}</span>;
}
},
genContent() {
if (this.$slots.default) {
return this.$slots.default();
}
return [this.genIcon(), this.getText()];
},
},
render() {
const {
center,
border,
square,
gutter,
direction,
clickable,
} = this.parent;
return (
<div class={[bem({ square })]} style={this.style}>
<div
style={this.contentStyle}
role={clickable ? 'button' : null}
tabindex={clickable ? 0 : null}
class={[
bem('content', [
direction,
{
center,
square,
clickable,
surround: border && gutter,
},
]),
{ [BORDER]: border },
]}
onClick={this.onClick}
>
{this.genContent()}
</div>
</div>
);
},
});
+78
View File
@@ -0,0 +1,78 @@
@import '../style/var';
.van-grid-item {
position: relative;
box-sizing: border-box;
&--square {
height: 0;
}
&__icon {
font-size: @grid-item-icon-size;
}
&__icon-wrapper {
position: relative;
}
&__text {
color: @grid-item-text-color;
font-size: @grid-item-text-font-size;
line-height: 1.5;
word-wrap: break-word;
}
&__icon + &__text {
margin-top: @padding-xs;
}
&__content {
display: flex;
flex-direction: column;
box-sizing: border-box;
height: 100%;
padding: @grid-item-content-padding;
background-color: @grid-item-content-background-color;
&::after {
z-index: 1;
border-width: 0 @border-width-base @border-width-base 0;
}
&--square {
position: absolute;
top: 0;
right: 0;
left: 0;
}
&--center {
align-items: center;
justify-content: center;
}
&--horizontal {
flex-direction: row;
.van-grid-item__icon + .van-grid-item__text {
margin-top: 0;
margin-left: @padding-xs;
}
}
&--surround {
&::after {
border-width: @border-width-base;
}
}
&--clickable {
cursor: pointer;
&:active {
background-color: @grid-item-content-active-color;
}
}
}
}