diff --git a/src-next/loading/README.md b/src-next/loading/README.md new file mode 100644 index 000000000..0f040966f --- /dev/null +++ b/src-next/loading/README.md @@ -0,0 +1,60 @@ +# Loading + +### Install + +```js +import Vue from 'vue'; +import { Loading } from 'vant'; + +Vue.use(Loading); +``` + +## Usage + +### Type + +```html + +``` + +### Color + +```html + +``` + +### Size + +```html + +``` + +### Text + +```html +Loading... +``` + +### Vertical + +```html +Loading... +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +| --- | --- | --- | --- | +| color | Loading color | _string_ | `#c9c9c9` | +| type | Can be set to `spinner` | _string_ | `circular` | +| size | Icon size | _number \| string_ | `30px` | +| text-size | Text font size | _number \| string_ | `14px` | +| vertical | Whether to arrange icons and text content vertically | _boolean_ | `false` | + +### Slots + +| Name | Description | +| ------- | ------------ | +| default | Loading text | diff --git a/src-next/loading/README.zh-CN.md b/src-next/loading/README.zh-CN.md new file mode 100644 index 000000000..9531f5ddf --- /dev/null +++ b/src-next/loading/README.zh-CN.md @@ -0,0 +1,70 @@ +# Loading 加载 + +### 引入 + +```js +import Vue from 'vue'; +import { Loading } from 'vant'; + +Vue.use(Loading); +``` + +## 代码演示 + +### 加载类型 + +通过`type`属性可以设置加载图标的类型,默认为`circular`,可选值为`spinner` + +```html + +``` + +### 自定义颜色 + +通过`color`属性设置加载图标的颜色 + +```html + +``` + +### 自定义大小 + +通过`size`属性设置加载图标的大小,默认单位为`px` + +```html + +``` + +### 加载文案 + +可以使用默认插槽在图标的右侧插入加载文案 + +```html +加载中... +``` + +### 垂直排列 + +设置`vertical`属性后,图标和文案会垂直排列 + +```html +加载中... +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| --------- | ---------------------------- | ------------------ | ---------- | +| color | 颜色 | _string_ | `#c9c9c9` | +| type | 类型,可选值为 `spinner` | _string_ | `circular` | +| size | 加载图标大小,默认单位为`px` | _number \| string_ | `30px` | +| text-size | 文字大小,默认单位为`px` | _number \| string_ | `14px` | +| vertical | 是否垂直排列图标和文字内容 | _boolean_ | `false` | + +### Slots + +| 名称 | 说明 | +| ------- | -------- | +| default | 加载文案 | diff --git a/src-next/loading/demo/index.vue b/src-next/loading/demo/index.vue new file mode 100644 index 000000000..16cb624ab --- /dev/null +++ b/src-next/loading/demo/index.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/src-next/loading/index.js b/src-next/loading/index.js new file mode 100644 index 000000000..445cfb383 --- /dev/null +++ b/src-next/loading/index.js @@ -0,0 +1,64 @@ +// Utils +import { createNamespace, addUnit } from '../utils'; + +const [createComponent, bem] = createNamespace('loading'); + +const SpinIcon = []; +for (let i = 0; i < 12; i++) { + SpinIcon.push(); +} + +const CircularIcon = ( + + + +); + +export default createComponent({ + props: { + color: String, + size: [Number, String], + vertical: Boolean, + textSize: [Number, String], + type: { + type: String, + default: 'circular', + }, + }, + + methods: { + genLoadingText() { + if (this.$slots.default) { + const style = this.textSize && { + fontSize: addUnit(this.textSize), + }; + + return ( + + {this.$slots.default()} + + ); + } + }, + }, + + render() { + const { color, size, type, vertical } = this; + + const style = { color }; + if (size) { + const iconSize = addUnit(size); + style.width = iconSize; + style.height = iconSize; + } + + return ( +
+ + {type === 'spinner' ? SpinIcon : CircularIcon} + + {this.genLoadingText()} +
+ ); + }, +}); diff --git a/src-next/loading/index.less b/src-next/loading/index.less new file mode 100644 index 000000000..ff2ed370a --- /dev/null +++ b/src-next/loading/index.less @@ -0,0 +1,103 @@ +@import '../style/var'; + +.van-loading { + position: relative; + color: @loading-spinner-color; + font-size: 0; + vertical-align: middle; + + &__spinner { + position: relative; + display: inline-block; + width: @loading-spinner-size; + // compatible for 1.x, users may set width or height in root element + max-width: 100%; + height: @loading-spinner-size; + max-height: 100%; + vertical-align: middle; + animation: van-rotate @loading-spinner-animation-duration linear infinite; + + &--spinner { + animation-timing-function: steps(12); + + i { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + + &::before { + display: block; + width: 2px; + height: 25%; + margin: 0 auto; + background-color: currentColor; + border-radius: 40%; + content: ' '; + } + } + } + + &--circular { + animation-duration: 2s; + } + } + + &__circular { + display: block; + width: 100%; + height: 100%; + + circle { + animation: van-circular 1.5s ease-in-out infinite; + stroke: currentColor; + stroke-width: 3; + stroke-linecap: round; + } + } + + &__text { + display: inline-block; + margin-left: @padding-xs; + color: @loading-text-color; + font-size: @loading-text-font-size; + vertical-align: middle; + } + + &--vertical { + display: flex; + flex-direction: column; + align-items: center; + + .van-loading__text { + margin: @padding-xs 0 0; + } + } +} + +@keyframes van-circular { + 0% { + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + } + + 50% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -40; + } + + 100% { + stroke-dasharray: 90, 150; + stroke-dashoffset: -120; + } +} + +.generate-spinner(@n, @i: 1) when (@i =< @n) { + .van-loading__spinner--spinner i:nth-of-type(@{i}) { + transform: rotate(@i * 30deg); + opacity: 1 - (0.75 / 12) * (@i - 1); + } + .generate-spinner(@n, (@i + 1)); +} +.generate-spinner(12); diff --git a/src-next/loading/test/__snapshots__/demo.spec.js.snap b/src-next/loading/test/__snapshots__/demo.spec.js.snap new file mode 100644 index 000000000..424aa506c --- /dev/null +++ b/src-next/loading/test/__snapshots__/demo.spec.js.snap @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders demo correctly 1`] = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 加载中... +
+
+
+
+ 加载中... +
+
+
+`; diff --git a/src-next/loading/test/__snapshots__/index.spec.js.snap b/src-next/loading/test/__snapshots__/index.spec.js.snap new file mode 100644 index 000000000..925bda61e --- /dev/null +++ b/src-next/loading/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`size prop 1`] = `
`; + +exports[`text-size prop 1`] = `
Text
`; diff --git a/src-next/loading/test/demo.spec.js b/src-next/loading/test/demo.spec.js new file mode 100644 index 000000000..5c70922b5 --- /dev/null +++ b/src-next/loading/test/demo.spec.js @@ -0,0 +1,4 @@ +import Demo from '../demo'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo); diff --git a/src-next/loading/test/index.spec.js b/src-next/loading/test/index.spec.js new file mode 100644 index 000000000..5459775a1 --- /dev/null +++ b/src-next/loading/test/index.spec.js @@ -0,0 +1,25 @@ +import { mount } from '../../../test'; +import Loading from '..'; + +test('size prop', () => { + const wrapper = mount(Loading, { + propsData: { + size: 20, + }, + }); + + expect(wrapper).toMatchSnapshot(); +}); + +test('text-size prop', () => { + const wrapper = mount(Loading, { + propsData: { + textSize: 20, + }, + scopedSlots: { + default: () => 'Text', + }, + }); + + expect(wrapper).toMatchSnapshot(); +}); diff --git a/vant.config.js b/vant.config.js index 67ce5e06d..585ec7160 100644 --- a/vant.config.js +++ b/vant.config.js @@ -192,10 +192,10 @@ module.exports = { // path: 'dropdown-menu', // title: 'DropdownMenu 下拉菜单', // }, - // { - // path: 'loading', - // title: 'Loading 加载', - // }, + { + path: 'loading', + title: 'Loading 加载', + }, // { // path: 'notify', // title: 'Notify 消息通知', @@ -543,10 +543,10 @@ module.exports = { // path: 'dropdown-menu', // title: 'DropdownMenu', // }, - // { - // path: 'loading', - // title: 'Loading', - // }, + { + path: 'loading', + title: 'Loading', + }, // { // path: 'notify', // title: 'Notify',