@arco-design/web-vue
Version:
Arco Design Vue 2.0: A Vue.js 3 UI Library
239 lines (238 loc) • 7.08 kB
JavaScript
;
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;