Skip to content

Commit

Permalink
feat(comp:spin): add IxSpinProvider (#1222)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzaijiang authored Oct 31, 2022
1 parent 7613c7d commit 42491a9
Show file tree
Hide file tree
Showing 15 changed files with 579 additions and 67 deletions.
3 changes: 2 additions & 1 deletion packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { IxSelect, IxSelectOption, IxSelectOptionGroup, IxSelectPanel } from '@i
import { IxSkeleton } from '@idux/components/skeleton'
import { IxSlider } from '@idux/components/slider'
import { IxSpace } from '@idux/components/space'
import { IxSpin } from '@idux/components/spin'
import { IxSpin, IxSpinProvider } from '@idux/components/spin'
import { IxStatistic } from '@idux/components/statistic'
import { IxStepper, IxStepperItem } from '@idux/components/stepper'
import { IxSwitch } from '@idux/components/switch'
Expand Down Expand Up @@ -146,6 +146,7 @@ const components = [
IxSlider,
IxSpace,
IxSpin,
IxSpinProvider,
IxStatistic,
IxStepper,
IxStepperItem,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Vitest Snapshot v1

exports[`SpinProvider > basic > render work 1`] = `"<div class=\\"ix-spin-provider\\">content</div>"`;
101 changes: 101 additions & 0 deletions packages/components/spin/__tests__/spinProvider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { MountingOptions, VueWrapper, flushPromises, mount } from '@vue/test-utils'

import { renderWork } from '@tests'

import SpinProvider from '../src/SpinProvider'
import { SpinProviderInstance, SpinProviderProps } from '../src/types'

describe('SpinProvider', () => {
const SpinProviderMount = (options?: MountingOptions<SpinProviderProps>) => {
return mount(SpinProvider, { ...options }) as VueWrapper<SpinProviderInstance>
}

const tip = 'This is a tip'

const newTip = 'This is a newTip'

describe('basic', () => {
renderWork(SpinProvider, { slots: { default: 'content' } })

test('update and destroy and destroyAll work', async () => {
const wrapper = SpinProviderMount()

document.body.innerHTML = '<div class="target">This is a content</div>'

wrapper.vm.open({ tip, target: '.target' })
await flushPromises()

expect(document.querySelectorAll('.ix-spin').length).toBe(1)

expect(document.querySelector('.target')?.classList.contains('ix-spin-target-container')).toBe(true)

expect(document.querySelector('.ix-spin-spinner-tip')!.textContent).toBe(tip)

wrapper.vm.update({
tip: newTip,
target: '.target',
})

await flushPromises()

expect(document.querySelector('.ix-spin-spinner-tip')!.textContent).toBe(newTip)

wrapper.vm.open({ tip })
await flushPromises()

expect(document.querySelectorAll('.ix-spin').length).toBe(2)

wrapper.vm.destroy()

await flushPromises()

expect(document.querySelectorAll('.ix-spin').length).toBe(1)

// // will not generate spins repeatedly
wrapper.vm.open({ tip, target: '.target' })

await flushPromises()

expect(document.querySelectorAll('.ix-spin').length).toBe(1)

wrapper.vm.destroyAll()

await flushPromises()

expect(document.querySelectorAll('.ix-spin').length).toBe(0)
})
})

describe('spinRef', () => {
test.skip('update and destroy work', async () => {
const wrapper = SpinProviderMount()
const spinProviderRef = wrapper.vm.open({ tip })
await flushPromises()

expect(document.body.classList.contains('ix-spin-target-container')).toBe(true)

expect(document.querySelectorAll('.ix-spin').length).toBe(1)

expect(document.querySelectorAll('.ix-spin')[0].style.zIndex).toBe('2000')

expect(document.querySelector('.ix-spin-spinner-tip')!.textContent).toBe(tip)

spinProviderRef.update({
tip: 'new text',
zIndex: 3000,
})

await flushPromises()

expect(document.querySelector('.ix-spin-spinner-tip')!.textContent).toBe('new text')

expect(document.querySelectorAll('.ix-spin')[0].style.zIndex).toBe('3000')

spinProviderRef.destroy()

await flushPromises()

expect(document.querySelectorAll('.ix-spin').length).toBe(0)
})
})
})
2 changes: 1 addition & 1 deletion packages/components/spin/demo/Basic.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<IxSpin :spinning="spinning">
<div class="content">content</div>
<IxButton>1212</IxButton>
</IxSpin>
<div class="operation-area">
<IxButton mode="primary" @click="changeSpinning()">切换状态</IxButton>
Expand Down
19 changes: 19 additions & 0 deletions packages/components/spin/demo/UseSpin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
order: 4
title:
zh: UseSpin
en: UseSpin
hidden: true
---

## zh

你可以通过`useSpin`来灵活的使用`spin`组件,前提是需要把子组件包裹在`IxSpinProvider`里面

``` html
<IxSpinProvider>
<App />
</IxSpinProvider>
```

## en
65 changes: 65 additions & 0 deletions packages/components/spin/demo/UseSpin.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<IxSpace vertical :size="20">
<div class="card">
<div class="content">content</div>
</div>
<IxSpace>
<IxButton @click="openSpin">Open</IxButton>
<IxButton @click="upldateSpin">Update</IxButton>
<IxButton @click="destroySpin">Destroy</IxButton>
<IxButton @click="fullScreenSpin">fullScreen</IxButton>
<IxButton @click="destroyAllSpin">DestroyAll</IxButton>
</IxSpace>
</IxSpace>
</template>

<script setup lang="ts">
import { type SpinRef, useSpin } from '@idux/components/spin'
const { open, destroy, destroyAll } = useSpin()
let spinRef: SpinRef
const openSpin = () => {
spinRef = open({
tip: '等待',
target: '.card',
})
}
const upldateSpin = () => {
spinRef?.update({
tip: '更新',
})
}
const destroySpin = () => {
spinRef?.destroy()
}
const fullScreenSpin = () => {
open({
tip: '2S后关闭',
})
setTimeout(() => {
destroy()
}, 2000)
}
const destroyAllSpin = () => {
destroyAll()
}
</script>
<style lang="less" scoped>
.card {
text-align: center;
padding: 50px;
background-color: #eee;
height: 300px;
overflow: auto;
.content {
height: 500px;
}
}
</style>
29 changes: 29 additions & 0 deletions packages/components/spin/docs/Api.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,32 @@
|名称 | 说明 | 参数类型 | 备注 |
| --- | --- | --- | --- |
|`default` | 需要遮罩的内容区域 | - | - |

### IxSpinProvider

#### IxSpinProviderMethods

| 名称 | 说明 | 参数类型 | 备注 |
| --- | --- | --- | --- |
| `open` | 打开 | `(options: SpinOptions) => SpinRef` | `target`不传,默认为`target``body` |
| `update` | 更新 | `(options: SpinOptions) => void` | `target`不传,默认为`target``body` |
| `destroy` | 销毁 | `(target?: TargetType \| TargetType[]) => void` | `target`不传,默认为`target``body` |
| `destroyAll` | 销毁全部 | `() => void` | - |

``` ts
export type SpinOptions = Partial<
Omit<SpinProps, 'spinning'> & {
tip: string
target: string | HTMLElement | (() => string | HTMLElement)
zIndex: number
}
>

export type SpinRefUpdateOptions = Omit<SpinOptions, 'target'>

export interface SpinRef {
update: (options: SpinRefUpdateOptions) => void
destroy: () => void
}

```
23 changes: 20 additions & 3 deletions packages/components/spin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,29 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { SpinComponent } from './src/types'
import type { SpinComponent, SpinProviderComponent } from './src/types'

import Spin from './src/Spin'
import SpinProvider from './src/SpinProvider'

const IxSpin = Spin as unknown as SpinComponent
const IxSpinProvider = SpinProvider as unknown as SpinProviderComponent

export { IxSpin }
export { IxSpin, IxSpinProvider }

export type { SpinInstance, SpinComponent, SpinPublicProps as SpinProps, SpinTipAlignType, SpinSize } from './src/types'
export { useSpin } from './src/useSpin'

export type {
SpinInstance,
SpinComponent,
SpinPublicProps as SpinProps,
SpinProviderInstance,
SpinProviderComponent,
SpinProviderPublicProps as SpinProviderProps,
SpinProviderRef,
SpinRef,
SpinOptions,
SpinRefUpdateOptions,
SpinTipAlignType,
SpinSize,
} from './src/types'
6 changes: 3 additions & 3 deletions packages/components/spin/src/Spin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default defineComponent({
const { size, strokeWidth, radius } = useSize(props, spinConfig)

const hasDefaultSlot = computed(() => hasSlot(slots))
const mregedIcon = computed(() => props.icon ?? spinConfig.icon)
const mergedIcon = computed(() => props.icon ?? spinConfig.icon)
const mergedTip = computed(() => props.tip ?? spinConfig.tip)

const { spinnerClassName, containerClassName } = useClasses(
Expand Down Expand Up @@ -73,11 +73,11 @@ export default defineComponent({
return <div class={iconCls}>{slots.icon()}</div>
}

if (mregedIcon.value) {
if (mergedIcon.value) {
const iconStyle = normalizeStyle(props.duration && { animationDuration: `${props.duration}s` })
return (
<div class={[iconCls, props.rotate && `${iconCls}--rotate`]} style={iconStyle}>
<IxIcon name={mregedIcon.value} />
<IxIcon name={mergedIcon.value} />
</div>
)
}
Expand Down
Loading

0 comments on commit 42491a9

Please sign in to comment.