diff --git a/packages/element-plus/index.ts b/packages/element-plus/index.ts index 2976341d0f..08179a551a 100644 --- a/packages/element-plus/index.ts +++ b/packages/element-plus/index.ts @@ -3,11 +3,18 @@ import ElButton from '@element-plus/button' import ElBadge from '@element-plus/badge' import ElCard from '@element-plus/card' import ElTag from '@element-plus/tag' +import ElLayout from '@element-plus/layout' import ElDivider from '@element-plus/divider' import ElTimeLine from '@element-plus/time-line' export { - ElButton, ElBadge, ElCard, ElDivider, ElTag, ElTimeLine, + ElLayout, + ElButton, + ElBadge, + ElCard, + ElDivider, + ElTag, + ElTimeLine, } export default function install(app: App): void { @@ -15,6 +22,7 @@ export default function install(app: App): void { ElBadge(app) ElCard(app) ElTag(app) + ElLayout(app) ElDivider(app) ElTimeLine(app) } diff --git a/packages/element-plus/package.json b/packages/element-plus/package.json index b7d5be193e..268a2646f8 100644 --- a/packages/element-plus/package.json +++ b/packages/element-plus/package.json @@ -16,6 +16,7 @@ "dependencies": { "@element-plus/badge": "^0.0.0", "@element-plus/button": "^0.0.0", + "@element-plus/layout": "^0.0.0", "@element-plus/card": "^0.0.0", "@element-plus/tag": "^0.0.0", "@element-plus/time-line": "^0.0.0", diff --git a/packages/layout/__tests__/layout.spec.ts b/packages/layout/__tests__/layout.spec.ts new file mode 100644 index 0000000000..ba1672bcb1 --- /dev/null +++ b/packages/layout/__tests__/layout.spec.ts @@ -0,0 +1,102 @@ +import { mount } from '@vue/test-utils' +import Col from '../src/col' +import Row from '../src/row' + +describe('Col', () => { + it('create', () => { + const wrapper = mount(Col) + expect(wrapper.classes()).toContain('el-col') + }) + + it('span', () => { + const wrapper = mount(Col, { + props: { span: 12 }, + }) + expect(wrapper.classes()).toContain('el-col-12') + }) + + it('pull', () => { + const wrapper = mount(Col, { + props: { span: 12, pull: 3 }, + }) + expect(wrapper.classes()).toContain('el-col-pull-3') + }) + + it('push', () => { + const wrapper = mount(Col, { + props: { span: 12, push: 3 }, + }) + expect(wrapper.classes()).toContain('el-col-push-3') + }) + + it('gutter', () => { + const TestComponent = { + template: ` + + `, + components: { + 'el-col': Col, + 'el-row':Row, + }, + } + const wrapper = mount(TestComponent) + const colElm = wrapper.findComponent({ ref: 'col' }).element as HTMLElement + expect(colElm.style.paddingLeft === '10px').toBe(true) + expect(colElm.style.paddingRight === '10px').toBe(true) + }) + it('responsive', () => { + const TestComponent = { + template: ` + + + `, + components: { + 'el-col': Col, + 'el-row':Row, + }, + } + const wrapper = mount(TestComponent) + const colElmClass = wrapper.findComponent({ ref: 'col' }).classes() + expect(colElmClass.includes('el-col-sm-4')).toBe(true) + expect(colElmClass.includes('el-col-sm-4')).toBe(true) + expect(colElmClass.includes('el-col-sm-offset-2')).toBe(true) + expect(colElmClass.includes('el-col-lg-6')).toBe(true) + expect(colElmClass.includes('el-col-lg-offset-3')).toBe(true) + expect(colElmClass.includes('el-col-md-8')).toBe(true) + }) +}) + +describe('Row', () => { + test('create', () => { + const wrapper = mount(Row) + expect(wrapper.classes()).toContain('el-row') + }) + + test('gutter', () => { + const wrapper = mount(Row, { + props: { gutter: 20 }, + }) + const rowElm = wrapper.element as HTMLElement + expect(rowElm.style.marginLeft).toEqual('-10px') + expect(rowElm.style.marginRight).toEqual('-10px') + }) + test('type', () => { + const wrapper = mount(Row, { + props: { type: 'flex' }, + }) + expect(wrapper.classes()).toContain('el-row--flex') + }) + test('justify', () => { + const wrapper = mount(Row, { + props: { justify: 'end' }, + }) + expect(wrapper.classes()).toContain('is-justify-end') + }) + test('align', () => { + const wrapper = mount(Row, { + props: { align: 'bottom' }, + }) + expect(wrapper.classes()).toContain('is-align-bottom') + }) +}) + diff --git a/packages/layout/doc/basic.vue b/packages/layout/doc/basic.vue new file mode 100644 index 0000000000..5a31a69cdc --- /dev/null +++ b/packages/layout/doc/basic.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/packages/layout/doc/index.stories.ts b/packages/layout/doc/index.stories.ts new file mode 100644 index 0000000000..a5e472687e --- /dev/null +++ b/packages/layout/doc/index.stories.ts @@ -0,0 +1,6 @@ +export { default as BasicUsage } from './basic.vue' + +export default { + title: 'Layout', +} + diff --git a/packages/layout/index.ts b/packages/layout/index.ts new file mode 100644 index 0000000000..570d70f3fe --- /dev/null +++ b/packages/layout/index.ts @@ -0,0 +1,7 @@ +import { App } from 'vue' +import Row from './src/row' +import Col from './src/col' +export default (app: App) => { + app.component(Row.name, Row) + app.component(Col.name, Col) +} diff --git a/packages/layout/package.json b/packages/layout/package.json new file mode 100644 index 0000000000..2f9e2928c3 --- /dev/null +++ b/packages/layout/package.json @@ -0,0 +1,12 @@ +{ + "name": "@element-plus/layout", + "version": "0.0.0", + "main": "dist/index.js", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.0-rc.1" + }, + "devDependencies": { + "@vue/test-utils": "^2.0.0-beta.0" + } +} diff --git a/packages/layout/src/col.ts b/packages/layout/src/col.ts new file mode 100644 index 0000000000..82ffb538c1 --- /dev/null +++ b/packages/layout/src/col.ts @@ -0,0 +1,67 @@ +import { defineComponent, computed, inject, h } from 'vue' + +const ElCol = defineComponent({ + name: 'ElCol', + props: { + span: { + type: Number, + default: 24, + }, + offset: Number, + pull: Number, + push: Number, + xs: [Number, Object], + sm: [Number, Object], + md: [Number, Object], + lg: [Number, Object], + xl: [Number, Object], + }, + setup(props, { slots }) { + const gutter = inject('ElRow', 0) + + const style = computed(() => { + if (gutter) { + return { + paddingLeft: gutter / 2 + 'px', + paddingRight: gutter / 2 + 'px', + } + } + return {} + }) + const classList = computed(() => { + const ret: string[] = [] + const pos: ['span', 'offset', 'pull', 'push'] = ['span', 'offset', 'pull', 'push'] + pos.forEach(prop => { + const size = props[prop] + if (typeof size === 'number' && size >= 0) { + ret.push(prop !== 'span' ? `el-col-${prop}-${props[prop]}` : `el-col-${props[prop]}`) + } + }) + const sizes: ['xs', 'sm', 'md', 'lg', 'xl'] = ['xs', 'sm', 'md', 'lg', 'xl'] + sizes.forEach(size => { + if (typeof props[size] === 'number') { + ret.push(`el-col-${size}-${props[size]}`) + } else if (typeof props[size] === 'object') { + const sizeProps = props[size] + Object.keys(sizeProps).forEach(prop => { + ret.push( + prop !== 'span' ? `el-col-${size}-${prop}-${sizeProps[prop]}` : `el-col-${size}-${sizeProps[prop]}`, + ) + }) + } + }) + return ret + }) + + return () =>h( + 'div', + { + class: ['el-col', classList.value], + style: style.value, + }, + slots.default?.(), + ) + }, +}) + +export default ElCol diff --git a/packages/layout/src/row.ts b/packages/layout/src/row.ts new file mode 100644 index 0000000000..8068b40056 --- /dev/null +++ b/packages/layout/src/row.ts @@ -0,0 +1,47 @@ +import { defineComponent, computed, h, provide } from 'vue' +export default defineComponent({ + name: 'ElRow', + props: { + tag: { + type: String, + default: 'div', + }, + gutter: Number, + type: String, + justify: { + type: String, + default: 'start', + }, + align: { + type: String, + default: 'top', + }, + }, + setup(props, { slots }) { + provide('ElRow', props.gutter) + + const style = computed(() => { + const ret = { marginLeft: '', marginRight: '' } + if (props.gutter) { + ret.marginLeft = `-${props.gutter / 2}px` + ret.marginRight = ret.marginLeft + } + return ret + }) + + return () => + h( + props.tag, + { + class: [ + 'el-row', + props.justify !== 'start' ? `is-justify-${props.justify}` : '', + props.align !== 'top' ? `is-align-${props.align}` : '', + props.type === 'flex' ? 'el-row--flex' : '', + ], + style: style.value, + }, + slots.default?.(), + ) + }, +}) diff --git a/src/router.ts b/src/router.ts deleted file mode 100644 index 73c64d52e0..0000000000 --- a/src/router.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router' -import Button from '@element-plus/button/doc/index.vue' -import Tag from '@element-plus/tag/doc/index.vue' - -const routes: Array = [ - { - path: '/button', - component: Button, - }, - { - path: '/tag', - component: Tag, - }, -] - -const router = createRouter({ - history: createWebHistory(process.env.BASE_URL), - routes, -}) - -export default router