update: [Grid] merged from vue-component/grid

This commit is contained in:
wanlei 2017-10-27 13:24:22 +08:00
parent 894f6031fa
commit 3290cdf114
11 changed files with 495 additions and 3 deletions

View File

@ -1,4 +1,9 @@
{
"presets": ["env"],
"plugins": ["transform-vue-jsx"]
"plugins": [
"transform-vue-jsx",
"transform-es2015-destructuring",
"transform-es2015-parameters",
"transform-object-rest-spread"
]
}

85
components/grid/col.vue Normal file
View File

@ -0,0 +1,85 @@
<script>
// Equal or Larger Than 0
function elt0 (value) {
return value >= 0
}
// equal to 0(default) or more
const DEFAULT_0_OR_MORE = {
'default': 0,
validator: elt0,
}
export default {
name: 'Col',
props: {
prefixCls: {
'default': 'ant-col',
type: String,
},
span: Number,
order: DEFAULT_0_OR_MORE,
offset: DEFAULT_0_OR_MORE,
push: DEFAULT_0_OR_MORE,
pull: DEFAULT_0_OR_MORE,
xs: [Number, Object],
sm: [Number, Object],
md: [Number, Object],
lg: [Number, Object],
xl: [Number, Object],
},
computed: {
classes () {
const { prefixCls, span, order, offset, push, pull } = this
let sizeClassObj = {};
['xs', 'sm', 'md', 'lg', 'xl'].forEach(size => {
let sizeProps = {}
if (typeof this[size] === 'number') {
sizeProps.span = this[size]
} else if (typeof this[size] === 'object') {
sizeProps = this[size] || {}
}
sizeClassObj = {
...sizeClassObj,
[`${prefixCls}-${size}-${sizeProps.span}`]: sizeProps.span !== undefined,
[`${prefixCls}-${size}-order-${sizeProps.order}`]: sizeProps.order || sizeProps.order === 0,
[`${prefixCls}-${size}-offset-${sizeProps.offset}`]: sizeProps.offset || sizeProps.offset === 0,
[`${prefixCls}-${size}-push-${sizeProps.push}`]: sizeProps.push || sizeProps.push === 0,
[`${prefixCls}-${size}-pull-${sizeProps.pull}`]: sizeProps.pull || sizeProps.pull === 0,
}
})
return {
[`${prefixCls}`]: true,
[`${prefixCls}-${span}`]: span !== undefined,
[`${prefixCls}-order-${order}`]: order,
[`${prefixCls}-offset-${offset}`]: offset,
[`${prefixCls}-push-${push}`]: push,
[`${prefixCls}-pull-${pull}`]: pull,
...sizeClassObj,
}
},
gutter () {
let parent = this.$parent
while (parent && parent.$options.name !== 'Row') {
console.info(parent.$options.name)
parent = parent.$parent
}
return parent ? parent.gutter : 0
},
},
render (h) {
const style = {}
if (this.gutter) {
style.paddingLeft = this.gutter / 2 + 'px'
style.paddingRight = style.paddingLeft
}
console.info(style)
// why only unnamed slots
return h('div', {
'class': this.classes,
style,
}, this.$slots['default'])
},
}
</script>

7
components/grid/index.js Normal file
View File

@ -0,0 +1,7 @@
import Row from './row.vue'
import Col from './col.vue'
export default {
Col, Row,
}

79
components/grid/row.vue Normal file
View File

@ -0,0 +1,79 @@
<template>
<div :class="classes" :style="modifiedStyle">
<slot />
</div>
</template>
<script>
export default {
name: 'Row',
props: {
prefixCls: {
'default': 'ant-row',
type: String,
},
type: {
validator (value) {
// flex can't work before IE11
if (document.all && document.compatMode) {
console.error('you cannot use flex in the old browser')
return false
}
return ['flex', ''].includes(value)
},
},
gutter: {
'default': 0,
validator: k => k >= 0,
},
align: {
'default': 'top',
validator (value) {
return ['top', 'middle', 'bottom'].includes(value)
},
},
justify: {
'default': 'start',
validator (value) {
return ['start', 'end', 'center', 'space-around', 'space-between'].includes(value)
},
},
},
data () {
const half = this.gutter / 2
return {
modifiedStyle: {
'margin-left': -half + 'px',
'margin-right': -half + 'px',
},
}
},
computed: {
classes () {
const { prefixCls, type, align, justify } = this
return {
[`${prefixCls}`]: true,
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-${type}-${justify}`]: type && justify,
[`${prefixCls}-${type}-${align}`]: type && align,
}
},
},
methods: {
handleClick (event) {
if (this.clicked) {
return
}
this.clicked = true
clearTimeout(this.timeout)
this.timeout = setTimeout(() => (this.clicked = false), 500)
this.$emit('click', event)
},
},
beforeDestroy () {
if (this.timeout) {
clearTimeout(this.timeout)
}
},
}
</script>

View File

@ -0,0 +1,2 @@
import '../../style/index.less'
import './index.less'

View File

@ -0,0 +1,107 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@import "./mixin";
// Grid system
.@{ant-prefix}-row {
.make-row();
display: block;
}
.@{ant-prefix}-row-flex {
display: flex;
flex-flow: row wrap;
&:before,
&:after {
display: flex;
}
}
// x轴原点
.@{ant-prefix}-row-flex-start {
justify-content: flex-start;
}
// x轴居中
.@{ant-prefix}-row-flex-center {
justify-content: center;
}
// x轴反方向
.@{ant-prefix}-row-flex-end {
justify-content: flex-end;
}
// x轴平分
.@{ant-prefix}-row-flex-space-between {
justify-content: space-between;
}
// x轴有间隔地平分
.@{ant-prefix}-row-flex-space-around {
justify-content: space-around;
}
// 顶部对齐
.@{ant-prefix}-row-flex-top {
align-items: flex-start;
}
// 居中对齐
.@{ant-prefix}-row-flex-middle {
align-items: center;
}
// 底部对齐
.@{ant-prefix}-row-flex-bottom {
align-items: flex-end;
}
.@{ant-prefix}-col {
position: relative;
display: block;
}
.make-grid-columns();
.make-grid();
// Extra small grid
//
// Columns, offsets, pushes, and pulls for extra small devices like
// smartphones.
.make-grid(-xs);
// Small grid
//
// Columns, offsets, pushes, and pulls for the small device range, from phones
// to tablets.
@media (min-width: @screen-sm-min) {
.make-grid(-sm);
}
// Medium grid
//
// Columns, offsets, pushes, and pulls for the desktop device range.
@media (min-width: @screen-md-min) {
.make-grid(-md);
}
// Large grid
//
// Columns, offsets, pushes, and pulls for the large desktop device range.
@media (min-width: @screen-lg-min) {
.make-grid(-lg);
}
// Extra Large grid
//
// Columns, offsets, pushes, and pulls for the full hd device range.
@media (min-width: @screen-xl-min) {
.make-grid(-xl);
}

View File

@ -0,0 +1,100 @@
@import "../../style/mixins/index";
// mixins for grid system
// ------------------------
.make-row(@gutter: @grid-gutter-width) {
position: relative;
margin-left: (@gutter / -2);
margin-right: (@gutter / -2);
height: auto;
.clearfix;
}
.make-grid-columns() {
.col(@index) {
@item: ~".@{ant-prefix}-col-@{index}, .@{ant-prefix}-col-xs-@{index}, .@{ant-prefix}-col-sm-@{index}, .@{ant-prefix}-col-md-@{index}, .@{ant-prefix}-col-lg-@{index}";
.col((@index + 1), @item);
}
.col(@index, @list) when (@index =< @grid-columns) {
@item: ~".@{ant-prefix}-col-@{index}, .@{ant-prefix}-col-xs-@{index}, .@{ant-prefix}-col-sm-@{index}, .@{ant-prefix}-col-md-@{index}, .@{ant-prefix}-col-lg-@{index}";
.col((@index + 1), ~"@{list}, @{item}");
}
.col(@index, @list) when (@index > @grid-columns) {
@{list} {
position: relative;
// Prevent columns from collapsing when empty
min-height: 1px;
padding-left: (@grid-gutter-width / 2);
padding-right: (@grid-gutter-width / 2);
}
}
.col(1);
}
.float-grid-columns(@class) {
.col(@index) { // initial
@item: ~".@{ant-prefix}-col@{class}-@{index}";
.col((@index + 1), @item);
}
.col(@index, @list) when (@index =< @grid-columns) { // general
@item: ~".@{ant-prefix}-col@{class}-@{index}";
.col((@index + 1), ~"@{list}, @{item}");
}
.col(@index, @list) when (@index > @grid-columns) { // terminal
@{list} {
float: left;
flex: 0 0 auto;
}
}
.col(1); // kickstart it
}
// lesshint false
.loop-grid-columns(@index, @class) when (@index > 0) {
.@{ant-prefix}-col@{class}-@{index} {
display: block;
width: percentage((@index / @grid-columns));
}
.@{ant-prefix}-col@{class}-push-@{index} {
left: percentage((@index / @grid-columns));
}
.@{ant-prefix}-col@{class}-pull-@{index} {
right: percentage((@index / @grid-columns));
}
.@{ant-prefix}-col@{class}-offset-@{index} {
margin-left: percentage((@index / @grid-columns));
}
.@{ant-prefix}-col@{class}-order-@{index} {
order: @index;
}
.loop-grid-columns((@index - 1), @class);
}
.loop-grid-columns(@index, @class) when (@index = 0) {
.@{ant-prefix}-col@{class}-@{index} {
display: none;
}
.@{ant-prefix}-col-push-@{index} {
left: auto;
}
.@{ant-prefix}-col-pull-@{index} {
right: auto;
}
.@{ant-prefix}-col@{class}-push-@{index} {
left: auto;
}
.@{ant-prefix}-col@{class}-pull-@{index} {
right: auto;
}
.@{ant-prefix}-col@{class}-offset-@{index} {
margin-left: 0;
}
.@{ant-prefix}-col@{class}-order-@{index} {
order: 0;
}
}
.make-grid(@class: ~'') {
.float-grid-columns(@class);
.loop-grid-columns(@grid-columns, @class);
}

View File

@ -1,9 +1,12 @@
import './button/style'
import './checkbox/style'
import './icon/style'
import './grid/style'
export { default as Button } from './button'
export { default as Checkbox } from './checkbox'
export { default as Icon } from './icon'
export { default as Grid } from './grid'

98
examples/grid.vue Normal file
View File

@ -0,0 +1,98 @@
<template>
<div class="grid">
<div class="show-block">
<ant-row gutter="10">
<ant-col :style="style1" :span="6">
<div :style="style2">1</div>
</ant-col>
<ant-col :style="style1" :span="6">
<div :style="style2">2</div>
</ant-col>
<ant-col :style="style1" :span="6">
<div :style="style2">3</div>
</ant-col>
<ant-col :style="style1" :span="6">
<div :style="style2">4</div>
</ant-col>
</ant-row>
</div>
<div class="show-block">
<ant-row gutter="10">
<ant-col :style="style1" :span="6" :offset="2">
<div :style="style2">offset = 2</div>
</ant-col>
<ant-col :style="style1" :span="6" :offset="2">
<div :style="style2">offset = 2</div>
</ant-col>
</ant-row>
</div>
<div class="show-block">
<ant-row gutter="10" type="flex">
<ant-col class="height1 color1" :span="6">
<div class="">F</div>
</ant-col>
<ant-col class="height2 color2" :span="6">
<div class="">L</div>
</ant-col>
<ant-col class="height3 color1" :span="6">
<div class="">E</div>
</ant-col>
<ant-col class="height4 color2" :span="6">
<div class="">X</div>
</ant-col>
</ant-row>
</div>
</div>
</template>
<script>
import { Grid } from '../components'
const { Row, Col } = Grid
export default {
data () {
return {
style1: { height: 40 + 'px' },
style2: { background: '#00bfff', height: 40 + 'px' }
}
},
methods: {
handleClick (event) {
console.log(event)
this.type = this.type === 'primary' ? 'danger' : 'primary'
},
},
components: {
AntRow: Row,
AntCol: Col
},
}
</script>
<style lang="less">
.grid div {
text-align: center;
vertical-align: middle;
line-height: 40px;
}
.show-block {
margin: 20px 0;
}
.height1 {
height: 60px;
}
.height2 {
height: 40px;
}
.height3 {
height: 80px;
}
.height4 {
height: 50px;
}
.color1 {
background: #00bfff;
color: white;
}
.color2 {
background: #0e77ca;
color: white;
}
</style>

View File

@ -1,19 +1,22 @@
import Vue from 'vue'
import Checkbox from './checkbox.vue'
import Button from './button.vue'
import Grid from './grid.vue'
// import Dialog from './dialog.vue'
import './index.less'
new Vue({
el: '#app',
template: `
<div>
<Checkbox />
<AntButton />
<Grid />
<Checkbox />
<AntButton />
</div>
`,
components: {
AntButton: Button,
// AntDialog: Dialog,
Checkbox,
Grid,
},
})

View File

@ -32,6 +32,9 @@
"babel-loader": "^7.1.2",
"babel-plugin-istanbul": "^4.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
"babel-plugin-transform-es2015-parameters": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.6.0",
"chai": "^4.1.2",