UNPKG

@arco-design/web-vue

Version:

Arco Design Vue 2.0: A Vue.js 3 UI Library

239 lines (238 loc) 7.08 kB
"use strict"; var vue = require("vue"); var globalConfig = require("../_utils/global-config.js"); var carouselIndicator = require("./carousel-indicator.js"); var carouselArrow = require("./carousel-arrow.js"); var context = require("./context.js"); var is = require("../_utils/is.js"); var useChildrenComponents = require("../_hooks/use-children-components.js"); const DEFAULT_AUTO_PLAY = { interval: 3e3, hoverToPause: true }; function getValidIndex(i, length) { const indexNumber = +i; return typeof indexNumber === "number" && !Number.isNaN(indexNumber) ? (indexNumber + length) % length : i; } var _Carousel = vue.defineComponent({ name: "Carousel", props: { current: { type: Number }, defaultCurrent: { type: Number, default: 1 }, autoPlay: { type: [Boolean, Object], default: false }, moveSpeed: { type: Number, default: 500 }, animationName: { type: String, default: "slide" }, trigger: { type: String, default: "click" }, direction: { type: String, default: "horizontal" }, showArrow: { type: String, default: "always" }, arrowClass: { type: String, default: "" }, indicatorType: { type: String, default: "dot" }, indicatorPosition: { type: String, default: "bottom" }, indicatorClass: { type: String, default: "" }, transitionTimingFunction: { type: String, default: "cubic-bezier(0.34, 0.69, 0.1, 1)" } }, emits: { "update:current": (index) => true, "change": (index, prevIndex, isManual) => true }, setup(props, { emit, slots }) { const { current, animationName, moveSpeed, transitionTimingFunction } = vue.toRefs(props); const prefixCls = globalConfig.getPrefixCls("carousel"); const isPause = vue.ref(false); const previousIndex = vue.ref(); const slideDirection = vue.ref(); const computedAutoPlay = vue.computed(() => { if (is.isObject(props.autoPlay)) { return { ...DEFAULT_AUTO_PLAY, ...props.autoPlay }; } return props.autoPlay ? DEFAULT_AUTO_PLAY : {}; }); let intervalTimer = 0; let animationTimer = 0; const { children, components } = useChildrenComponents.useChildrenComponents("CarouselItem"); const _index = vue.ref(props.defaultCurrent - 1); const mergedIndexes = vue.computed(() => { const childrenLength = components.value.length; const mergedIndex = is.isNumber(current.value) ? getValidIndex(current.value - 1, childrenLength) : _index.value; const prevIndex = getValidIndex(mergedIndex - 1, childrenLength); const nextIndex = getValidIndex(mergedIndex + 1, childrenLength); return { mergedIndex, mergedPrevIndex: prevIndex, mergedNextIndex: nextIndex }; }); const carouselContext = vue.reactive({ items: components, slideTo, mergedIndexes, previousIndex, animationName, slideDirection, transitionTimingFunction, moveSpeed }); vue.provide(context.carouselInjectionKey, carouselContext); const clearTimer = () => { if (intervalTimer) { window.clearInterval(intervalTimer); } }; vue.watchEffect(() => { var _a; const { interval } = computedAutoPlay.value || {}; const { mergedNextIndex } = mergedIndexes.value; const shouldInterval = ((_a = components.value) == null ? void 0 : _a.length) > 1 && !isPause.value && Boolean(interval); clearTimer(); if (shouldInterval) { intervalTimer = window.setInterval(() => { slideTo({ targetIndex: mergedNextIndex }); }, interval); } }); vue.onBeforeUnmount(() => { clearTimer(); }); function slideTo({ targetIndex, isNegative = false, isManual = false }) { if (!animationTimer && targetIndex !== mergedIndexes.value.mergedIndex) { previousIndex.value = _index.value; _index.value = targetIndex; slideDirection.value = isNegative ? "negative" : "positive"; animationTimer = window.setTimeout(() => { animationTimer = 0; }, moveSpeed.value); emit("update:current", _index.value + 1); emit("change", _index.value + 1, previousIndex.value + 1, isManual); } } const onPreviousClick = () => slideTo({ targetIndex: mergedIndexes.value.mergedPrevIndex, isNegative: true, isManual: true }); const onNextClick = () => slideTo({ targetIndex: mergedIndexes.value.mergedNextIndex, isManual: true }); const onSelect = (index) => slideTo({ targetIndex: index, isNegative: index < mergedIndexes.value.mergedIndex, isManual: true }); const eventHandlers = vue.computed(() => { return computedAutoPlay.value.hoverToPause ? { onMouseenter: () => { isPause.value = true; }, onMouseleave: () => { isPause.value = false; } } : {}; }); const hasIndicator = vue.computed(() => { return props.indicatorType !== "never" && components.value.length > 1; }); const hasArrow = vue.computed(() => { return props.showArrow !== "never" && components.value.length > 1; }); const cls = vue.computed(() => { return [prefixCls, `${prefixCls}-indicator-position-${props.indicatorPosition}`]; }); const contentCls = vue.computed(() => { return [`${prefixCls}-${props.animationName}`, `${prefixCls}-${props.direction}`, { [`${prefixCls}-negative`]: slideDirection.value === "negative" }]; }); const indicatorCls = vue.computed(() => { return [`${prefixCls}-indicator-wrapper`, `${prefixCls}-indicator-wrapper-${props.indicatorPosition}`]; }); return () => { var _a; children.value = (_a = slots.default) == null ? void 0 : _a.call(slots); return vue.createVNode("div", vue.mergeProps({ "class": cls.value }, eventHandlers.value), [vue.createVNode("div", { "class": contentCls.value }, [children.value]), hasIndicator.value && vue.createVNode("div", { "class": indicatorCls.value }, [vue.createVNode(carouselIndicator, { "class": props.indicatorClass, "type": props.indicatorType, "count": components.value.length, "activeIndex": mergedIndexes.value.mergedIndex, "position": props.indicatorPosition, "trigger": props.trigger, "onSelect": onSelect }, null)]), hasArrow.value && vue.createVNode(carouselArrow, { "class": props.arrowClass, "direction": props.direction, "showArrow": props.showArrow, "onPreviousClick": onPreviousClick, "onNextClick": onNextClick }, null)]); }; } }); module.exports = _Carousel;