@farris/ui-vue
Version:
Farris Vue, a Farris Design based Vue3 component library.
213 lines (212 loc) • 7.49 kB
JavaScript
import { ref as y, onMounted as M, onUnmounted as U, onDeactivated as V, unref as R, nextTick as C, onActivated as j, computed as v, isRef as k, defineComponent as q, toRefs as z, watch as G, createVNode as d, Fragment as J } from "vue";
import { LocaleService as K } from "../locale/index.esm.js";
import { throttle as Q } from "lodash-es";
import { useBem as W } from "../common/index.esm.js";
const X = {
/** 是否处于加载状态,支持语法糖`v-model:loading`,此状态下将在列表底部显示加载中提示文本 */
loading: { type: Boolean, default: !1 },
/** 是否处于加载失败状态,支持语法糖`v-model:error`,此状态下将在列表底部显示加载失败提示文本,用户点击提示将触发加载事件 */
error: { type: Boolean, default: !1 },
/** 是否加载完成,加载完成后将在列表下方显示加载完成提示文本,且不会再触发加载事件 */
finished: { type: Boolean, default: !1 },
/** 是否自动触发加载事件,默认为`true`,当用户滑动到列表底部时,自动触发加载事件 */
autoLoadMore: { type: Boolean, default: !0 },
/** 滚动条与底部的距离小于等于`offset`(且`autoLoadMore=true`)时自动触发加载事件 */
offset: { type: [Number, String], default: 30 },
/** 是否在初始化时立即检查自动触发加载事件的条件,满足则自动触发加载事件 */
immediateCheck: { type: Boolean, default: !0 },
/** 是否禁用,禁用后不再触发加载事件 */
disabled: { type: Boolean, default: !1 },
/** 默认情况下滚动到底部触发加载,如果将本属性设为`up`则滚动到顶部时触发加载 */
direction: { type: String, default: "down" },
/** 加载更多提示文本 */
loadMoreText: { type: String, default: void 0 },
/** 加载中提示文本 */
loadingText: { type: String, default: void 0 },
/** 加载完成提示文本 */
finishedText: { type: String, default: void 0 },
/** 加载失败提示文本 */
errorText: { type: String, default: void 0 },
/** 是否显示加载完成提示文本,如果为`false`则忽略`finishedText`属性和`finished`插槽 */
showFinishedTip: { type: Boolean, default: !0 }
}, Z = /scroll|auto|overlay/i, N = typeof window < "u" ? window : void 0;
function $(e) {
return e.tagName !== "HTML" && e.tagName !== "BODY" && e.nodeType === 1;
}
function ee(e, r = N) {
let t = e;
for (; t && t !== r && $(t); ) {
const { overflowY: l } = window.getComputedStyle(t);
if (Z.test(l))
return t;
t = t.parentNode;
}
return r;
}
function te(e, r = N) {
const t = y();
return M(() => {
e.value && (t.value = ee(e.value, r));
}), t;
}
function oe(e) {
let r;
M(() => {
e(), C(() => {
r = !0;
});
}), j(() => {
r && e();
});
}
function ne(e, r, t = {}) {
let l = !1;
const { target: a = window, capture: o = !1, immediate: m = !1 } = t, { passive: g = !1 } = t, c = () => {
const s = R(a);
s && !l && (s.addEventListener(e, r, {
capture: o,
passive: g
}), l = !0);
}, u = () => {
const s = R(a);
s && l && (s.removeEventListener(e, r, o), l = !1);
};
m ? c() : oe(c), U(u), V(u);
}
const re = 30, le = (e, r) => {
const { containerRef: t, direction: l, offset: a } = e, o = y(!1), m = te(t), g = v(() => (k(l) ? l.value : l) || "down"), c = v(() => {
const f = k(a) ? +a.value : +(a || 0);
return f >= 0 ? f : re;
});
let u = !1;
const s = (f) => {
u || (u = !0, C(() => {
const i = f && f.target || m.value;
if (!i)
return;
const x = window.innerHeight, S = typeof i.scrollHeight == "number" ? i.scrollHeight : Math.max(document.documentElement.scrollHeight, document.body.scrollHeight), L = typeof i.offsetHeight == "number" ? i.offsetHeight : x, w = typeof i.scrollTop == "number" ? i.scrollTop : document.documentElement.scrollTop || document.body.scrollTop;
if (L <= 0)
return;
const E = S - w - L;
o.value = g.value === "up" ? w <= c.value : E <= c.value, o.value && r && r(), u = !1, e.onScroll && e.onScroll({ topDistance: w, bottomDistance: E });
}));
};
return M(() => {
ne("scroll", Q(s, 100), {
target: m,
passive: !0,
immediate: !0
});
}), {
isReachEdge: o,
check: () => s()
};
}, B = /* @__PURE__ */ q({
name: "FScrollList",
props: X,
emit: ["load", "update:error", "update:loading", "scroll"],
setup(e, r) {
const {
bem: t
} = W("FScrollList"), {
getLocaleValue: l
} = K, {
emit: a,
slots: o,
expose: m
} = r, g = y(), c = y(e.loading), u = () => {
c.value = !0, a("update:loading", !0), a("load");
}, s = v(() => e.autoLoadMore && !c.value && !e.finished && !e.disabled && !e.error), f = () => {
s.value && u();
}, {
direction: i,
offset: x
} = z(e), {
check: S
} = le({
containerRef: g,
direction: i.value,
offset: x.value,
onScroll: (n) => {
a("scroll", n);
}
}, f);
G(() => [e.loading, e.finished, e.error], () => {
c.value = e.loading, e.autoLoadMore && S();
});
const L = v(() => e.autoLoadMore && e.immediateCheck);
M(() => {
L.value && S();
});
const w = () => {
e.disabled || (e.error && a("update:error", !1), u());
}, E = () => {
var h;
const n = (h = o.header) == null ? void 0 : h.call(o);
if (n)
return d("div", {
class: t("header")
}, [n]);
}, D = () => {
var h;
const n = (h = o.footer) == null ? void 0 : h.call(o);
if (n)
return d("div", {
class: t("footer")
}, [n]);
}, O = () => {
if (!e.showFinishedTip)
return;
const n = o.finished ? o.finished() : e.finishedText;
if (n)
return d("div", {
class: t("finished-info")
}, [n]);
}, P = () => {
const n = o.loading ? o.loading() : d("div", {
class: t(["list", "loading-container"])
}, [d("span", {
class: "f-loading-round",
style: "width: 16px; height: 16px;"
}, null), d("span", null, [e.loadingText || l("scroll-list.loading")])]);
return d("div", {
class: t(["list", "loading"])
}, [n]);
}, A = () => {
const n = o.error ? o.error() : e.errorText;
if (n)
return d("div", {
role: "button",
class: t("error"),
tabindex: 0,
onClick: w
}, [n]);
}, I = () => {
const n = o.loadMore ? o.loadMore() : e.loadMoreText || l("scroll-list.loadMore");
return d("div", {
role: "button",
class: t("load-more"),
tabindex: 0,
onClick: w
}, [n]);
}, T = v(() => e.finished), b = v(() => c.value && !e.disabled && !T.value), F = v(() => e.error && !T.value && !b.value), _ = v(() => !e.autoLoadMore && !T.value && !b.value && !F.value), Y = () => d(J, null, [T.value && O(), b.value && P(), F.value && A(), _.value && I()]);
return m({
check: S
}), () => {
var H;
const n = (H = o.default) == null ? void 0 : H.call(o), h = i.value === "down", p = i.value === "up";
return d("div", {
ref: g,
class: t("list")
}, [E(), h && n, Y(), p && n, D()]);
};
}
});
B.install = (e) => {
e.component(B.name, B);
};
export {
B as FScrollList,
B as default,
X as listProps
};