UNPKG

@farris/ui-vue

Version:

Farris Vue, a Farris Design based Vue3 component library.

348 lines (347 loc) 10 kB
import { withInstall as J } from "../common/index.esm.js"; import { defineComponent as V, ref as x, computed as A, watch as H, onMounted as X, onUnmounted as Y, createVNode as u, Fragment as D, createTextVNode as N } from "vue"; const G = { // 初始激活的内容项索引 initialIndex: { type: Number, default: 0 }, // 走马灯容器高度 height: { type: String, default: "400px" }, // 是否自动轮播 autoplay: { type: Boolean, default: !0 }, // 自动轮播的时间间隔(毫秒) interval: { type: Number, default: 3e3 }, // 是否循环展示 loop: { type: Boolean, default: !0 }, // 展示方向 direction: { type: String, default: "horizontal", validator: (e) => ["horizontal", "vertical"].includes(e) }, // 切换按钮显示时机 arrow: { type: String, default: "hover", validator: (e) => ["always", "hover", "never"].includes(e) }, // 指示器位置 indicatorPosition: { type: String, default: "inside", validator: (e) => ["inside", "outside", "none"].includes(e) }, // 指示器切换触发方式 trigger: { type: String, default: "click", validator: (e) => ["click", "hover"].includes(e) }, // 悬停时是否暂停自动轮播 pauseOnHover: { type: Boolean, default: !0 }, // 展示风格类型 type: { type: String, default: "", validator: (e) => ["card", ""].includes(e) }, // 是否显示标题区域 showTitle: { type: Boolean, default: !1 }, // 标题对齐方式 titleAlign: { type: String, default: "left", validator: (e) => ["left", "center", "right"].includes(e) } }; function U(e, { emit: m, slots: s }, n, d, h, c) { const f = (l) => e.loop ? l - 1 : l, w = () => { if (!e.loop) return; let l = !1, v = n.value; n.value === 0 ? (v = d.value, l = !0) : n.value === h.value - 1 && (v = 1, l = !0), l && (c.value = !1, n.value = v); }, g = (l, v = !1) => { if (c.value && !v) return; let o; if (typeof l == "string") { if (!s.default || (o = s.default().findIndex((I) => { var S; return ((S = I.props) == null ? void 0 : S.name) === l; }), o === -1)) return; e.loop && (o += 1); } else o = l; if (o < 0 || o >= h.value) { if (!e.loop) return; o < 0 ? o = h.value - 2 : o = 1; } if (o === n.value && !v) return; const k = f(n.value); n.value = o, c.value = !v, v || setTimeout(() => { c.value = !1, w(); }, 500), m("change", f(o), k); }; return { setActiveItem: g, next: () => { if (d.value <= 1) return; let l = n.value + 1; if (l >= h.value) { if (!e.loop) return; l = h.value - 1; } g(l); }, prev: () => { if (d.value <= 1) return; let l = n.value - 1; if (l < 0) { if (!e.loop) return; l = 0; } g(l); }, handleIndicatorEvent: (l) => { e.trigger === "hover" && g(l); }, handleIndicatorClick: (l) => { e.trigger === "click" && g(l); }, getRealIndex: f }; } function W(e, m, s) { let n = null; const d = () => { n && (clearInterval(n), n = null); }, h = () => { e.autoplay && (d(), n = setInterval(() => { (!m.value || !e.pauseOnHover) && s(); }, e.interval)); }; return { startAutoPlay: h, stopAutoPlay: d, handleMouseEnter: () => { m.value = !0, e.pauseOnHover && d(); }, handleMouseLeave: () => { m.value = !1, e.autoplay && h(); } }; } const j = /* @__PURE__ */ V({ name: "Carousel", props: G, emits: ["change"], setup(e, { emit: m, slots: s }) { const n = x(!1), d = x(!1), h = x(null), c = A(() => { if (!s.default) return 0; const t = s.default(); return !t || t.length === 0 ? 0 : t.length === 1 && t[0].children && Array.isArray(t[0].children) ? t[0].children.length : t.length; }), f = x(e.loop ? Math.min(e.initialIndex + 1, c.value) : e.initialIndex), w = A(() => e.loop ? c.value + 2 : c.value), { next: g, prev: $, setActiveItem: b, handleIndicatorEvent: P, handleIndicatorClick: z, getRealIndex: l } = U(e, { emit: m, slots: s }, f, c, w, n), { startAutoPlay: v, stopAutoPlay: o, handleMouseEnter: k, handleMouseLeave: C } = W(e, d, g), I = A(() => -(f.value * 100) / w.value), S = A(() => ({ overflow: "hidden", position: "relative", height: e.height, width: "100%" })), B = A(() => { const t = e.direction === "horizontal"; return { display: "flex", // 循环模式需要额外的克隆项空间 height: t ? "100%" : `${w.value * 100}%`, width: t ? `${w.value * 100}%` : "100%", flexDirection: t ? "row" : "column", transition: n.value ? "transform 0.5s ease-in-out" : "none", transform: t ? `translateX(${I.value}%)` : `translateY(${I.value}%)` }; }), M = (t) => { const i = t === f.value, r = e.direction === "horizontal", a = 100 / w.value; return { // flex-basis 是相对于父容器(轨道)的主轴方向 // 水平模式:flex-basis 控制宽度,每个项目占轨道宽度的 (100/totalItemCount)% // 垂直模式:flex-basis 控制高度,每个项目占轨道高度的 (100/totalItemCount)% flex: `0 0 ${a}%`, // 确保另一个方向也占满 width: "100%", height: "100%", minWidth: r ? `${a}%` : "100%", minHeight: r ? "100%" : `${a}%`, position: "relative", overflow: "hidden", // 卡片模式的特殊样式 opacity: e.type === "card" ? i ? 1 : 0.5 : 1, transform: e.type === "card" ? i ? "scale(1)" : "scale(0.8)" : "scale(1)", transition: "all 0.5s ease-in-out", cursor: e.type === "card" ? "pointer" : "default" }; }, O = A(() => e.arrow === "never" ? !1 : e.arrow === "always" ? !0 : d.value), R = A(() => e.indicatorPosition !== "none" && c.value > 1); H(() => e.autoplay, (t) => { t && !d.value ? v() : o(); }), H(() => e.interval, () => { e.autoplay && !d.value && v(); }), X(() => { e.autoplay && v(); }), Y(() => { o(); }); const F = () => { if (!O.value || c.value <= 1) return null; const t = (r) => ({ position: "absolute", [e.direction === "horizontal" ? r === "prev" ? "left" : "right" : r === "prev" ? "top" : "bottom"]: "16px", [e.direction === "horizontal" ? "top" : "left"]: "50%", transform: e.direction === "horizontal" ? "translateY(-50%)" : "translateX(-50%)" }), i = e.direction === "horizontal" ? "horizontal" : "vertical"; return u(D, null, [u("button", { class: `carousel-arrow carousel-arrow-prev ${i}`, onClick: $, type: "button", style: t("prev") }, [u("span", { class: "icon" }, [N("‹")])]), u("button", { class: `carousel-arrow carousel-arrow-next ${i}`, onClick: g, type: "button", style: t("next") }, [u("span", { class: "icon" }, [N("›")])])]); }, E = () => { if (!R.value) return null; const t = e.indicatorPosition === "outside", i = c.value; return u("div", { class: `carousel-indicators ${t ? "outside" : ""}` }, [Array.from({ length: i }).map((r, a) => { const y = e.loop ? a + 1 : a, _ = f.value === y; return u("button", { key: a, type: "button", class: `carousel-indicator ${_ ? "active" : ""}`, onMouseenter: () => P(y), onClick: () => z(y), "aria-label": `Go to slide ${a + 1}` }, null); })]); }, L = () => { if (!e.showTitle || !s.default) return null; let t = s.default(); if (!t || t.length === 0) return null; t.length === 1 && t[0].children && Array.isArray(t[0].children) && (t = t[0].children); const i = l(f.value), r = t[i]; if (!r || !r.props) return null; const { label: a } = r.props; return a ? u("div", { class: "carousel-title-area", style: { textAlign: { left: "left", center: "center", right: "right" }[e.titleAlign] } }, [u("h3", null, [a])]) : null; }, T = () => { if (!s.default) return null; let t = s.default(); if (!t || t.length === 0) return null; t.length === 1 && t[0].children && Array.isArray(t[0].children) && (t = t[0].children); const i = []; if (e.loop && t.length > 1) { const r = t[t.length - 1]; i.push(u("div", { key: "clone-last", class: "carousel-item", style: M(0) }, [r])); } if (t.forEach((r, a) => { const y = e.loop ? a + 1 : a; i.push(u("div", { key: a, class: `carousel-item ${y === f.value ? "active" : ""}`, style: M(y), onClick: () => { e.type === "card" && y !== f.value && b(y); } }, [r])); }), e.loop && t.length > 1) { const r = t[0], a = t.length + 1; i.push(u("div", { key: "clone-first", class: "carousel-item", style: M(a) }, [r])); } return i; }; return () => u("div", { ref: h, class: "el-carousel", style: S.value, onMouseenter: k, onMouseleave: C }, [u("div", { class: "el-carousel__track", style: B.value }, [T()]), F(), e.indicatorPosition === "inside" && E(), e.indicatorPosition === "outside" && E(), L()]); } }), Q = J(j); export { j as FCarouselComponent, G as carouselProps, Q as default };