Skip to content

Commit

Permalink
feat(comp:loading-bar): add LoadingBar component (#971) (#1023)
Browse files Browse the repository at this point in the history
  • Loading branch information
qingshan-dev committed Jul 25, 2022
1 parent 3e24905 commit f948786
Show file tree
Hide file tree
Showing 28 changed files with 581 additions and 54 deletions.
17 changes: 17 additions & 0 deletions packages/components/config/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,23 @@ export const defaultConfig: GlobalConfig = {
size: 'md',
borderless: true,
},
loadingBar: {
mask: false,
animation: {
loading: {
duration: 3000,
progress: 80,
},
finish: {
duration: 300,
progress: 100,
},
error: {
duration: 400,
progress: 100,
},
},
},
image: {
preview: true,
},
Expand Down
9 changes: 8 additions & 1 deletion packages/components/config/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import type { ButtonSize } from '@idux/components/button'
import type { CardSize } from '@idux/components/card'
import type { CarouselDotPlacement, CarouselDotTrigger } from '@idux/components/carousel'
import type { CascaderData } from '@idux/components/cascader'
import type { DatePickerType } from '@idux/components/date-picker/src/types'
import type { DatePickerType } from '@idux/components/date-picker'
import type { FormLabelAlign, FormLayout, FormSize } from '@idux/components/form'
import type { ListSize } from '@idux/components/list'
import type { LoadingBarAnimation } from '@idux/components/loading-bar'
import type { Locale } from '@idux/components/locales'
import type { MenuData, MenuTheme } from '@idux/components/menu'
import type { MessageType } from '@idux/components/message'
Expand Down Expand Up @@ -63,6 +64,7 @@ export interface GlobalConfig {
input: InputConfig
inputNumber: InputNumberConfig
list: ListConfig
loadingBar: LoadingBarConfig
image: ImageConfig
imageViewer: ImageViewerConfig
menu: MenuConfig
Expand Down Expand Up @@ -251,6 +253,11 @@ export interface ListConfig {
borderless: boolean
}

export interface LoadingBarConfig {
mask: boolean
animation: LoadingBarAnimation
}

export interface ImageConfig {
preview: boolean
}
Expand Down
1 change: 1 addition & 0 deletions packages/components/default.less
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@
@import './typography/style/themes/default.less';
@import './upload/style/themes/default.less';
@import './watermark/style/themes/default.less';
@import './loading-bar/style/themes/default.less';
3 changes: 3 additions & 0 deletions packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { IxInput } from '@idux/components/input'
import { IxInputNumber } from '@idux/components/input-number'
import { IxLayout, IxLayoutContent, IxLayoutFooter, IxLayoutHeader, IxLayoutSider } from '@idux/components/layout'
import { IxList, IxListItem } from '@idux/components/list'
import { IxLoadingBarProvider } from '@idux/components/loading-bar'
import { IxMenu, IxMenuDivider, IxMenuItem, IxMenuItemGroup, IxMenuSub } from '@idux/components/menu'
import { IxMessage, IxMessageProvider } from '@idux/components/message'
import { IxModal, IxModalProvider } from '@idux/components/modal'
Expand Down Expand Up @@ -117,6 +118,7 @@ const components = [
IxLayoutSider,
IxList,
IxListItem,
IxLoadingBarProvider,
IxMenu,
IxMenuDivider,
IxMenuItem,
Expand Down Expand Up @@ -216,6 +218,7 @@ export * from '@idux/components/input'
export * from '@idux/components/input-number'
export * from '@idux/components/layout'
export * from '@idux/components/list'
export * from '@idux/components/loading-bar'
export * from '@idux/components/locales'
export * from '@idux/components/menu'
export * from '@idux/components/message'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Vitest Snapshot v1

exports[`LoadingBarProvider > render work 1`] = `
"<!--teleport start-->
<!--teleport end-->&lt;button&gt;ok&lt;/button&gt;"
`;
61 changes: 61 additions & 0 deletions packages/components/loading-bar/__tests__/loadingBar.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable vue/one-component-per-file */
import { MountingOptions, VueWrapper, flushPromises, mount } from '@vue/test-utils'

import { renderWork } from '@tests'

import IxLoadingBarProvider from '../src/LoadingBarProvider'
import { LoadingBarProviderInstance, LoadingBarProviderProps } from '../src/types'

describe('LoadingBarProvider', () => {
const sleepMs = (ms = 1000) => new Promise<void>(r => setTimeout(() => r(), ms))
const LoadingBarMount = (options?: MountingOptions<Partial<LoadingBarProviderProps>>) =>
mount(IxLoadingBarProvider, { ...options }) as VueWrapper<LoadingBarProviderInstance>

renderWork<LoadingBarProviderProps>(IxLoadingBarProvider, {
props: {},
slots: { default: () => `<button>ok</button>` },
})

test('render', async () => {
LoadingBarMount({ props: {}, slots: { default: () => `<button>ok</button>` } })
await flushPromises()

const containerEl = document.querySelector('.ix-loading-bar-container') as HTMLElement
expect(containerEl).not.toBeNull()

const loadingBarEl = document.querySelector('.ix-loading-bar') as HTMLElement
expect(loadingBarEl).not.toBeNull()
expect(window.getComputedStyle(loadingBarEl).display).toBe('none')

const maskEl = document.querySelector('.ix-loading-bar-mask') as HTMLElement
expect(maskEl).not.toBeNull()
})

test('start', async () => {
const wrapper = LoadingBarMount()
await flushPromises()
const loadingBarEl = document.querySelector('.ix-loading-bar') as HTMLElement
expect(loadingBarEl).not.toBeNull()
wrapper.vm.start()

await sleepMs(300)
expect(window.parseInt(window.getComputedStyle(loadingBarEl).maxWidth)).toBeLessThanOrEqual(80)
expect(document.querySelector('.ix-loading-bar--loading')).not.toBeNull()
wrapper.vm.finish()

await sleepMs(500)
expect(window.parseInt(window.getComputedStyle(loadingBarEl).maxWidth)).toBeLessThanOrEqual(100)
})

test('error', async () => {
const wrapper = LoadingBarMount()
await flushPromises()
const loadingBarEl = document.querySelector('.ix-loading-bar') as HTMLElement
expect(loadingBarEl).not.toBeNull()
wrapper.vm.error()
await sleepMs(100)
expect(document.querySelector('.ix-loading-bar--error')).not.toBeNull()
await sleepMs()
expect(window.parseInt(window.getComputedStyle(loadingBarEl).maxWidth)).toBeLessThanOrEqual(100)
})
})
41 changes: 41 additions & 0 deletions packages/components/loading-bar/__tests__/useLoadingBar.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable vue/one-component-per-file */

import { mount } from '@vue/test-utils'
import { defineComponent } from 'vue'

import IxLoadingBarProvider from '../src/LoadingBarProvider'
import { LoadingBarProviderInstance } from '../src/types'
import { useLoadingBar } from '../src/useLoadingBar'

describe('LoadingBarProvider', () => {
test('no provider', async () => {
const Test = defineComponent({
setup() {
useLoadingBar()
},
})
expect(() => mount(Test)).toThrowError(/IxLoadingBarProvider/)
})

test('provider', async () => {
const Test = defineComponent({
setup(props, { expose }) {
expose(useLoadingBar())
},
render() {
return null
},
})
const wrapper = mount({
template: '<IxLoadingBarProvider><Test ref="test"></Test></IxLoadingBarProvider>',
components: {
IxLoadingBarProvider,
Test,
},
})
const instance = wrapper.vm.$refs['test'] as LoadingBarProviderInstance
expect(instance.start).not.toBeNull()
expect(instance.finish).not.toBeNull()
expect(instance.error).not.toBeNull()
})
})
14 changes: 14 additions & 0 deletions packages/components/loading-bar/demo/Basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 0
title:
zh: 基本使用
en: Basic usage
---

## zh

最简单的用法。

## en

The simplest usage.
17 changes: 17 additions & 0 deletions packages/components/loading-bar/demo/Basic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<IxSpace>
<IxButton @click="start()">开始</IxButton>
<IxButton @click="finish">结束</IxButton>
<IxButton @click="error">错误</IxButton>
<IxButton @click="autoExit">开始有遮罩,4s后自动结束</IxButton>
</IxSpace>
</template>

<script setup lang="ts">
import { useLoadingBar } from '@idux/components/loading-bar'
const { start, finish, error } = useLoadingBar()
function autoExit() {
start({ mask: true })
setTimeout(() => finish(), 4000)
}
</script>
3 changes: 3 additions & 0 deletions packages/components/loading-bar/docs/Design.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 组件定义

## 使用场景
40 changes: 40 additions & 0 deletions packages/components/loading-bar/docs/Index.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
category: components
type: 反馈
order: 0
title: LoadingBar
subtitle: 加载进度条
---

## API

使用 LoadingBar 只有一种方法,在 IxLoadingBarProvider 组件里面嵌套使用 `useLoadingBar`

### IxLoadingProviderBar

如果你想通过 `useLoadingBar` 来创建提示框,则你需要把组件包裹在 `IxLoadingBarProvider` 内部,因为这样才不会丢失应用的上下文信息。

#### LoadingBarProviderProps

| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| mask | `start()`后是否同时显示遮罩 | - | false || - |

#### LoadingBarProviderMethods

| 名称 | 说明 | 参数类型 | 备注 |
| --- | --- | --- | --- |
| `start` | 开始 | (LoadingBarOptions) => void | 加载并显示进度条到80%暂停 |
| `finish` | 结束 | - | 继续加载进度条到100%,然后隐藏 |
| `error` | 错误 | - | 加载并显示,进度条继续加载到100,然后隐藏 |

<!--- insert less variable begin --->
## 主题变量

| 名称 | default | seer | 备注 |
| --- | --- | --- | --- |
|`@loading-bar-height` | `2px` | - | - |
|`@loading-bar-loading-color` | `@color-primary` | - | - |
|`@loading-bar-error-color` | `@color-error`| - | - |

<!--- insert less variable end --->
25 changes: 25 additions & 0 deletions packages/components/loading-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { LoadingBarProviderComponent } from './src/types'

import LoadingBarProvider from './src/LoadingBarProvider'

const IxLoadingBarProvider = LoadingBarProvider as unknown as LoadingBarProviderComponent

export { IxLoadingBarProvider }

export { useLoadingBar } from './src/useLoadingBar'

export type {
LoadingBarOptions,
LoadingBarAnimation,
LoadingBarProviderInstance,
LoadingBarProviderPublicProps as LoadingBarProviderProps,
LoadingBarProviderComponent,
LoadingBarProviderRef,
} from './src/types'
Loading

0 comments on commit f948786

Please sign in to comment.