@opensig/opendesign
Version:
<p align="center"><img src="../docs/public/opendesign-logo-light.png"/></p> <h1 align="center">opendesign</h1> <p align="center">一个 Vue 3 组件库</p> <p align="center"><b>皮肤可定制,使用 TypeScript</b></p>
354 lines (353 loc) • 10.8 kB
JavaScript
;
const vue = require("vue");
const icons = require("../_utils/icons.js");
const gallery = require("./effects/gallery.js");
const toggle = require("./effects/toggle.js");
const provide = require("./provide.js");
const types = require("./types.js");
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__ */ vue.defineComponent({
__name: "OCarousel",
props: types.carouselProps,
emits: ["before-change", "change", "update:activeIndex", "pause"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const containerRef = vue.ref(null);
const total = vue.computed(() => {
var _a;
return (_a = containerRef.value) == null ? void 0 : _a.children.length;
});
const isAutoPlay = vue.ref(props.autoPlay);
vue.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 = vue.ref(props.activeIndex ? fixIndex(props.activeIndex) : 0);
vue.watch(
() => props.activeIndex,
(v) => {
activeIndex.value = v ?? 0;
}
);
const initialized = vue.ref(false);
const slidesRef = vue.ref(null);
const slideElList = vue.computed(() => {
var _a;
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 = vue.ref(isAutoPlay.value);
const pausePlay = () => {
if (timer) {
clearInterval(timer);
timer = null;
isPlaying.value = false;
emits("pause", activeIndex.value);
}
};
const resumePlay = () => {
if (isAutoPlay.value) {
setTimeout(() => {
startPlay();
}, 0);
}
};
const startPlay = () => {
pausePlay();
isPlaying.value = true;
timer = window.setInterval(() => {
activeSlideByIndex(activeIndex.value + 1);
}, props.interval);
};
const activeSlide = (index, resumeAutoPlay = true) => {
pausePlay();
return activeSlideByIndex(index).then((success) => {
if (!success) {
return;
}
if (!props.pauseOnHover || resumeAutoPlay) {
resumePlay();
}
});
};
const initSlides = () => {
if (!slideElList.value || !containerRef.value || initialized.value) {
return;
}
const options = {
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);
}
};
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, options);
}
if (props.clickToSwitch) {
slideElList.value.forEach((el, idx) => {
el.addEventListener("click", () => {
if (idx !== activeIndex.value) {
activeSlide(idx);
}
});
});
}
initialized.value = true;
};
vue.watch(
() => props.autoPlay,
(v) => {
if (v) {
startPlay();
} else {
pausePlay();
}
}
);
const init = () => {
initSlides();
if (isAutoPlay.value) {
startPlay();
}
};
vue.onMounted(() => {
if (!props.manualInit) {
init();
}
});
vue.onUnmounted(() => {
if (timer) {
clearInterval(timer);
timer = null;
}
slidesInstance == null ? void 0 : slidesInstance.destroyed();
});
vue.provide(provide.carouselInjectKey, {
effect: props.effect
});
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({
init,
play,
pause,
active: activeSlide
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock(
"div",
{
ref_key: "slidesRef",
ref: slidesRef,
class: vue.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: vue.normalizeStyle({
"--carousel-interval": props.interval + "ms"
}),
onMouseenter: onHoverIn,
onMouseleave: onHoverOut
},
[
vue.createElementVNode("div", _hoisted_1, [
vue.createElementVNode(
"div",
{
ref_key: "containerRef",
ref: containerRef,
class: vue.normalizeClass([`o-carousel-container-${props.effect}`])
},
[
vue.renderSlot(_ctx.$slots, "default")
],
2
/* CLASS */
)
]),
!props.hideIndicator ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 0,
class: vue.normalizeClass(["o-carousel-indicator-wrap", props.indicatorWrapClass])
},
[
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList(total.value, (item, idx) => {
return vue.openBlock(), vue.createElementBlock("div", {
key: item,
class: "o-carousel-indicator-item",
onClick: ($event) => props.indicatorClick && activeSlide(idx)
}, [
vue.renderSlot(_ctx.$slots, "indicator", {
active: item - 1 === activeIndex.value,
index: idx
}, () => [
vue.createElementVNode(
"div",
{
class: vue.normalizeClass(["o-carousel-indicator-bar", {
"o-carousel-indicator-bar-selected": item - 1 === activeIndex.value
}])
},
_cache[2] || (_cache[2] = [
vue.createElementVNode(
"div",
{ class: "o-carousel-indicator-line" },
null,
-1
/* HOISTED */
)
]),
2
/* CLASS */
)
])
], 8, _hoisted_2);
}),
128
/* KEYED_FRAGMENT */
))
],
2
/* CLASS */
)) : vue.createCommentVNode("v-if", true),
props.arrow !== "never" ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 1,
class: vue.normalizeClass(["o-carousel-arrow-wrap", props.arrowWrapClass])
},
[
vue.createElementVNode("div", {
onClick: _cache[0] || (_cache[0] = ($event) => activeSlide(activeIndex.value - 1, false))
}, [
vue.renderSlot(_ctx.$slots, "arrow-prev", {}, () => [
vue.createElementVNode("div", _hoisted_3, [
vue.createElementVNode("div", _hoisted_4, [
vue.renderSlot(_ctx.$slots, "arrow-prev-icon", {}, () => [
vue.createVNode(vue.unref(icons.IconChevronLeft))
])
])
])
])
]),
vue.createElementVNode("div", {
onClick: _cache[1] || (_cache[1] = ($event) => activeSlide(activeIndex.value + 1, false))
}, [
vue.renderSlot(_ctx.$slots, "arrow-next", {}, () => [
vue.createElementVNode("div", _hoisted_5, [
vue.createElementVNode("div", _hoisted_6, [
vue.renderSlot(_ctx.$slots, "arrow-next-icon", {}, () => [
vue.createVNode(vue.unref(icons.IconChevronRight))
])
])
])
])
])
],
2
/* CLASS */
)) : vue.createCommentVNode("v-if", true)
],
38
/* CLASS, STYLE, NEED_HYDRATION */
);
};
}
});
module.exports = _sfc_main;