@opensig/opendesign
Version:
413 lines (412 loc) • 12.5 kB
JavaScript
import { defineComponent, ref, computed, watch, onMounted, onUnmounted, nextTick, provide, createElementBlock, openBlock, normalizeStyle, normalizeClass, createElementVNode, createCommentVNode, renderSlot, Fragment, renderList, createVNode, unref } from "vue";
import { IconChevronLeft, IconChevronRight } from "../_utils/icons.mjs";
import Gallery from "./effects/gallery.mjs";
import Toggle from "./effects/toggle.mjs";
import { carouselInjectKey } from "./provide.mjs";
import { carouselProps } from "./types.mjs";
const _hoisted_1 = { class: "o-carousel-wrap" };
const _hoisted_2 = ["onClick"];
const _hoisted_3 = { class: "o-carousel-arrow-prev" };
const _hoisted_4 = { class: "o-carousel-arrow-icon" };
const _hoisted_5 = { class: "o-carousel-arrow-next" };
const _hoisted_6 = { class: "o-carousel-arrow-icon" };
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "OCarousel",
props: carouselProps,
emits: ["before-change", "change", "update:activeIndex", "pause"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const containerRef = ref(null);
const childrenLength = ref(0);
const registerItem = () => {
childrenLength.value++;
};
const unregisterItem = () => {
childrenLength.value++;
};
const total = computed(() => {
var _a;
childrenLength.value;
return ((_a = containerRef.value) == null ? void 0 : _a.children.length) ?? 0;
});
const isAutoPlay = ref(props.autoPlay);
watch(
() => props.autoPlay,
(a) => {
isAutoPlay.value = a;
}
);
const fixIndex = (idx) => {
if (!total.value) {
return idx;
}
const i = idx % total.value;
return i >= 0 ? i : i + total.value;
};
const activeIndex = ref(props.activeIndex ? fixIndex(props.activeIndex) : 0);
watch(
() => props.activeIndex,
(v) => {
activeIndex.value = v ?? 0;
}
);
const initialized = ref(false);
const slidesRef = ref(null);
const slideElList = computed(() => {
var _a;
childrenLength.value;
const c = (_a = containerRef.value) == null ? void 0 : _a.children;
return c ? Array.from(c).map((el) => el) : null;
});
let slidesInstance = null;
let isChanging = false;
const activeSlideByIndex = (index) => {
return new Promise((resolve) => {
const to = fixIndex(index);
const from = activeIndex.value;
if (isChanging || !slideElList.value) {
resolve(false);
return;
}
if (to === from) {
resolve(true);
return;
}
isChanging = true;
if (slidesInstance) {
activeIndex.value = to;
emits("update:activeIndex", to);
slidesInstance.active(to).then(() => {
isChanging = false;
resolve(true);
});
} else {
isChanging = false;
resolve(false);
}
});
};
let timer = null;
const isPlaying = ref(isAutoPlay.value);
const pausePlay = () => {
if (timer) {
clearInterval(timer);
timer = null;
isPlaying.value = false;
emits("pause", activeIndex.value);
}
};
const startPlay = () => {
pausePlay();
isPlaying.value = true;
timer = window.setInterval(() => {
activeSlideByIndex(activeIndex.value + 1);
}, props.interval);
};
const resumePlay = () => {
if (isAutoPlay.value) {
setTimeout(() => {
startPlay();
}, 0);
}
};
const activeSlide = (index, resumeAutoPlay = true) => {
pausePlay();
return activeSlideByIndex(index).then((success) => {
if (!success) {
return;
}
if (!props.pauseOnHover || resumeAutoPlay) {
resumePlay();
}
});
};
const clickListenerCleanups = [];
const cleanupClickListeners = () => {
clickListenerCleanups.forEach((fn) => fn());
clickListenerCleanups.length = 0;
};
const buildEffectOptions = () => ({
activeClass: props.activeClass,
onTouchstart: () => {
pausePlay();
},
onTouchend: () => {
resumePlay();
},
onBeforeChange: (to, from) => {
emits("before-change", to, from);
},
onChanged: (to, from) => {
activeIndex.value = to;
emits("update:activeIndex", to);
emits("change", to, from);
}
});
const bindClickListeners = (els) => {
els.forEach((el, idx) => {
const handler = () => {
if (idx !== activeIndex.value) {
activeSlide(idx);
}
};
el.addEventListener("click", handler);
clickListenerCleanups.push(() => el.removeEventListener("click", handler));
});
};
const initSlides = () => {
if (!slideElList.value || !containerRef.value) {
return;
}
slidesInstance == null ? void 0 : slidesInstance.destroyed();
slidesInstance = null;
cleanupClickListeners();
if (activeIndex.value >= slideElList.value.length) {
activeIndex.value = fixIndex(activeIndex.value);
emits("update:activeIndex", activeIndex.value);
}
let EffectType = null;
switch (props.effect) {
case "gallery": {
EffectType = Gallery;
break;
}
case "toggle": {
EffectType = Toggle;
break;
}
default: {
EffectType = Gallery;
break;
}
}
if (EffectType) {
slidesInstance = new EffectType(slideElList.value, containerRef.value, activeIndex.value, buildEffectOptions());
}
if (props.clickToSwitch) {
bindClickListeners(slideElList.value);
}
initialized.value = true;
};
watch(
() => props.autoPlay,
(v) => {
if (v) {
startPlay();
} else {
pausePlay();
}
}
);
const init = () => {
initSlides();
if (isAutoPlay.value) {
startPlay();
}
};
onMounted(() => {
if (!props.manualInit) {
init();
}
});
onUnmounted(() => {
if (timer) {
clearInterval(timer);
timer = null;
}
slidesInstance == null ? void 0 : slidesInstance.destroyed();
cleanupClickListeners();
});
watch(
() => {
var _a;
return ((_a = slideElList.value) == null ? void 0 : _a.length) ?? 0;
},
async (now, prev) => {
if (!initialized.value || now === prev) {
return;
}
await nextTick();
initSlides();
}
);
provide(carouselInjectKey, {
effect: props.effect,
register: registerItem,
unregister: unregisterItem
});
const play = () => {
isAutoPlay.value = true;
startPlay();
};
const pause = () => {
isAutoPlay.value = false;
pausePlay();
};
const onHoverIn = () => {
if (props.pauseOnHover) {
pausePlay();
}
};
const onHoverOut = () => {
if (props.pauseOnHover) {
resumePlay();
}
};
__expose({
/**
* @zh-CN 初始化轮播组件
* @en-US Initialize the carousel component
*/
init,
/**
* @zh-CN 开始自动播放
* @en-US Start auto play
*/
play,
/**
* @zh-CN 暂停自动播放
* @en-US Pause auto play
*/
pause,
/**
* @zh-CN 切换到指定幻灯片
* @en-US Switch to the specified slide
*/
active: activeSlide
});
return (_ctx, _cache) => {
return openBlock(), createElementBlock(
"div",
{
ref_key: "slidesRef",
ref: slidesRef,
class: normalizeClass(["o-carousel", [
{
"o-carousel-visible": initialized.value,
"o-carousel-click-to-switch": props.clickToSwitch,
"o-carousel-hover-arrow": props.arrow === "hover",
"o-carousel-autoplay": isAutoPlay.value,
"is-playing": isPlaying.value
},
`o-carousel-effect-${props.effect}`
]]),
style: normalizeStyle({
"--carousel-interval": props.interval + "ms"
}),
onMouseenter: onHoverIn,
onMouseleave: onHoverOut
},
[
createElementVNode("div", _hoisted_1, [
createElementVNode(
"div",
{
ref_key: "containerRef",
ref: containerRef,
class: normalizeClass([`o-carousel-container-${props.effect}`])
},
[
renderSlot(_ctx.$slots, "default")
],
2
/* CLASS */
)
]),
!props.hideIndicator ? (openBlock(), createElementBlock(
"div",
{
key: 0,
class: normalizeClass(["o-carousel-indicator-wrap", props.indicatorWrapClass])
},
[
(openBlock(true), createElementBlock(
Fragment,
null,
renderList(total.value, (item, idx) => {
return openBlock(), createElementBlock("div", {
key: item,
class: "o-carousel-indicator-item",
onClick: ($event) => props.indicatorClick && activeSlide(idx)
}, [
renderSlot(_ctx.$slots, "indicator", {
active: item - 1 === activeIndex.value,
index: idx
}, () => [
createElementVNode(
"div",
{
class: normalizeClass(["o-carousel-indicator-bar", {
"o-carousel-indicator-bar-selected": item - 1 === activeIndex.value
}])
},
[..._cache[2] || (_cache[2] = [
createElementVNode(
"div",
{ class: "o-carousel-indicator-line" },
null,
-1
/* CACHED */
)
])],
2
/* CLASS */
)
])
], 8, _hoisted_2);
}),
128
/* KEYED_FRAGMENT */
))
],
2
/* CLASS */
)) : createCommentVNode("v-if", true),
props.arrow !== "never" ? (openBlock(), createElementBlock(
"div",
{
key: 1,
class: normalizeClass(["o-carousel-arrow-wrap", props.arrowWrapClass])
},
[
createElementVNode("div", {
onClick: _cache[0] || (_cache[0] = ($event) => activeSlide(activeIndex.value - 1, false))
}, [
renderSlot(_ctx.$slots, "arrow-prev", {}, () => [
createElementVNode("div", _hoisted_3, [
createElementVNode("div", _hoisted_4, [
renderSlot(_ctx.$slots, "arrow-prev-icon", {}, () => [
createVNode(unref(IconChevronLeft))
])
])
])
])
]),
createElementVNode("div", {
onClick: _cache[1] || (_cache[1] = ($event) => activeSlide(activeIndex.value + 1, false))
}, [
renderSlot(_ctx.$slots, "arrow-next", {}, () => [
createElementVNode("div", _hoisted_5, [
createElementVNode("div", _hoisted_6, [
renderSlot(_ctx.$slots, "arrow-next-icon", {}, () => [
createVNode(unref(IconChevronRight))
])
])
])
])
])
],
2
/* CLASS */
)) : createCommentVNode("v-if", true)
],
38
/* CLASS, STYLE, NEED_HYDRATION */
);
};
}
});
export {
_sfc_main as default
};