Refactor carousel (#5292)
* refactor: carousel * refactor: carousel * style: update vc-slick pathpull/5317/head
parent
5edc8cadca
commit
c7492a0b59
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`renders ./components/carousel/demo/autoplay.vue correctly 1`] = `
|
||||
<div class="ant-carousel">
|
||||
<div class="slick-slider slick-initialized">
|
||||
<div class="slick-slider slick-initialized" dir="ltr">
|
||||
<!---->
|
||||
<div class="slick-list">
|
||||
<div class="slick-track" style="opacity: 1; transform: translate3d(0px, 0px, 0px);">
|
||||
|
@ -84,7 +84,7 @@ exports[`renders ./components/carousel/demo/autoplay.vue correctly 1`] = `
|
|||
|
||||
exports[`renders ./components/carousel/demo/basic.vue correctly 1`] = `
|
||||
<div class="ant-carousel">
|
||||
<div class="slick-slider slick-initialized">
|
||||
<div class="slick-slider slick-initialized" dir="ltr">
|
||||
<!---->
|
||||
<div class="slick-list">
|
||||
<div class="slick-track" style="opacity: 1; transform: translate3d(0px, 0px, 0px);">
|
||||
|
@ -166,7 +166,7 @@ exports[`renders ./components/carousel/demo/basic.vue correctly 1`] = `
|
|||
|
||||
exports[`renders ./components/carousel/demo/customArrows.vue correctly 1`] = `
|
||||
<div class="ant-carousel">
|
||||
<div class="slick-slider slick-initialized">
|
||||
<div class="slick-slider slick-initialized" dir="ltr">
|
||||
<div class="custom-slick-arrow slick-arrow slick-prev" style="left: 10px; z-index: 1; display: block;"><span role="img" aria-label="left-circle" class="anticon anticon-left-circle"><svg focusable="false" class="" data-icon="left-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M603.3 327.5l-246 178a7.95 7.95 0 000 12.9l246 178c5.3 3.8 12.7 0 12.7-6.5V643c0-10.2-4.9-19.9-13.2-25.9L457.4 512l145.4-105.2c8.3-6 13.2-15.6 13.2-25.9V334c0-6.5-7.4-10.3-12.7-6.5z"></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span></div>
|
||||
<div class="slick-list">
|
||||
<div class="slick-track" style="opacity: 1; transform: translate3d(0px, 0px, 0px);">
|
||||
|
@ -248,7 +248,7 @@ exports[`renders ./components/carousel/demo/customArrows.vue correctly 1`] = `
|
|||
|
||||
exports[`renders ./components/carousel/demo/customPaging.vue correctly 1`] = `
|
||||
<div class="ant-carousel">
|
||||
<div class="slick-slider slick-initialized"><button type="button" data-role="none" class="slick-arrow slick-prev" style="display: block;"> Previous</button>
|
||||
<div class="slick-slider slick-initialized" dir="ltr"><button type="button" data-role="none" class="slick-arrow slick-prev" style="display: block;"> Previous</button>
|
||||
<div class="slick-list">
|
||||
<div class="slick-track" style="opacity: 1; transform: translate3d(0px, 0px, 0px);">
|
||||
<div class="slick-slide slick-cloned" tabindex="-1" data-index="-1" aria-hidden="true" style="width: 0px;">
|
||||
|
@ -310,7 +310,7 @@ exports[`renders ./components/carousel/demo/customPaging.vue correctly 1`] = `
|
|||
|
||||
exports[`renders ./components/carousel/demo/fade.vue correctly 1`] = `
|
||||
<div class="ant-carousel">
|
||||
<div class="slick-slider slick-initialized">
|
||||
<div class="slick-slider slick-initialized" dir="ltr">
|
||||
<!---->
|
||||
<div class="slick-list">
|
||||
<div class="slick-track" style="opacity: 1;">
|
||||
|
@ -358,7 +358,7 @@ exports[`renders ./components/carousel/demo/fade.vue correctly 1`] = `
|
|||
exports[`renders ./components/carousel/demo/position.vue correctly 1`] = `
|
||||
<div class="ant-radio-group ant-radio-group-outline ant-radio-group-default" style="margin-bottom: 8px;"><label class="ant-radio-button-wrapper ant-radio-button-wrapper-checked"><span class="ant-radio-button ant-radio-button-checked"><input type="radio" class="ant-radio-button-input" value="top"><span class="ant-radio-button-inner"></span></span><span>Top</span></label><label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="bottom"><span class="ant-radio-button-inner"></span></span><span>Bottom</span></label><label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="left"><span class="ant-radio-button-inner"></span></span><span>Left</span></label><label class="ant-radio-button-wrapper"><span class="ant-radio-button"><input type="radio" class="ant-radio-button-input" value="right"><span class="ant-radio-button-inner"></span></span><span>Right</span></label></div>
|
||||
<div class="ant-carousel">
|
||||
<div class="slick-slider slick-initialized">
|
||||
<div class="slick-slider slick-initialized" dir="ltr">
|
||||
<!---->
|
||||
<div class="slick-list">
|
||||
<div class="slick-track" style="opacity: 1; transform: translate3d(0px, 0px, 0px);">
|
||||
|
|
|
@ -21,9 +21,7 @@ describe('Carousel', () => {
|
|||
sync: false,
|
||||
};
|
||||
const wrapper = mount(Carousel, props);
|
||||
const { innerSlider, slick } = wrapper.vm;
|
||||
const innerSliderFromRefs = slick.innerSlider;
|
||||
expect(innerSlider).toBe(innerSliderFromRefs);
|
||||
const { innerSlider } = wrapper.componentVM;
|
||||
expect(typeof innerSlider.slickNext).toBe('function');
|
||||
});
|
||||
|
||||
|
@ -39,26 +37,25 @@ describe('Carousel', () => {
|
|||
sync: false,
|
||||
};
|
||||
const wrapper = mount(Carousel, props);
|
||||
const { prev, next, goTo } = wrapper.vm;
|
||||
const { prev, next, goTo, innerSlider } = wrapper.componentVM;
|
||||
expect(typeof prev).toBe('function');
|
||||
expect(typeof next).toBe('function');
|
||||
expect(typeof goTo).toBe('function');
|
||||
const slick = wrapper.vm.slick;
|
||||
|
||||
expect(slick.innerSlider.currentSlide).toBe(0);
|
||||
expect(innerSlider.currentSlide).toBe(0);
|
||||
wrapper.vm.goTo(2);
|
||||
await asyncExpect(() => {
|
||||
expect(slick.innerSlider.currentSlide).toBe(2);
|
||||
expect(innerSlider.currentSlide).toBe(2);
|
||||
}, 1000);
|
||||
prev();
|
||||
await asyncExpect(() => {
|
||||
expect(slick.innerSlider.currentSlide).toBe(1);
|
||||
expect(innerSlider.currentSlide).toBe(1);
|
||||
}, 1000);
|
||||
|
||||
next();
|
||||
|
||||
await asyncExpect(() => {
|
||||
expect(slick.innerSlider.currentSlide).toBe(2);
|
||||
expect(innerSlider.currentSlide).toBe(2);
|
||||
}, 1000);
|
||||
});
|
||||
// TODO
|
||||
|
@ -77,8 +74,8 @@ describe('Carousel', () => {
|
|||
// sync: false,
|
||||
// };
|
||||
// const wrapper = mount(Carousel, props);
|
||||
|
||||
// const spy = jest.spyOn(wrapper.vm.slick.innerSlider, 'handleAutoPlay');
|
||||
// await sleep(100);
|
||||
// const spy = jest.spyOn(wrapper.componentVM.innerSlider, 'handleAutoPlay');
|
||||
// window.resizeTo(1000);
|
||||
// expect(spy).not.toHaveBeenCalled();
|
||||
// await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
@ -100,12 +97,9 @@ describe('Carousel', () => {
|
|||
sync: false,
|
||||
};
|
||||
const wrapper = mount(Carousel, props);
|
||||
const { onWindowResized } = wrapper.vm;
|
||||
const spy = jest.spyOn(wrapper.vm.onWindowResized, 'cancel');
|
||||
const spy2 = jest.spyOn(window, 'removeEventListener');
|
||||
const spy = jest.spyOn(window, 'removeEventListener');
|
||||
wrapper.unmount();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(spy2).toHaveBeenCalledWith('resize', onWindowResized);
|
||||
});
|
||||
|
||||
describe('should works for dotPosition', () => {
|
||||
|
|
|
@ -71,6 +71,7 @@ export default defineComponent({
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
filter: grayscale(100%);
|
||||
display: block;
|
||||
}
|
||||
.ant-carousel :deep .slick-thumb li.slick-active img {
|
||||
filter: grayscale(0%);
|
||||
|
|
|
@ -17,14 +17,14 @@ A carousel component. Scales with its container.
|
|||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| afterChange | Callback function called after the current index changes | function(current) | - | |
|
||||
| autoplay | Whether to scroll automatically | boolean | `false` | |
|
||||
| beforeChange | Callback function called before the current index changes | function(from, to) | - | |
|
||||
| dots | Whether to show the dots at the bottom of the gallery | boolean | `true` | |
|
||||
| dotPosition | The position of the dots, which can be one of `top` `bottom` `left` `right` | string | bottom | 1.5.0 |
|
||||
| dotPosition | The position of the dots, which can be one of `top` `bottom` `left` `right` | string | `bottom` | 1.5.0 |
|
||||
| dotsClass | Class name of the dots | string | `slick-dots` | |
|
||||
| easing | Transition interpolation function name | string | `linear` | |
|
||||
| effect | Transition effect | `scrollx` \| `fade` | `scrollx` | |
|
||||
| afterChange | Callback function called after the current index changes | function(current) | - | |
|
||||
| beforeChange | Callback function called before the current index changes | function(from, to) | - | |
|
||||
|
||||
## Methods
|
||||
|
||||
|
@ -34,4 +34,4 @@ A carousel component. Scales with its container.
|
|||
| next() | Change current slide to next slide | |
|
||||
| prev() | Change current slide to previous slide | |
|
||||
|
||||
For more info on the parameters, refer to the [vc-slick props](https://github.com/vueComponent/ant-design-vue/blob/next/components/vc-slick/src/default-props.js#L3)
|
||||
For more info on the props, refer to the [carousel props](https://github.com/vueComponent/ant-design-vue/blob/next/components/carousel/index.tsx)
|
||||
|
|
|
@ -1,168 +1,148 @@
|
|||
import type { ExtractPropTypes } from 'vue';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
import { ref, computed, watchEffect, defineComponent } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
import hasProp, { getComponent } from '../_util/props-util';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
import classNames from '../_util/classNames';
|
||||
import SlickCarousel from '../vc-slick/src';
|
||||
import { tuple, withInstall } from '../_util/type';
|
||||
import SlickCarousel from '../vc-slick';
|
||||
import { withInstall } from '../_util/type';
|
||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||
|
||||
export type SwipeDirection = 'left' | 'down' | 'right' | 'up' | string;
|
||||
|
||||
export type LazyLoadTypes = 'ondemand' | 'progressive';
|
||||
|
||||
export type CarouselEffect = 'scrollx' | 'fade';
|
||||
export type DotPosition = 'top' | 'bottom' | 'left' | 'right';
|
||||
|
||||
export interface CarouselRef {
|
||||
goTo: (slide: number, dontAnimate?: boolean) => void;
|
||||
next: () => void;
|
||||
prev: () => void;
|
||||
autoplay: (palyType?: 'update' | 'leave' | 'blur') => void;
|
||||
innerSlider: any;
|
||||
}
|
||||
|
||||
// Carousel
|
||||
export const carouselProps = {
|
||||
effect: PropTypes.oneOf(tuple('scrollx', 'fade')),
|
||||
dots: PropTypes.looseBool.def(true),
|
||||
vertical: PropTypes.looseBool,
|
||||
autoplay: PropTypes.looseBool,
|
||||
easing: PropTypes.string,
|
||||
beforeChange: PropTypes.func,
|
||||
afterChange: PropTypes.func,
|
||||
export const carouselProps = () => ({
|
||||
effect: String as PropType<CarouselEffect>,
|
||||
dots: { type: Boolean, default: true },
|
||||
vertical: { type: Boolean, default: undefined },
|
||||
autoplay: { type: Boolean, default: undefined },
|
||||
easing: String,
|
||||
beforeChange: Function as PropType<(currentSlide: number, nextSlide: number) => void>,
|
||||
afterChange: Function as PropType<(currentSlide: number) => void>,
|
||||
// style: PropTypes.React.CSSProperties,
|
||||
prefixCls: PropTypes.string,
|
||||
accessibility: PropTypes.looseBool,
|
||||
prefixCls: String,
|
||||
accessibility: { type: Boolean, default: undefined },
|
||||
nextArrow: PropTypes.any,
|
||||
prevArrow: PropTypes.any,
|
||||
pauseOnHover: PropTypes.looseBool,
|
||||
// className: PropTypes.string,
|
||||
adaptiveHeight: PropTypes.looseBool,
|
||||
arrows: PropTypes.looseBool.def(false),
|
||||
autoplaySpeed: PropTypes.number,
|
||||
centerMode: PropTypes.looseBool,
|
||||
centerPadding: PropTypes.string,
|
||||
cssEase: PropTypes.string,
|
||||
dotsClass: PropTypes.string,
|
||||
draggable: PropTypes.looseBool.def(false),
|
||||
fade: PropTypes.looseBool,
|
||||
focusOnSelect: PropTypes.looseBool,
|
||||
infinite: PropTypes.looseBool,
|
||||
initialSlide: PropTypes.number,
|
||||
lazyLoad: PropTypes.looseBool,
|
||||
rtl: PropTypes.looseBool,
|
||||
slide: PropTypes.string,
|
||||
slidesToShow: PropTypes.number,
|
||||
slidesToScroll: PropTypes.number,
|
||||
speed: PropTypes.number,
|
||||
swipe: PropTypes.looseBool,
|
||||
swipeToSlide: PropTypes.looseBool,
|
||||
touchMove: PropTypes.looseBool,
|
||||
touchThreshold: PropTypes.number,
|
||||
variableWidth: PropTypes.looseBool,
|
||||
useCSS: PropTypes.looseBool,
|
||||
slickGoTo: PropTypes.number,
|
||||
responsive: PropTypes.array,
|
||||
dotPosition: PropTypes.oneOf(tuple('top', 'bottom', 'left', 'right')),
|
||||
verticalSwiping: PropTypes.looseBool.def(false),
|
||||
};
|
||||
export type CarouselProps = Partial<ExtractPropTypes<typeof carouselProps>>;
|
||||
pauseOnHover: { type: Boolean, default: undefined },
|
||||
// className: String,
|
||||
adaptiveHeight: { type: Boolean, default: undefined },
|
||||
arrows: { type: Boolean, default: false },
|
||||
autoplaySpeed: Number,
|
||||
centerMode: { type: Boolean, default: undefined },
|
||||
centerPadding: String,
|
||||
cssEase: String,
|
||||
dotsClass: String,
|
||||
draggable: { type: Boolean, default: false },
|
||||
fade: { type: Boolean, default: undefined },
|
||||
focusOnSelect: { type: Boolean, default: undefined },
|
||||
infinite: { type: Boolean, default: undefined },
|
||||
initialSlide: Number,
|
||||
lazyLoad: String as PropType<LazyLoadTypes>,
|
||||
rtl: { type: Boolean, default: undefined },
|
||||
slide: String,
|
||||
slidesToShow: Number,
|
||||
slidesToScroll: Number,
|
||||
speed: Number,
|
||||
swipe: { type: Boolean, default: undefined },
|
||||
swipeToSlide: { type: Boolean, default: undefined },
|
||||
swipeEvent: Function as PropType<(swipeDirection: SwipeDirection) => void>,
|
||||
touchMove: { type: Boolean, default: undefined },
|
||||
touchThreshold: Number,
|
||||
variableWidth: { type: Boolean, default: undefined },
|
||||
useCSS: { type: Boolean, default: undefined },
|
||||
slickGoTo: Number,
|
||||
responsive: Array,
|
||||
dotPosition: { type: String as PropType<DotPosition>, default: undefined },
|
||||
verticalSwiping: { type: Boolean, default: false },
|
||||
});
|
||||
export type CarouselProps = Partial<ExtractPropTypes<ReturnType<typeof carouselProps>>>;
|
||||
const Carousel = defineComponent({
|
||||
name: 'ACarousel',
|
||||
inheritAttrs: false,
|
||||
props: carouselProps,
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', defaultConfigProvider),
|
||||
slick: undefined,
|
||||
innerSlider: undefined,
|
||||
props: carouselProps(),
|
||||
setup(props, { slots, attrs, expose }) {
|
||||
const slickRef = ref();
|
||||
|
||||
const goTo = (slide: number, dontAnimate = false) => {
|
||||
slickRef.value?.slickGoTo(slide, dontAnimate);
|
||||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.onWindowResized = debounce(this.onWindowResized, 500, {
|
||||
leading: false,
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
if (hasProp(this, 'vertical')) {
|
||||
|
||||
expose({
|
||||
goTo,
|
||||
autoplay: palyType => {
|
||||
slickRef.value?.innerSlider?.handleAutoPlay(palyType);
|
||||
},
|
||||
prev: () => {
|
||||
slickRef.value?.slickPrev();
|
||||
},
|
||||
next: () => {
|
||||
slickRef.value?.slickNext();
|
||||
},
|
||||
innerSlider: computed(() => {
|
||||
return slickRef.value?.innerSlider;
|
||||
}),
|
||||
} as CarouselRef);
|
||||
watchEffect(() => {
|
||||
warning(
|
||||
!this.vertical,
|
||||
props.vertical === undefined,
|
||||
'Carousel',
|
||||
'`vertical` is deprecated, please use `dotPosition` instead.',
|
||||
);
|
||||
}
|
||||
const { autoplay } = this;
|
||||
if (autoplay) {
|
||||
window.addEventListener('resize', this.onWindowResized);
|
||||
}
|
||||
// https://github.com/ant-design/ant-design/issues/7191
|
||||
this.innerSlider = this.slick && this.slick.innerSlider;
|
||||
},
|
||||
beforeUnmount() {
|
||||
const { autoplay } = this;
|
||||
if (autoplay) {
|
||||
window.removeEventListener('resize', this.onWindowResized);
|
||||
(this.onWindowResized as any).cancel();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDotPosition() {
|
||||
if (this.dotPosition) {
|
||||
return this.dotPosition;
|
||||
}
|
||||
if (hasProp(this, 'vertical')) {
|
||||
return this.vertical ? 'right' : 'bottom';
|
||||
}
|
||||
});
|
||||
const { prefixCls, direction } = useConfigInject('carousel', props);
|
||||
const dotPosition = computed(() => {
|
||||
if (props.dotPosition) return props.dotPosition;
|
||||
if (props.vertical !== undefined) return props.vertical ? 'right' : 'bottom';
|
||||
return 'bottom';
|
||||
},
|
||||
saveSlick(node: HTMLElement) {
|
||||
this.slick = node;
|
||||
},
|
||||
onWindowResized() {
|
||||
// Fix https://github.com/ant-design/ant-design/issues/2550
|
||||
const { autoplay } = this;
|
||||
if (autoplay && this.slick && this.slick.innerSlider && this.slick.innerSlider.autoPlay) {
|
||||
this.slick.innerSlider.autoPlay();
|
||||
}
|
||||
},
|
||||
|
||||
next() {
|
||||
this.slick.slickNext();
|
||||
},
|
||||
|
||||
prev() {
|
||||
this.slick.slickPrev();
|
||||
},
|
||||
|
||||
goTo(slide: number, dontAnimate = false) {
|
||||
this.slick.slickGoTo(slide, dontAnimate);
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const props = { ...this.$props };
|
||||
const { $slots } = this;
|
||||
|
||||
if (props.effect === 'fade') {
|
||||
props.fade = true;
|
||||
}
|
||||
const { class: cls, style, ...restAttrs } = this.$attrs as any;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
let className = getPrefixCls('carousel', props.prefixCls);
|
||||
const dotsClass = 'slick-dots';
|
||||
const dotPosition = this.getDotPosition();
|
||||
props.vertical = dotPosition === 'left' || dotPosition === 'right';
|
||||
props.dotsClass = classNames(`${dotsClass}`, `${dotsClass}-${dotPosition || 'bottom'}`, {
|
||||
[`${props.dotsClass}`]: !!props.dotsClass,
|
||||
});
|
||||
className = classNames({
|
||||
[cls]: !!cls,
|
||||
[className]: !!className,
|
||||
[`${className}-vertical`]: props.vertical,
|
||||
const vertical = computed(() => dotPosition.value === 'left' || dotPosition.value === 'right');
|
||||
const dsClass = computed(() => {
|
||||
const dotsClass = 'slick-dots';
|
||||
return classNames({
|
||||
[dotsClass]: true,
|
||||
[`${dotsClass}-${dotPosition.value}`]: true,
|
||||
[`${props.dotsClass}`]: !!props.dotsClass,
|
||||
});
|
||||
});
|
||||
const SlickCarouselProps = {
|
||||
...props,
|
||||
...restAttrs,
|
||||
nextArrow: getComponent(this, 'nextArrow'),
|
||||
prevArrow: getComponent(this, 'prevArrow'),
|
||||
return () => {
|
||||
const { dots, arrows, draggable, effect } = props;
|
||||
const { class: cls, style, ...restAttrs } = attrs;
|
||||
const fade = effect === 'fade' ? true : props.fade;
|
||||
const className = classNames(prefixCls.value, {
|
||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||
[`${prefixCls.value}-vertical`]: vertical.value,
|
||||
[`${cls}`]: !!cls,
|
||||
});
|
||||
return (
|
||||
<div class={className} style={style}>
|
||||
<SlickCarousel
|
||||
ref={slickRef}
|
||||
{...props}
|
||||
{...restAttrs}
|
||||
dots={!!dots}
|
||||
dotsClass={dsClass.value}
|
||||
arrows={arrows}
|
||||
draggable={draggable}
|
||||
fade={fade}
|
||||
vertical={vertical.value}
|
||||
v-slots={slots}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<div class={className} style={style}>
|
||||
<SlickCarousel
|
||||
ref={this.saveSlick}
|
||||
{...SlickCarouselProps}
|
||||
v-slots={$slots}
|
||||
></SlickCarousel>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -18,14 +18,14 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/%24C9tmj978R/Carousel.svg
|
|||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| afterChange | 切换面板的回调 | function(current) | 无 | |
|
||||
| autoplay | 是否自动切换 | boolean | false | |
|
||||
| beforeChange | 切换面板的回调 | function(from, to) | 无 | |
|
||||
| dotPosition | 面板指示点位置,可选 `top` `bottom` `left` `right` | string | bottom | 1.5.0 |
|
||||
| dotPosition | 面板指示点位置,可选 `top` `bottom` `left` `right` | string | `bottom` | 1.5.0 |
|
||||
| dots | 是否显示面板指示点 | boolean | true | |
|
||||
| dotsClass | 面板指示点类名 | string | `slick-dots` | |
|
||||
| easing | 动画效果 | string | linear | |
|
||||
| effect | 动画效果函数,可取 scrollx, fade | string | scrollx | |
|
||||
| easing | 动画效果 | string | `linear` | |
|
||||
| effect | 动画效果函数 | `scrollx` \| `fade` | `scrollx` | |
|
||||
| afterChange | 切换面板的回调 | function(current) | - | |
|
||||
| beforeChange | 切换面板的回调 | function(from, to) | - | |
|
||||
|
||||
## 方法
|
||||
|
||||
|
@ -35,4 +35,4 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/%24C9tmj978R/Carousel.svg
|
|||
| next() | 切换到下一面板 | |
|
||||
| prev() | 切换到上一面板 | |
|
||||
|
||||
更多参数可参考:[vc-slick props](https://github.com/vueComponent/ant-design-vue/blob/next/components/vc-slick/src/default-props.js#L3)
|
||||
更多属性可参考源码:[carousel props](https://github.com/vueComponent/ant-design-vue/blob/next/components/carousel/index.tsx)
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
.@{ant-prefix}-carousel {
|
||||
@carousel-prefix-cls: ~'@{ant-prefix}-carousel';
|
||||
|
||||
.@{carousel-prefix-cls} {
|
||||
.reset-component();
|
||||
|
||||
.slick-slider {
|
||||
position: relative;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
-webkit-touch-callout: none;
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.slick-list {
|
||||
position: relative;
|
||||
display: block;
|
||||
|
@ -45,11 +47,20 @@
|
|||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
// fix Carousel content height not match parent node
|
||||
// when children is empty node
|
||||
// https://github.com/ant-design/ant-design/issues/25878
|
||||
> div > div {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slick-slider .slick-track,
|
||||
.slick-slider .slick-list {
|
||||
transform: translate3d(0, 0, 0);
|
||||
touch-action: pan-y;
|
||||
}
|
||||
|
||||
.slick-track {
|
||||
|
@ -72,17 +83,17 @@
|
|||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.slick-slide {
|
||||
display: none;
|
||||
float: left;
|
||||
height: 100%;
|
||||
min-height: 1px;
|
||||
[dir='rtl'] & {
|
||||
float: right;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.slick-loading img {
|
||||
display: none;
|
||||
}
|
||||
|
@ -103,8 +114,8 @@
|
|||
.slick-vertical .slick-slide {
|
||||
display: block;
|
||||
height: auto;
|
||||
border: @border-width-base @border-style-base transparent;
|
||||
}
|
||||
|
||||
.slick-arrow.slick-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
@ -126,15 +137,18 @@
|
|||
border: 0;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: transparent;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
|
||||
&::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.slick-disabled::before {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
@ -142,6 +156,7 @@
|
|||
|
||||
.slick-prev {
|
||||
left: -25px;
|
||||
|
||||
&::before {
|
||||
content: '←';
|
||||
}
|
||||
|
@ -149,6 +164,7 @@
|
|||
|
||||
.slick-next {
|
||||
right: -25px;
|
||||
|
||||
&::before {
|
||||
content: '→';
|
||||
}
|
||||
|
@ -157,29 +173,45 @@
|
|||
// Dots
|
||||
.slick-dots {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: @carousel-dot-height;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 15;
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
margin-right: 15%;
|
||||
margin-left: 15%;
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
|
||||
&-bottom {
|
||||
bottom: 12px;
|
||||
}
|
||||
|
||||
&-top {
|
||||
top: 12px;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
flex: 0 1 auto;
|
||||
box-sizing: content-box;
|
||||
width: @carousel-dot-width;
|
||||
height: @carousel-dot-height;
|
||||
margin: 0 2px;
|
||||
margin-right: 3px;
|
||||
margin-left: 3px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
text-indent: -999px;
|
||||
vertical-align: top;
|
||||
transition: all 0.5s;
|
||||
|
||||
button {
|
||||
display: block;
|
||||
width: @carousel-dot-width;
|
||||
width: 100%;
|
||||
height: @carousel-dot-height;
|
||||
padding: 0;
|
||||
color: transparent;
|
||||
|
@ -191,15 +223,21 @@
|
|||
cursor: pointer;
|
||||
opacity: 0.3;
|
||||
transition: all 0.5s;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
&.slick-active button {
|
||||
|
||||
&.slick-active {
|
||||
width: @carousel-dot-active-width;
|
||||
background: @component-background;
|
||||
opacity: 1;
|
||||
|
||||
& button {
|
||||
background: @component-background;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
|
@ -213,26 +251,44 @@
|
|||
.slick-dots {
|
||||
top: 50%;
|
||||
bottom: auto;
|
||||
flex-direction: column;
|
||||
width: @carousel-dot-height;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
transform: translateY(-50%);
|
||||
|
||||
&-left {
|
||||
right: auto;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
&-right {
|
||||
right: 12px;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0 2px;
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-width;
|
||||
margin: 4px 2px;
|
||||
vertical-align: baseline;
|
||||
|
||||
button {
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-width;
|
||||
}
|
||||
&.slick-active button {
|
||||
|
||||
&.slick-active {
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-active-width;
|
||||
|
||||
button {
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-active-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@import './rtl';
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@carousel-prefix-cls: ~'@{ant-prefix}-carousel';
|
||||
|
||||
.@{carousel-prefix-cls} {
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.slick-track {
|
||||
.@{carousel-prefix-cls}-rtl & {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.slick-prev {
|
||||
.@{carousel-prefix-cls}-rtl & {
|
||||
right: -25px;
|
||||
left: auto;
|
||||
|
||||
&::before {
|
||||
content: '→';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slick-next {
|
||||
.@{carousel-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: -25px;
|
||||
|
||||
&::before {
|
||||
content: '←';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dots
|
||||
.slick-dots {
|
||||
.@{carousel-prefix-cls}-rtl& {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-carousel-vertical {
|
||||
.slick-dots {
|
||||
.@{carousel-prefix-cls}-rtl& {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import classnames from '../../_util/classNames';
|
||||
import { cloneElement } from '../../_util/vnode';
|
||||
import classnames from '../_util/classNames';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import { canGoNext } from './utils/innerSliderUtils';
|
||||
|
||||
function noop() {}
|
|
@ -1,4 +1,4 @@
|
|||
import PropTypes from '../../_util/vue-types';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
|
||||
const defaultProps = {
|
||||
accessibility: PropTypes.looseBool.def(true),
|
|
@ -1,5 +1,6 @@
|
|||
import classnames from '../../_util/classNames';
|
||||
import { cloneElement } from '../../_util/vnode';
|
||||
import classnames from '../_util/classNames';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import { clamp } from './utils/innerSliderUtils';
|
||||
|
||||
const getDotCount = function (spec) {
|
||||
let dots;
|
||||
|
@ -39,24 +40,26 @@ const Dots = (_, { attrs }) => {
|
|||
//
|
||||
// Credit: http://stackoverflow.com/a/13735425/1849458
|
||||
const mouseEvents = { onMouseenter, onMouseover, onMouseleave };
|
||||
const dots = Array.apply(
|
||||
null,
|
||||
Array(dotCount + 1)
|
||||
.join('0')
|
||||
.split(''),
|
||||
).map((x, i) => {
|
||||
const leftBound = i * slidesToScroll;
|
||||
const rightBound = i * slidesToScroll + (slidesToScroll - 1);
|
||||
const className = classnames({
|
||||
'slick-active': currentSlide >= leftBound && currentSlide <= rightBound,
|
||||
let dots = [];
|
||||
for (let i = 0; i < dotCount; i++) {
|
||||
let _rightBound = (i + 1) * slidesToScroll - 1;
|
||||
let rightBound = infinite ? _rightBound : clamp(_rightBound, 0, slideCount - 1);
|
||||
let _leftBound = rightBound - (slidesToScroll - 1);
|
||||
let leftBound = infinite ? _leftBound : clamp(_leftBound, 0, slideCount - 1);
|
||||
|
||||
let className = classnames({
|
||||
'slick-active': infinite
|
||||
? currentSlide >= leftBound && currentSlide <= rightBound
|
||||
: currentSlide === leftBound,
|
||||
});
|
||||
|
||||
const dotOptions = {
|
||||
let dotOptions = {
|
||||
message: 'dots',
|
||||
index: i,
|
||||
slidesToScroll,
|
||||
currentSlide,
|
||||
};
|
||||
|
||||
function onClick(e) {
|
||||
// In Autoplay the focus stays on clicked button even after transition
|
||||
// to next slide. That only goes away by click somewhere outside
|
||||
|
@ -65,14 +68,12 @@ const Dots = (_, { attrs }) => {
|
|||
}
|
||||
clickHandler(dotOptions);
|
||||
}
|
||||
return (
|
||||
dots = dots.concat(
|
||||
<li key={i} class={className}>
|
||||
{cloneElement(customPaging({ i }), {
|
||||
onClick,
|
||||
})}
|
||||
</li>
|
||||
{cloneElement(customPaging({ i }), { onClick })}
|
||||
</li>,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return cloneElement(appendDots({ dots }), {
|
||||
class: dotsClass,
|
|
@ -1,4 +1,4 @@
|
|||
// base react-slick 0.23.2
|
||||
// base react-slick 0.28.2
|
||||
import Slider from './slider';
|
||||
|
||||
export default Slider;
|
|
@ -21,6 +21,7 @@ const initialState = {
|
|||
touchObject: { startX: 0, startY: 0, curX: 0, curY: 0 },
|
||||
trackStyle: {},
|
||||
trackWidth: 0,
|
||||
targetSlide: 0,
|
||||
};
|
||||
|
||||
export default initialState;
|
|
@ -1,7 +1,7 @@
|
|||
import debounce from 'lodash-es/debounce';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
import classnames from '../../_util/classNames';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import classnames from '../_util/classNames';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import defaultProps from './default-props';
|
||||
import initialState from './initial-state';
|
||||
import {
|
||||
|
@ -24,7 +24,7 @@ import {
|
|||
import Track from './track';
|
||||
import Dots from './dots';
|
||||
import { PrevArrow, NextArrow } from './arrows';
|
||||
import supportsPassive from '../../_util/supportsPassive';
|
||||
import supportsPassive from '../_util/supportsPassive';
|
||||
|
||||
function noop() {}
|
||||
|
||||
|
@ -42,10 +42,12 @@ export default {
|
|||
this.callbackTimers = [];
|
||||
this.clickable = true;
|
||||
this.debouncedResize = null;
|
||||
const ssrState = this.ssrInit();
|
||||
return {
|
||||
...initialState,
|
||||
currentSlide: this.initialSlide,
|
||||
slideCount: this.children.length,
|
||||
...ssrState,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
@ -83,7 +85,9 @@ export default {
|
|||
currentSlide: this.currentSlide,
|
||||
});
|
||||
}
|
||||
if (nextProps.autoplay) {
|
||||
if (!this.preProps.autoplay && nextProps.autoplay) {
|
||||
this.handleAutoPlay('playing');
|
||||
} else if (nextProps.autoplay) {
|
||||
this.handleAutoPlay('update');
|
||||
} else {
|
||||
this.pause('paused');
|
||||
|
@ -92,8 +96,7 @@ export default {
|
|||
this.preProps = { ...nextProps };
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
this.ssrInit();
|
||||
mounted() {
|
||||
this.__emit('init');
|
||||
if (this.lazyLoad) {
|
||||
const slidesToLoad = getOnDemandLazySlides({
|
||||
|
@ -107,8 +110,6 @@ export default {
|
|||
this.__emit('lazyLoad', slidesToLoad);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
const spec = {
|
||||
listRef: this.list,
|
||||
|
@ -118,7 +119,7 @@ export default {
|
|||
};
|
||||
this.updateState(spec, true, () => {
|
||||
this.adaptHeight();
|
||||
this.autoplay && this.handleAutoPlay('update');
|
||||
this.autoplay && this.handleAutoPlay('playing');
|
||||
});
|
||||
if (this.lazyLoad === 'progressive') {
|
||||
this.lazyLoadTimer = setInterval(this.progressiveLazyLoad, 1000);
|
||||
|
@ -132,14 +133,11 @@ export default {
|
|||
}
|
||||
});
|
||||
this.ro.observe(this.list);
|
||||
Array.prototype.forEach.call(document.querySelectorAll('.slick-slide'), slide => {
|
||||
slide.onfocus = this.$props.pauseOnFocus ? this.onSlideFocus : null;
|
||||
slide.onblur = this.$props.pauseOnFocus ? this.onSlideBlur : null;
|
||||
});
|
||||
// To support server-side rendering
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
document.querySelectorAll &&
|
||||
Array.prototype.forEach.call(document.querySelectorAll('.slick-slide'), slide => {
|
||||
slide.onfocus = this.$props.pauseOnFocus ? this.onSlideFocus : null;
|
||||
slide.onblur = this.$props.pauseOnFocus ? this.onSlideBlur : null;
|
||||
});
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('resize', this.onWindowResized);
|
||||
} else {
|
||||
|
@ -166,6 +164,7 @@ export default {
|
|||
if (this.autoplayTimer) {
|
||||
clearInterval(this.autoplayTimer);
|
||||
}
|
||||
this.ro?.disconnect();
|
||||
},
|
||||
updated() {
|
||||
this.checkImagesLoad();
|
||||
|
@ -206,7 +205,8 @@ export default {
|
|||
this.debouncedResize();
|
||||
},
|
||||
resizeWindow(setTrackStyle = true) {
|
||||
if (!this.track) return;
|
||||
const isTrackMounted = Boolean(this.track);
|
||||
if (!isTrackMounted) return;
|
||||
const spec = {
|
||||
listRef: this.list,
|
||||
trackRef: this.track,
|
||||
|
@ -278,10 +278,9 @@ export default {
|
|||
const currentWidth = `${childrenWidths[this.currentSlide]}px`;
|
||||
trackStyle.left = `calc(${trackStyle.left} + (100% - ${currentWidth}) / 2 ) `;
|
||||
}
|
||||
this.setState({
|
||||
return {
|
||||
trackStyle,
|
||||
});
|
||||
return;
|
||||
};
|
||||
}
|
||||
const childrenCount = children.length;
|
||||
const spec = { ...this.$props, ...this.$data, slideCount: childrenCount };
|
||||
|
@ -296,13 +295,17 @@ export default {
|
|||
width: trackWidth + '%',
|
||||
left: trackLeft + '%',
|
||||
};
|
||||
this.setState({
|
||||
return {
|
||||
slideWidth: slideWidth + '%',
|
||||
trackStyle,
|
||||
});
|
||||
};
|
||||
},
|
||||
checkImagesLoad() {
|
||||
const images = document.querySelectorAll('.slick-slide img');
|
||||
let images =
|
||||
(this.list &&
|
||||
this.list.querySelectorAll &&
|
||||
this.list.querySelectorAll('.slick-slide img')) ||
|
||||
[];
|
||||
const imagesCount = images.length;
|
||||
let loadedCount = 0;
|
||||
Array.prototype.forEach.call(images, image => {
|
||||
|
@ -376,10 +379,16 @@ export default {
|
|||
if (this.$attrs.onLazyLoad && slidesToLoad.length > 0) {
|
||||
this.__emit('lazyLoad', slidesToLoad);
|
||||
}
|
||||
if (!this.$props.waitForAnimate && this.animationEndCallback) {
|
||||
clearTimeout(this.animationEndCallback);
|
||||
afterChange && afterChange(currentSlide);
|
||||
delete this.animationEndCallback;
|
||||
}
|
||||
this.setState(state, () => {
|
||||
asNavFor &&
|
||||
asNavFor.innerSlider.currentSlide !== currentSlide &&
|
||||
if (asNavFor && this.asNavForIndex !== index) {
|
||||
this.asNavForIndex = index;
|
||||
asNavFor.innerSlider.slideHandler(index);
|
||||
}
|
||||
if (!nextState) return;
|
||||
this.animationEndCallback = setTimeout(() => {
|
||||
const { animating, ...firstBatch } = nextState;
|
||||
|
@ -400,6 +409,11 @@ export default {
|
|||
} else {
|
||||
this.slideHandler(targetSlide);
|
||||
}
|
||||
this.$props.autoplay && this.handleAutoPlay('update');
|
||||
if (this.$props.focusOnSelect) {
|
||||
const nodes = this.list.querySelectorAll('.slick-current');
|
||||
nodes[0] && nodes[0].focus();
|
||||
}
|
||||
},
|
||||
clickHandler(e) {
|
||||
if (this.clickable === false) {
|
||||
|
@ -465,6 +479,10 @@ export default {
|
|||
this.enableBodyScroll();
|
||||
}
|
||||
},
|
||||
touchEnd(e) {
|
||||
this.swipeEnd(e);
|
||||
this.clickable = true;
|
||||
},
|
||||
slickPrev() {
|
||||
// this and fellow methods are wrapped in setTimeout
|
||||
// to make sure initialize setState has happened before
|
||||
|
@ -599,11 +617,13 @@ export default {
|
|||
'variableWidth',
|
||||
'unslick',
|
||||
'centerPadding',
|
||||
'targetSlide',
|
||||
'useCSS',
|
||||
]);
|
||||
const { pauseOnHover } = this.$props;
|
||||
trackProps = {
|
||||
...trackProps,
|
||||
focusOnSelect: this.focusOnSelect ? this.selectHandler : null,
|
||||
focusOnSelect: this.focusOnSelect && this.clickable ? this.selectHandler : null,
|
||||
ref: this.trackRefHandler,
|
||||
onMouseleave: pauseOnHover ? this.onTrackLeave : noop,
|
||||
onMouseover: pauseOnHover ? this.onTrackOver : noop,
|
||||
|
@ -701,14 +721,15 @@ export default {
|
|||
: noop,
|
||||
[supportsPassive ? 'onTouchmovePassive' : 'onTouchmove']:
|
||||
this.dragging && touchMove ? this.swipeMove : noop,
|
||||
onTouchend: touchMove ? this.swipeEnd : noop,
|
||||
onTouchend: touchMove ? this.touchEnd : noop,
|
||||
onTouchcancel: this.dragging && touchMove ? this.swipeEnd : noop,
|
||||
onKeydown: this.accessibility ? this.keyHandler : noop,
|
||||
};
|
||||
|
||||
let innerSliderProps = {
|
||||
class: className,
|
||||
// dir: 'ltr',
|
||||
dir: 'ltr',
|
||||
style: this.$attrs.style,
|
||||
};
|
||||
|
||||
if (this.unslick) {
|
|
@ -1,10 +1,10 @@
|
|||
import json2mq from '../../_util/json2mq';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import { cloneElement } from '../../_util/vnode';
|
||||
import json2mq from '../_util/json2mq';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import InnerSlider from './inner-slider';
|
||||
import defaultProps from './default-props';
|
||||
import { canUseDOM } from './utils/innerSliderUtils';
|
||||
import { getSlot } from '../../_util/props-util';
|
||||
import { getSlot } from '../_util/props-util';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -21,7 +21,7 @@ export default defineComponent({
|
|||
};
|
||||
},
|
||||
// handles responsive breakpoints
|
||||
beforeMount() {
|
||||
mounted() {
|
||||
if (this.responsive) {
|
||||
const breakpoints = this.responsive.map(breakpt => breakpt.breakpoint);
|
||||
// sort them in increasing order of their numerical value
|
||||
|
@ -77,19 +77,19 @@ export default defineComponent({
|
|||
this._responsiveMediaHandlers.push({ mql, query, listener });
|
||||
},
|
||||
slickPrev() {
|
||||
this.innerSlider.slickPrev();
|
||||
this.innerSlider?.slickPrev();
|
||||
},
|
||||
slickNext() {
|
||||
this.innerSlider.slickNext();
|
||||
this.innerSlider?.slickNext();
|
||||
},
|
||||
slickGoTo(slide, dontAnimate = false) {
|
||||
this.innerSlider.slickGoTo(slide, dontAnimate);
|
||||
this.innerSlider?.slickGoTo(slide, dontAnimate);
|
||||
},
|
||||
slickPause() {
|
||||
this.innerSlider.pause('paused');
|
||||
this.innerSlider?.pause('paused');
|
||||
},
|
||||
slickPlay() {
|
||||
this.innerSlider.handleAutoPlay('play');
|
||||
this.innerSlider?.handleAutoPlay('play');
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -185,7 +185,7 @@ export default defineComponent({
|
|||
|
||||
if (settings === 'unslick') {
|
||||
const className = 'regular slider ' + (this.className || '');
|
||||
return <div class={className}>{newChildren}</div>;
|
||||
return <div class={className}>{children}</div>;
|
||||
} else if (newChildren.length <= settings.slidesToShow) {
|
||||
settings.unslick = true;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { createVNode } from 'vue';
|
||||
import classnames from '../../_util/classNames';
|
||||
import { cloneElement } from '../../_util/vnode';
|
||||
import { flattenChildren } from '../../_util/props-util';
|
||||
import classnames from '../_util/classNames';
|
||||
import { cloneElement } from '../_util/vnode';
|
||||
import { flattenChildren } from '../_util/props-util';
|
||||
import { lazyStartIndex, lazyEndIndex, getPreClones } from './utils/innerSliderUtils';
|
||||
|
||||
// given specifications/props for a slide, fetch all the classes that need to be applied to the slide
|
||||
|
@ -24,7 +24,15 @@ const getSlideClasses = spec => {
|
|||
} else {
|
||||
slickActive = spec.currentSlide <= index && index < spec.currentSlide + spec.slidesToShow;
|
||||
}
|
||||
const slickCurrent = index === spec.currentSlide;
|
||||
let focusedSlide;
|
||||
if (spec.targetSlide < 0) {
|
||||
focusedSlide = spec.targetSlide + spec.slideCount;
|
||||
} else if (spec.targetSlide >= spec.slideCount) {
|
||||
focusedSlide = spec.targetSlide - spec.slideCount;
|
||||
} else {
|
||||
focusedSlide = spec.targetSlide;
|
||||
}
|
||||
let slickCurrent = index === focusedSlide;
|
||||
return {
|
||||
'slick-slide': true,
|
||||
'slick-active': slickActive,
|
||||
|
@ -49,32 +57,24 @@ const getSlideStyle = function (spec) {
|
|||
style.left = -spec.index * parseInt(spec.slideWidth) + 'px';
|
||||
}
|
||||
style.opacity = spec.currentSlide === spec.index ? 1 : 0;
|
||||
style.transition =
|
||||
'opacity ' +
|
||||
spec.speed +
|
||||
'ms ' +
|
||||
spec.cssEase +
|
||||
', ' +
|
||||
'visibility ' +
|
||||
spec.speed +
|
||||
'ms ' +
|
||||
spec.cssEase;
|
||||
style.WebkitTransition =
|
||||
'opacity ' +
|
||||
spec.speed +
|
||||
'ms ' +
|
||||
spec.cssEase +
|
||||
', ' +
|
||||
'visibility ' +
|
||||
spec.speed +
|
||||
'ms ' +
|
||||
spec.cssEase;
|
||||
if (spec.useCSS) {
|
||||
style.transition =
|
||||
'opacity ' +
|
||||
spec.speed +
|
||||
'ms ' +
|
||||
spec.cssEase +
|
||||
', ' +
|
||||
'visibility ' +
|
||||
spec.speed +
|
||||
'ms ' +
|
||||
spec.cssEase;
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
};
|
||||
|
||||
const getKey = (child, fallbackKey) => child.key || (child.key === 0 && '0') || fallbackKey;
|
||||
const getKey = (child, fallbackKey) => child.key + '-' + fallbackKey;
|
||||
|
||||
const renderSlides = function (spec, children) {
|
||||
let key;
|
|
@ -1,4 +1,15 @@
|
|||
import supportsPassive from '../../../_util/supportsPassive';
|
||||
// import supportsPassive from '../../../_util/supportsPassive';
|
||||
|
||||
export function clamp(number, lowerBound, upperBound) {
|
||||
return Math.max(lowerBound, Math.min(number, upperBound));
|
||||
}
|
||||
|
||||
export const safePreventDefault = event => {
|
||||
const passiveEvents = ['touchstart', 'touchmove', 'wheel'];
|
||||
if (!passiveEvents.includes(event.type)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
export const getOnDemandLazySlides = spec => {
|
||||
const onDemandSlides = [];
|
||||
|
@ -91,8 +102,10 @@ export const extractObject = (spec, keys) => {
|
|||
export const initializedState = spec => {
|
||||
// spec also contains listRef, trackRef
|
||||
const slideCount = spec.children.length;
|
||||
const listWidth = Math.ceil(getWidth(spec.listRef));
|
||||
const trackWidth = Math.ceil(getWidth(spec.trackRef));
|
||||
const listNode = spec.listRef;
|
||||
const listWidth = Math.ceil(getWidth(listNode));
|
||||
const trackNode = spec.trackRef;
|
||||
const trackWidth = Math.ceil(getWidth(trackNode));
|
||||
let slideWidth;
|
||||
if (!spec.vertical) {
|
||||
let centerPaddingAdj = spec.centerMode && parseInt(spec.centerPadding) * 2;
|
||||
|
@ -103,15 +116,15 @@ export const initializedState = spec => {
|
|||
} else {
|
||||
slideWidth = listWidth;
|
||||
}
|
||||
const slideHeight = spec.listRef && getHeight(spec.listRef.querySelector('[data-index="0"]'));
|
||||
const slideHeight = listNode && getHeight(listNode.querySelector('[data-index="0"]'));
|
||||
const listHeight = slideHeight * spec.slidesToShow;
|
||||
let currentSlide = spec.currentSlide === undefined ? spec.initialSlide : spec.currentSlide;
|
||||
if (spec.rtl && spec.currentSlide === undefined) {
|
||||
currentSlide = slideCount - 1 - spec.initialSlide;
|
||||
}
|
||||
const lazyLoadedList = spec.lazyLoadedList || [];
|
||||
const slidesToLoad = getOnDemandLazySlides({ currentSlide, lazyLoadedList }, spec);
|
||||
lazyLoadedList.concat(slidesToLoad);
|
||||
let lazyLoadedList = spec.lazyLoadedList || [];
|
||||
const slidesToLoad = getOnDemandLazySlides({ ...spec, currentSlide, lazyLoadedList }, spec);
|
||||
lazyLoadedList = lazyLoadedList.concat(slidesToLoad);
|
||||
|
||||
const state = {
|
||||
slideCount,
|
||||
|
@ -139,7 +152,6 @@ export const slideHandler = spec => {
|
|||
infinite,
|
||||
index,
|
||||
slideCount,
|
||||
lazyLoadedList,
|
||||
lazyLoad,
|
||||
currentSlide,
|
||||
centerMode,
|
||||
|
@ -147,6 +159,7 @@ export const slideHandler = spec => {
|
|||
slidesToShow,
|
||||
useCSS,
|
||||
} = spec;
|
||||
let { lazyLoadedList } = spec;
|
||||
if (waitForAnimate && animating) return {};
|
||||
let animationSlide = index;
|
||||
let finalSlide;
|
||||
|
@ -154,6 +167,7 @@ export const slideHandler = spec => {
|
|||
let finalLeft;
|
||||
let state = {};
|
||||
let nextState = {};
|
||||
const targetSlide = infinite ? index : clamp(index, 0, slideCount - 1);
|
||||
if (fade) {
|
||||
if (!infinite && (index < 0 || index >= slideCount)) return {};
|
||||
if (index < 0) {
|
||||
|
@ -162,14 +176,15 @@ export const slideHandler = spec => {
|
|||
animationSlide = index - slideCount;
|
||||
}
|
||||
if (lazyLoad && lazyLoadedList.indexOf(animationSlide) < 0) {
|
||||
lazyLoadedList.push(animationSlide);
|
||||
lazyLoadedList = lazyLoadedList.concat(animationSlide);
|
||||
}
|
||||
state = {
|
||||
animating: true,
|
||||
currentSlide: animationSlide,
|
||||
lazyLoadedList,
|
||||
targetSlide: animationSlide,
|
||||
};
|
||||
nextState = { animating: false };
|
||||
nextState = { animating: false, targetSlide: animationSlide };
|
||||
} else {
|
||||
finalSlide = animationSlide;
|
||||
if (animationSlide < 0) {
|
||||
|
@ -188,19 +203,28 @@ export const slideHandler = spec => {
|
|||
if (!infinite) finalSlide = slideCount - slidesToShow;
|
||||
else if (slideCount % slidesToScroll !== 0) finalSlide = 0;
|
||||
}
|
||||
|
||||
if (!infinite && animationSlide + slidesToShow >= slideCount) {
|
||||
finalSlide = slideCount - slidesToShow;
|
||||
}
|
||||
|
||||
animationLeft = getTrackLeft({ ...spec, slideIndex: animationSlide });
|
||||
finalLeft = getTrackLeft({ ...spec, slideIndex: finalSlide });
|
||||
if (!infinite) {
|
||||
if (animationLeft === finalLeft) animationSlide = finalSlide;
|
||||
animationLeft = finalLeft;
|
||||
}
|
||||
lazyLoad &&
|
||||
lazyLoadedList.concat(getOnDemandLazySlides({ ...spec, currentSlide: animationSlide }));
|
||||
if (lazyLoad) {
|
||||
lazyLoadedList = lazyLoadedList.concat(
|
||||
getOnDemandLazySlides({ ...spec, currentSlide: animationSlide }),
|
||||
);
|
||||
}
|
||||
if (!useCSS) {
|
||||
state = {
|
||||
currentSlide: finalSlide,
|
||||
trackStyle: getTrackCSS({ ...spec, left: finalLeft }),
|
||||
lazyLoadedList,
|
||||
targetSlide,
|
||||
};
|
||||
} else {
|
||||
state = {
|
||||
|
@ -208,12 +232,14 @@ export const slideHandler = spec => {
|
|||
currentSlide: finalSlide,
|
||||
trackStyle: getTrackAnimateCSS({ ...spec, left: animationLeft }),
|
||||
lazyLoadedList,
|
||||
targetSlide,
|
||||
};
|
||||
nextState = {
|
||||
animating: false,
|
||||
currentSlide: finalSlide,
|
||||
trackStyle: getTrackCSS({ ...spec, left: finalLeft }),
|
||||
swipeLeft: null,
|
||||
targetSlide,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +248,15 @@ export const slideHandler = spec => {
|
|||
|
||||
export const changeSlide = (spec, options) => {
|
||||
let previousInt, slideOffset, targetSlide;
|
||||
const { slidesToScroll, slidesToShow, slideCount, currentSlide, lazyLoad, infinite } = spec;
|
||||
const {
|
||||
slidesToScroll,
|
||||
slidesToShow,
|
||||
slideCount,
|
||||
currentSlide,
|
||||
targetSlide: previousTargetSlide,
|
||||
lazyLoad,
|
||||
infinite,
|
||||
} = spec;
|
||||
const unevenOffset = slideCount % slidesToScroll !== 0;
|
||||
const indexOffset = unevenOffset ? 0 : (slideCount - currentSlide) % slidesToScroll;
|
||||
|
||||
|
@ -233,24 +267,25 @@ export const changeSlide = (spec, options) => {
|
|||
previousInt = currentSlide - slideOffset;
|
||||
targetSlide = previousInt === -1 ? slideCount - 1 : previousInt;
|
||||
}
|
||||
if (!infinite) {
|
||||
targetSlide = previousTargetSlide - slidesToScroll;
|
||||
}
|
||||
} else if (options.message === 'next') {
|
||||
slideOffset = indexOffset === 0 ? slidesToScroll : indexOffset;
|
||||
targetSlide = currentSlide + slideOffset;
|
||||
if (lazyLoad && !infinite) {
|
||||
targetSlide = ((currentSlide + slidesToScroll) % slideCount) + indexOffset;
|
||||
}
|
||||
if (!infinite) {
|
||||
targetSlide = previousTargetSlide + slidesToScroll;
|
||||
}
|
||||
} else if (options.message === 'dots') {
|
||||
// Click on dots
|
||||
targetSlide = options.index * options.slidesToScroll;
|
||||
if (targetSlide === options.currentSlide) {
|
||||
return null;
|
||||
}
|
||||
} else if (options.message === 'children') {
|
||||
// Click on the slides
|
||||
targetSlide = options.index;
|
||||
if (targetSlide === options.currentSlide) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (infinite) {
|
||||
const direction = siblingDirection({ ...spec, targetSlide });
|
||||
if (targetSlide > options.currentSlide && direction === 'left') {
|
||||
|
@ -261,9 +296,6 @@ export const changeSlide = (spec, options) => {
|
|||
}
|
||||
} else if (options.message === 'index') {
|
||||
targetSlide = Number(options.index);
|
||||
if (targetSlide === options.currentSlide) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return targetSlide;
|
||||
};
|
||||
|
@ -277,7 +309,7 @@ export const keyHandler = (e, accessibility, rtl) => {
|
|||
};
|
||||
|
||||
export const swipeStart = (e, swipe, draggable) => {
|
||||
e.target.tagName === 'IMG' && !supportsPassive && e.preventDefault();
|
||||
e.target.tagName === 'IMG' && safePreventDefault.preventDefault();
|
||||
if (!swipe || (!draggable && e.type.indexOf('mouse') !== -1)) return '';
|
||||
return {
|
||||
dragging: true,
|
||||
|
@ -313,11 +345,8 @@ export const swipeMove = (e, spec) => {
|
|||
listWidth,
|
||||
} = spec;
|
||||
if (scrolling) return;
|
||||
if (animating) {
|
||||
!supportsPassive && e.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (vertical && swipeToSlide && verticalSwiping) !supportsPassive && e.preventDefault();
|
||||
if (animating) return safePreventDefault(e);
|
||||
if (vertical && swipeToSlide && verticalSwiping) safePreventDefault(e);
|
||||
let swipeLeft;
|
||||
let state = {};
|
||||
const curLeft = getTrackLeft(spec);
|
||||
|
@ -343,9 +372,9 @@ export const swipeMove = (e, spec) => {
|
|||
let touchSwipeLength = touchObject.swipeLength;
|
||||
if (!infinite) {
|
||||
if (
|
||||
(currentSlide === 0 && swipeDirection === 'right') ||
|
||||
(currentSlide + 1 >= dotCount && swipeDirection === 'left') ||
|
||||
(!canGoNext(spec) && swipeDirection === 'left')
|
||||
(currentSlide === 0 && (swipeDirection === 'right' || swipeDirection === 'down')) ||
|
||||
(currentSlide + 1 >= dotCount && (swipeDirection === 'left' || swipeDirection === 'up')) ||
|
||||
(!canGoNext(spec) && (swipeDirection === 'left' || swipeDirection === 'up'))
|
||||
) {
|
||||
touchSwipeLength = touchObject.swipeLength * edgeFriction;
|
||||
if (edgeDragged === false && onEdge) {
|
||||
|
@ -384,7 +413,7 @@ export const swipeMove = (e, spec) => {
|
|||
}
|
||||
if (touchObject.swipeLength > 10) {
|
||||
state['swiping'] = true;
|
||||
!supportsPassive && e.preventDefault();
|
||||
safePreventDefault(e);
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
@ -397,13 +426,15 @@ export const swipeEnd = (e, spec) => {
|
|||
touchThreshold,
|
||||
verticalSwiping,
|
||||
listHeight,
|
||||
currentSlide,
|
||||
swipeToSlide,
|
||||
scrolling,
|
||||
onSwipe,
|
||||
targetSlide,
|
||||
currentSlide,
|
||||
infinite,
|
||||
} = spec;
|
||||
if (!dragging) {
|
||||
if (swipe) e.preventDefault();
|
||||
if (swipe) safePreventDefault(e);
|
||||
return {};
|
||||
}
|
||||
const minSwipe = verticalSwiping ? listHeight / touchThreshold : listWidth / touchThreshold;
|
||||
|
@ -425,26 +456,27 @@ export const swipeEnd = (e, spec) => {
|
|||
return state;
|
||||
}
|
||||
if (touchObject.swipeLength > minSwipe) {
|
||||
e.preventDefault();
|
||||
safePreventDefault(e);
|
||||
if (onSwipe) {
|
||||
onSwipe(swipeDirection);
|
||||
}
|
||||
let slideCount, newSlide;
|
||||
let activeSlide = infinite ? currentSlide : targetSlide;
|
||||
switch (swipeDirection) {
|
||||
case 'left':
|
||||
case 'up':
|
||||
newSlide = currentSlide + getSlideCount(spec);
|
||||
newSlide = activeSlide + getSlideCount(spec);
|
||||
slideCount = swipeToSlide ? checkNavigable(spec, newSlide) : newSlide;
|
||||
state['currentDirection'] = 0;
|
||||
break;
|
||||
case 'right':
|
||||
case 'down':
|
||||
newSlide = currentSlide - getSlideCount(spec);
|
||||
newSlide = activeSlide - getSlideCount(spec);
|
||||
slideCount = swipeToSlide ? checkNavigable(spec, newSlide) : newSlide;
|
||||
state['currentDirection'] = 1;
|
||||
break;
|
||||
default:
|
||||
slideCount = currentSlide;
|
||||
slideCount = activeSlide;
|
||||
}
|
||||
state['triggerSlideHandler'] = slideCount;
|
||||
} else {
|
||||
|
@ -487,7 +519,7 @@ export const getSlideCount = spec => {
|
|||
if (spec.swipeToSlide) {
|
||||
let swipedSlide;
|
||||
const slickList = spec.listRef;
|
||||
const slides = slickList.querySelectorAll('.slick-slide');
|
||||
const slides = (slickList.querySelectorAll && slickList.querySelectorAll('.slick-slide')) || [];
|
||||
Array.from(slides).every(slide => {
|
||||
if (!spec.vertical) {
|
||||
if (slide.offsetLeft - centerOffset + getWidth(slide) / 2 > spec.swipeLeft * -1) {
|
Loading…
Reference in New Issue