UNPKG

vue3-carrousel

Version:

Ce composant est un carousel flexible et personnalisable. Il permet de créer un slider avec des options telles que le défilement automatique, l'effet de boucle, le contrôle via les touches du clavier, et bien plus encore.

399 lines (398 loc) 12.8 kB
import { h as B, toRef as ee, readonly as E, customRef as te, ref as I, onMounted as G, nextTick as ne, getCurrentScope as le, onScopeDispose as oe, unref as D, getCurrentInstance as re, reactive as X, computed as $, watch as se, defineComponent as ae, useTemplateRef as V, onUnmounted as ue, openBlock as k, createElementBlock as x, createElementVNode as P, normalizeStyle as M, Fragment as K, renderList as z, renderSlot as F, toDisplayString as ie, createVNode as H, createCommentVNode as W, normalizeClass as ce } from "vue"; /** * @license lucide-vue-next v0.453.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */ const de = (t) => t.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); /** * @license lucide-vue-next v0.453.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */ var T = { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": 2, "stroke-linecap": "round", "stroke-linejoin": "round" }; /** * @license lucide-vue-next v0.453.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */ const ve = ({ size: t, strokeWidth: l = 2, absoluteStrokeWidth: e, color: u, iconNode: c, name: n, class: v, ...g }, { slots: f }) => B( "svg", { ...T, width: t || T.width, height: t || T.height, stroke: u || T.stroke, "stroke-width": e ? Number(l) * 24 / Number(t) : l, class: ["lucide", `lucide-${de(n ?? "icon")}`], ...g }, [...c.map((m) => B(...m)), ...f.default ? [f.default()] : []] ); /** * @license lucide-vue-next v0.453.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */ const q = (t, l) => (e, { slots: u }) => B( ve, { ...e, iconNode: l, name: t }, u ); /** * @license lucide-vue-next v0.453.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */ const fe = q("ChevronLeftIcon", [ ["path", { d: "m15 18-6-6 6-6", key: "1wnfg3" }] ]); /** * @license lucide-vue-next v0.453.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */ const pe = q("ChevronRightIcon", [ ["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }] ]); async function Y(t) { return new Promise((l) => setTimeout(l, t)); } function ye(t) { return le() ? (oe(t), !0) : !1; } function U(t) { return typeof t == "function" ? t() : D(t); } const he = typeof window < "u" && typeof document < "u"; typeof WorkerGlobalScope < "u" && globalThis instanceof WorkerGlobalScope; const ge = Object.prototype.toString, we = (t) => ge.call(t) === "[object Object]", Z = () => { }; function me(t) { return re(); } function be(...t) { if (t.length !== 1) return ee(...t); const l = t[0]; return typeof l == "function" ? E(te(() => ({ get: l, set: Z }))) : I(l); } function Se(t, l = !0, e) { me() ? G(t, e) : l ? t() : ne(t); } const ke = he ? window : void 0; function xe(t) { var l; const e = U(t); return (l = e == null ? void 0 : e.$el) != null ? l : e; } function j(...t) { let l, e, u, c; if (typeof t[0] == "string" || Array.isArray(t[0]) ? ([e, u, c] = t, l = ke) : [l, e, u, c] = t, !l) return Z; Array.isArray(e) || (e = [e]), Array.isArray(u) || (u = [u]); const n = [], v = () => { n.forEach((s) => s()), n.length = 0; }, g = (s, p, h, w) => (s.addEventListener(p, h, w), () => s.removeEventListener(p, h, w)), f = se( () => [xe(l), U(c)], ([s, p]) => { if (v(), !s) return; const h = we(p) ? { ...p } : p; n.push( ...e.flatMap((w) => u.map((A) => g(s, w, A, h))) ); }, { immediate: !0, flush: "post" } ), m = () => { f(), v(); }; return ye(m), m; } function Ae(t, l = {}) { const e = be(t), { threshold: u = 50, onSwipe: c, onSwipeEnd: n, onSwipeStart: v, disableTextSelect: g = !1 } = l, f = X({ x: 0, y: 0 }), m = (r, y) => { f.x = r, f.y = y; }, s = X({ x: 0, y: 0 }), p = (r, y) => { s.x = r, s.y = y; }, h = $(() => f.x - s.x), w = $(() => f.y - s.y), { max: A, abs: o } = Math, i = $(() => A(o(h.value), o(w.value)) >= u), a = I(!1), d = I(!1), C = $(() => i.value ? o(h.value) > o(w.value) ? h.value > 0 ? "left" : "right" : w.value > 0 ? "up" : "down" : "none"), O = (r) => { var y, b, S; const _ = r.buttons === 0, L = r.buttons === 1; return (S = (b = (y = l.pointerTypes) == null ? void 0 : y.includes(r.pointerType)) != null ? b : _ || L) != null ? S : !0; }, J = [ j(t, "pointerdown", (r) => { if (!O(r)) return; d.value = !0; const y = r.target; y == null || y.setPointerCapture(r.pointerId); const { clientX: b, clientY: S } = r; m(b, S), p(b, S), v == null || v(r); }), j(t, "pointermove", (r) => { if (!O(r) || !d.value) return; const { clientX: y, clientY: b } = r; p(y, b), !a.value && i.value && (a.value = !0), a.value && (c == null || c(r)); }), j(t, "pointerup", (r) => { O(r) && (a.value && (n == null || n(r, C.value)), d.value = !1, a.value = !1); }) ]; Se(() => { var r, y, b, S, _, L, R, N; (y = (r = e.value) == null ? void 0 : r.style) == null || y.setProperty("touch-action", "none"), g && ((S = (b = e.value) == null ? void 0 : b.style) == null || S.setProperty("-webkit-user-select", "none"), (L = (_ = e.value) == null ? void 0 : _.style) == null || L.setProperty("-ms-user-select", "none"), (N = (R = e.value) == null ? void 0 : R.style) == null || N.setProperty("user-select", "none")); }); const Q = () => J.forEach((r) => r()); return { isSwiping: E(a), direction: E(C), posStart: E(f), posEnd: E(s), distanceX: h, distanceY: w, stop: Q }; } const Ce = { class: "p-11 text-center select-none" }, Pe = { class: "w-full flex justify-center gap-2 pb-4" }, Ee = ["onClick"], Ie = /* @__PURE__ */ ae({ __name: "Carousel", props: { /** * Position par défaut du carousel */ modelValue: { type: Number, default: 0 }, /** * Nombre de slides à afficher */ // itemsToShow: { // type: Number, // default: 1, // }, /** * Nombre de slides à scroller */ // itemsToScroll: { // type: Number, // default: 1, // }, /** * Slides à afficher */ slides: { type: Array, default: () => [] }, /** * Active ou non l'effet de boucle */ wrapAround: { type: Boolean, default: !1 }, /** * Durée de la transition */ transitionDuration: { type: Number, default: 300 }, /** * Active ou non le défilement automatique */ autoPlay: { type: Boolean, default: !1 }, /** * Intervalle de temps entre chaque slide */ autoPlayInterval: { type: Number, default: 5e3 }, /** * Active ou non la pause du défilement automatique au survol */ pauseAutoPlayOnHover: { type: Boolean, default: !0 }, /** * Active ou non la navigation au clavier */ arrowKeys: { type: Boolean, default: !0 }, /** * Active ou non le swipe */ touchDrag: { type: Boolean, default: !0 } }, setup(t, { expose: l }) { const e = t, u = V("carousel"), c = V("slides"), n = I(0), v = I(void 0), g = $(() => e.slides.length < 2 ? { 0: e.slides[0] } : e.wrapAround ? { 0: e.slides[e.slides.length - 1], ...e.slides.reduce((o, i, a) => (o[a + 1] = i, o), {}), [e.slides.length + 1]: e.slides[0] } : { ...e.slides.reduce((o, i, a) => (o[a] = i, o), {}) }); G(() => { if (s(e.modelValue, !1), e.autoPlay) { const o = () => { const i = n.value === e.slides.length - 1; if (!e.wrapAround && i) { clearInterval(v.value); return; } p(); }; v.value = setInterval(o, e.autoPlayInterval), e.pauseAutoPlayOnHover && u.value && (u.value.addEventListener("mouseenter", () => { clearInterval(v.value); }), u.value.addEventListener("mouseleave", () => { v.value = setInterval(o, e.autoPlayInterval); })); } }), ue(() => { e.autoPlay && (clearInterval(v.value), e.pauseAutoPlayOnHover && u.value && (u.value.removeEventListener("mouseenter", () => { clearInterval(v.value); }), u.value.removeEventListener("mouseleave", () => { clearInterval(v.value); }))); }); const { direction: f, distanceX: m } = Ae(c, { onSwipe() { if (c.value && e.touchDrag && e.wrapAround) { const o = 100 / Object.keys(g.value).length, a = e.slides.length > 1 || e.wrapAround ? n.value + 1 : n.value, d = `translateX(-${o * a}%)`; if (c.value.style.transition = "none", f.value === "right") { const C = Math.sign(m.value) * m.value; c.value.style.transform = `translateX(${C}px) ${d}`; } else c.value.style.transform = `translateX(-${m.value}px) ${d}`; } }, onSwipeEnd() { const o = f.value === "right", i = f.value === "left", a = n.value === 0 && o, d = n.value === e.slides.length - 1 && i; (a || d) && !e.wrapAround || (i ? p() : o && h()); } }); function s(o, i = !0) { if (c.value) { n.value = o; const a = 100 / Object.keys(g.value).length, d = e.slides.length < 2 || !e.wrapAround ? o : o + 1; i ? c.value.style.transition = `transform ${e.transitionDuration}ms` : c.value.style.transition = "none", c.value.style.transform = `translateX(-${a * d}%)`; } } function p() { if (n.value === e.slides.length - 1) { w(); return; } n.value++, n.value >= e.slides.length && (n.value = 0), s(n.value); } function h() { if (n.value === 0) { A(); return; } n.value--, n.value < 0 && (n.value = e.slides.length - 1), s(n.value); } async function w() { n.value++, s(n.value), n.value = 0, await Y(e.transitionDuration), s(n.value, !1); } async function A() { n.value--, s(n.value), n.value = e.slides.length - 1, await Y(e.transitionDuration), s(n.value, !1); } return l({ next: p, prev: h, slideTo: s, currentSlide: n }), (o, i) => (k(), x("div", { ref_key: "carousel", ref: u, class: "relative w-full max-w-[800px] mx-auto overflow-hidden" }, [ P("div", { ref: "slides", class: "flex items-center overflow-x-auto select-none", style: M({ width: `${100 * Object.keys(g.value).length}%` }) }, [ (k(!0), x(K, null, z(g.value, (a, d) => (k(), x("div", { key: d, style: M({ width: `${100 / Object.keys(g.value).length}%` }) }, [ F(o.$slots, "slide", { s: a }, () => [ P("div", Ce, [ P("p", null, ie(a), 1) ]) ]) ], 4))), 128)) ], 4), P("div", null, [ e.arrowKeys && (e.wrapAround || n.value > 0) ? (k(), x("button", { key: 0, class: "absolute top-1/2 left-3 -translate-y-1/2 cursor-pointer bg-transparent border-none outline-none", onClick: i[0] || (i[0] = (a) => h()) }, [ H(D(fe), { size: 32 }) ])) : W("", !0), e.arrowKeys && (e.wrapAround || n.value < e.slides.length - 1) ? (k(), x("button", { key: 1, class: "absolute top-1/2 right-3 -translate-y-1/2 cursor-pointer bg-transparent border-none outline-none", onClick: i[1] || (i[1] = (a) => p()) }, [ H(D(pe), { size: 32 }) ])) : W("", !0) ]), F(o.$slots, "addons", { slides: t.slides }, () => [ P("div", Pe, [ (k(!0), x(K, null, z(t.slides, (a, d) => (k(), x("span", { key: d, class: ce([ "w-2 h-2 mx-1 rounded-full cursor-pointer", [ d === n.value ? "bg-gray-100 border border-neutral-700 dark:bg-neutral-700 dark:border-gray-100" : "bg-neutral-700 dark:bg-gray-100" ] ]), onClick: (C) => s(d, !0) }, null, 10, Ee))), 128)) ]) ]) ], 512)); } }); export { Ie as Carousel };