From 176bc652eacd2a24e621e9fb6a67d7fca779231f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=9C=E5=90=AF=E7=BC=98?= <1743369777@qq.com> Date: Thu, 17 Mar 2022 12:21:06 +0800 Subject: [PATCH] refactor(components): [carousel] refactor (#6681) * refactor(components): [carousel] refactor * fix: build error --- internal/build/src/type-safe.json | 1 + .../{carousel.spec.ts => carousel.spec.tsx} | 203 ++++----- packages/components/carousel/index.ts | 7 +- .../components/carousel/src/carousel-item.ts | 15 + .../components/carousel/src/carousel-item.vue | 169 +++++++ packages/components/carousel/src/carousel.ts | 100 +++-- packages/components/carousel/src/carousel.vue | 324 ++++++++++++++ packages/components/carousel/src/item.vue | 186 -------- packages/components/carousel/src/main.vue | 416 ------------------ packages/tokens/carousel.ts | 35 ++ packages/tokens/index.ts | 1 + 11 files changed, 706 insertions(+), 751 deletions(-) rename packages/components/carousel/__tests__/{carousel.spec.ts => carousel.spec.tsx} (51%) create mode 100644 packages/components/carousel/src/carousel-item.ts create mode 100644 packages/components/carousel/src/carousel-item.vue create mode 100644 packages/components/carousel/src/carousel.vue delete mode 100644 packages/components/carousel/src/item.vue delete mode 100644 packages/components/carousel/src/main.vue create mode 100644 packages/tokens/carousel.ts diff --git a/internal/build/src/type-safe.json b/internal/build/src/type-safe.json index 88fdbd7ddd..f3a89b98ee 100644 --- a/internal/build/src/type-safe.json +++ b/internal/build/src/type-safe.json @@ -12,6 +12,7 @@ "packages/components/button/", "packages/components/button-group/", "packages/components/card/", + "packages/components/carousel/", "packages/components/check-tag/", "packages/components/col/", "packages/components/collapse/", diff --git a/packages/components/carousel/__tests__/carousel.spec.ts b/packages/components/carousel/__tests__/carousel.spec.tsx similarity index 51% rename from packages/components/carousel/__tests__/carousel.spec.ts rename to packages/components/carousel/__tests__/carousel.spec.tsx index e193e9e139..170f991720 100644 --- a/packages/components/carousel/__tests__/carousel.spec.ts +++ b/packages/components/carousel/__tests__/carousel.spec.tsx @@ -1,46 +1,41 @@ -import { nextTick } from 'vue' +import { nextTick, reactive } from 'vue' import { mount } from '@vue/test-utils' -import Carousel from '../src/main.vue' -import CarouselItem from '../src/item.vue' +import Carousel from '../src/carousel.vue' +import CarouselItem from '../src/carousel-item.vue' +import type { CarouselInstance } from '../src/carousel' const wait = (ms = 100) => new Promise((resolve) => setTimeout(() => resolve(0), ms)) -const _mount = (template: string, data?: () => void, methods?: any) => - mount({ - components: { - 'el-carousel': Carousel, - 'el-carousel-item': CarouselItem, - }, - template, - data, - methods, - }) +const generateCarouselItems = (count = 3) => { + const list = Array.from({ length: count }, (_, index) => index + 1) + return list.map((i) => ) +} describe('Carousel', () => { it('create', () => { - const wrapper = _mount( - ` -
- - - -
- ` - ) + const wrapper = mount({ + setup() { + return () => ( +
+ {generateCarouselItems()} +
+ ) + }, + }) - expect(wrapper.vm.$refs.carousel.direction).toBe('horizontal') + const carousel = wrapper.findComponent({ ref: 'carousel' }) + .vm as CarouselInstance + expect(carousel.direction).toBe('horizontal') expect(wrapper.findAll('.el-carousel__item').length).toEqual(3) }) it('auto play', async (done) => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount(() => ( +
+ {generateCarouselItems()} +
+ )) await nextTick() await wait(10) @@ -52,13 +47,13 @@ describe('Carousel', () => { }) it('initial index', async (done) => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount(() => ( +
+ + {generateCarouselItems()} + +
+ )) await nextTick() await wait(10) @@ -72,13 +67,11 @@ describe('Carousel', () => { }) it('reset timer', async (done) => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount(() => ( +
+ {generateCarouselItems()} +
+ )) await nextTick() const items = wrapper.vm.$el.querySelectorAll('.el-carousel__item') await wrapper.trigger('mouseenter') @@ -92,43 +85,45 @@ describe('Carousel', () => { }) it('change', async (done) => { - const wrapper = _mount( - ` -
- - - -
- `, - () => { - return { - val: -1, - oldVal: -1, + const state = reactive({ + val: -1, + oldVal: -1, + }) + + mount({ + setup() { + const handleChange = (val: number, oldVal: number) => { + state.val = val + state.oldVal = oldVal } + + return () => ( +
+ + {generateCarouselItems()} + +
+ ) }, - { - handleChange(val, oldVal) { - this.val = val - this.oldVal = oldVal - }, - } - ) + }) await nextTick() await wait(50) - expect(wrapper.vm.val).toBe(1) - expect(wrapper.vm.oldVal).toBe(0) + expect(state.val).toBe(1) + expect(state.oldVal).toBe(0) done() }) it('label', async (done) => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount(() => ( +
+ + {[1, 2, 3].map((i) => ( + + ))} + +
+ )) await nextTick() expect(wrapper.find('.el-carousel__button span').text()).toBe('1') done() @@ -136,13 +131,11 @@ describe('Carousel', () => { describe('manual control', () => { it('hover', async (done) => { - const wrapper = _mount(` + const wrapper = mount(() => (
- - - + {generateCarouselItems()}
- `) + )) await nextTick() await wait() @@ -159,13 +152,13 @@ describe('Carousel', () => { }) it('card', async (done) => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount(() => ( +
+ + {generateCarouselItems(7)} + +
+ )) await nextTick() await wait() const items = wrapper.vm.$el.querySelectorAll('.el-carousel__item') @@ -185,27 +178,37 @@ describe('Carousel', () => { }) it('vertical direction', () => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount({ + setup() { + return () => ( +
+ + {generateCarouselItems()} + +
+ ) + }, + }) const items = wrapper.vm.$el.querySelectorAll('.el-carousel__item') - - expect(wrapper.vm.$refs.carousel.direction).toBe('vertical') + const carousel = wrapper.findComponent({ ref: 'carousel' }) + .vm as CarouselInstance + expect(carousel.direction).toBe('vertical') expect(items[0].style.transform.includes('translateY')).toBeTruthy() }) it('pause auto play on hover', async (done) => { - const wrapper = _mount(` -
- - - -
- `) + const wrapper = mount(() => ( +
+ + {generateCarouselItems()} + +
+ )) await nextTick() await wrapper.find('.el-carousel').trigger('mouseenter') diff --git a/packages/components/carousel/index.ts b/packages/components/carousel/index.ts index 38f82e8acd..c377404f77 100644 --- a/packages/components/carousel/index.ts +++ b/packages/components/carousel/index.ts @@ -1,6 +1,6 @@ import { withInstall, withNoopInstall } from '@element-plus/utils' -import Carousel from './src/main.vue' -import CarouselItem from './src/item.vue' +import Carousel from './src/carousel.vue' +import CarouselItem from './src/carousel-item.vue' export const ElCarousel = withInstall(Carousel, { CarouselItem, @@ -9,3 +9,6 @@ export const ElCarousel = withInstall(Carousel, { export default ElCarousel export const ElCarouselItem = withNoopInstall(CarouselItem) + +export * from './src/carousel' +export * from './src/carousel-item' diff --git a/packages/components/carousel/src/carousel-item.ts b/packages/components/carousel/src/carousel-item.ts new file mode 100644 index 0000000000..00426004dd --- /dev/null +++ b/packages/components/carousel/src/carousel-item.ts @@ -0,0 +1,15 @@ +import { buildProps } from '@element-plus/utils' +import type { ExtractPropTypes } from 'vue' +import type CarouselItem from './carousel-item.vue' + +export const carouselItemProps = buildProps({ + name: { type: String, default: '' }, + label: { + type: [String, Number], + default: '', + }, +} as const) + +export type CarouselItemProps = ExtractPropTypes + +export type CarouselItemInstance = InstanceType diff --git a/packages/components/carousel/src/carousel-item.vue b/packages/components/carousel/src/carousel-item.vue new file mode 100644 index 0000000000..622cd06dda --- /dev/null +++ b/packages/components/carousel/src/carousel-item.vue @@ -0,0 +1,169 @@ + + + diff --git a/packages/components/carousel/src/carousel.ts b/packages/components/carousel/src/carousel.ts index c96cac3bf1..52ef09b692 100644 --- a/packages/components/carousel/src/carousel.ts +++ b/packages/components/carousel/src/carousel.ts @@ -1,51 +1,57 @@ -import type { Ref, ToRefs, UnwrapRef } from 'vue' +import { buildProps, isNumber } from '@element-plus/utils' +import type { ExtractPropTypes } from 'vue' +import type Carousel from './carousel.vue' -export interface ICarouselItemProps { - name: string - label: string | number - key: string +export const carouselProps = buildProps({ + initialIndex: { + type: Number, + default: 0, + }, + height: { type: String, default: '' }, + trigger: { + type: String, + default: 'hover', + }, + autoplay: { + type: Boolean, + default: true, + }, + interval: { + type: Number, + default: 3000, + }, + indicatorPosition: { type: String, default: '' }, + indicator: { + type: Boolean, + default: true, + }, + arrow: { + type: String, + default: 'hover', + }, + type: { type: String, default: '' }, + loop: { + type: Boolean, + default: true, + }, + direction: { + type: String, + default: 'horizontal', + validator(val: string) { + return ['horizontal', 'vertical'].includes(val) + }, + }, + pauseOnHover: { + type: Boolean, + default: true, + }, +} as const) + +export const carouselEmits = { + change: (current: number, prev: number) => [current, prev].every(isNumber), } -export interface ICarouselItemData { - hover: boolean - translate: number - scale: number - active: boolean - ready: boolean - inStage: boolean - animating: boolean -} +export type CarouselProps = ExtractPropTypes +export type CarouselEmits = typeof carouselEmits -export interface ICarouselProps { - initialIndex: number - height: string - trigger: string - autoplay: boolean - interval: number - indicatorPosition: string - indicator: boolean - arrow: string - type: string - loop: boolean - direction: string - pauseOnHover: boolean -} - -export type UnionCarouselItemData = ICarouselItemProps & - ToRefs - -export interface CarouselItem extends UnionCarouselItemData { - uid: number - translateItem: (index: number, activeIndex: number, oldIndex: number) => void -} - -export interface InjectCarouselScope { - root: Ref - direction: string - type: string - items: Ref> - loop: boolean - addItem: (item: CarouselItem) => void - removeItem: (uid: number) => void - setActiveItem: (index: number) => void -} +export type CarouselInstance = InstanceType diff --git a/packages/components/carousel/src/carousel.vue b/packages/components/carousel/src/carousel.vue new file mode 100644 index 0000000000..a51833d9d3 --- /dev/null +++ b/packages/components/carousel/src/carousel.vue @@ -0,0 +1,324 @@ + + + diff --git a/packages/components/carousel/src/item.vue b/packages/components/carousel/src/item.vue deleted file mode 100644 index e232d749c0..0000000000 --- a/packages/components/carousel/src/item.vue +++ /dev/null @@ -1,186 +0,0 @@ - - diff --git a/packages/components/carousel/src/main.vue b/packages/components/carousel/src/main.vue deleted file mode 100644 index ba74f9643b..0000000000 --- a/packages/components/carousel/src/main.vue +++ /dev/null @@ -1,416 +0,0 @@ - - - diff --git a/packages/tokens/carousel.ts b/packages/tokens/carousel.ts new file mode 100644 index 0000000000..c711c33bc4 --- /dev/null +++ b/packages/tokens/carousel.ts @@ -0,0 +1,35 @@ +import type { InjectionKey, Ref, ToRefs, UnwrapRef } from 'vue' + +import type { CarouselItemProps } from '@element-plus/components/carousel' + +export type CarouselItemContext = CarouselItemProps & + ToRefs<{ + hover: boolean + translate: number + scale: number + active: boolean + ready: boolean + inStage: boolean + animating: boolean + }> & { + uid: number | undefined + translateItem: ( + index: number, + activeIndex: number, + oldIndex: number + ) => void + } + +export type CarouselContext = { + root: Ref + direction: string + type: string + items: Ref> + loop: boolean + addItem: (item: CarouselItemContext) => void + removeItem: (uid: number | undefined) => void + setActiveItem: (index: number) => void +} + +export const carouselContextKey: InjectionKey = + Symbol('carouselContextKey') diff --git a/packages/tokens/index.ts b/packages/tokens/index.ts index 2d5209b5a8..2a11a2e90d 100644 --- a/packages/tokens/index.ts +++ b/packages/tokens/index.ts @@ -1,5 +1,6 @@ export * from './breadcrumb' export * from './button' +export * from './carousel' export * from './collapse' export * from './config-provider' export * from './dialog'