Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(comp:loading-bar): add LoadingBar component (#971) #1023

Merged
merged 1 commit into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -15,9 +15,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 @@ -62,6 +63,7 @@ export interface GlobalConfig {
input: InputConfig
inputNumber: InputNumberConfig
list: ListConfig
loadingBar: LoadingBarConfig
image: ImageConfig
imageViewer: ImageViewerConfig
menu: MenuConfig
Expand Down Expand Up @@ -250,6 +252,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