y-design-ssr
Version:
SSR component library of YUI with Vue3
389 lines (388 loc) • 10.5 kB
JavaScript
import { ref as d, reactive as J, defineComponent as F, createVNode as o, computed as S, onMounted as K, onUpdated as Q, nextTick as X, onUnmounted as Z, createTextVNode as ee } from "vue";
const te = (e) => (n) => Object.prototype.toString.call(n) === `[object ${e}]`, ne = te("Number"), _ = (e, n) => n ? typeof n == "string" ? ` ${e}--${n}` : Array.isArray(n) ? n.reduce((i, l) => i + _(e, l), "") : Object.keys(n).reduce(
(i, l) => i + (n[l] ? _(e, l) : ""),
""
) : "", ae = (e) => (n, i) => {
let l = n, f = i;
return l && typeof l != "string" && (f = l, l = ""), l = l ? `${e}__${l}` : e, `${l}${_(l, f)}`;
}, le = () => (e, n) => n ? `${_(`y-${e}`, n)}` : `y-${e}`, re = {
"pull-refresh": {
pulling: "下拉刷新...",
loosing: "释放刷新...",
loading: "数据加载中...",
success: "数据已更新",
failed: "数据跟新失败,请稍后再试"
},
"form-item": {
validateMessage: "请输入正确内容"
}
};
d("zh-CN");
J({
"zh-CN": re
});
const P = (e) => {
const n = `y-${e}`;
return [n, ae(n), le()];
}, H = (e) => isNaN(Number(e)) && typeof e == "string" ? e : `${e}px`, ie = (e) => {
switch (e) {
case "top":
return "column-reverse";
case "bottom":
return "column";
case "left":
return "row-reverse";
case "right":
return "row";
default:
return "column";
}
}, [oe, R] = P("loading"), ue = {
// Loading icon 的颜色
color: {
type: String,
default: ""
},
// 背景色
bgColor: {
type: String,
default: ""
},
bgBorderRadius: {
type: [Number, String],
default: "16px"
},
// 粗细
thick: {
type: [Number, String],
default: 8
},
// 方向
direction: {
type: String,
default: "forward"
},
// 大小
size: {
type: [Number, String],
default: "24px"
},
padding: {
type: [Number, String],
default: ""
},
// 文案
text: {
type: String,
default: ""
},
// 文案位置
textLocation: {
type: String,
default: "bottom"
},
// 文案大小
textSize: {
type: [Number, String],
default: ""
},
// 文案颜色
textColor: {
type: String,
default: ""
},
// 布局位置
position: {
type: String,
default: "relative"
}
}, ce = /* @__PURE__ */ F({
name: oe,
props: ue,
setup(e, {
slots: n
}) {
return () => {
var w, B;
const {
position: i,
textLocation: l,
bgColor: f,
bgBorderRadius: m,
size: u,
padding: x,
color: v,
thick: T,
direction: C,
text: s,
textColor: p,
textSize: r
} = e, k = ((w = n.default) == null ? void 0 : w.call(n)) || s;
return o("div", {
class: R({
[i]: i !== "relative"
})
}, [o("div", {
class: R("bg", {
[i]: i !== "relative"
}),
style: {
flexDirection: ie(l),
backgroundColor: f,
borderRadius: H(m),
padding: H(x)
}
}, [o("span", {
class: R("icon-wrapper"),
style: {
width: H(u),
height: H(u)
}
}, [((B = n.icon) == null ? void 0 : B.call(n)) || o("svg", {
class: R("icon", {
[C]: C
}),
viewBox: "25 25 50 50"
}, [o("circle", {
class: R("icon-circle"),
style: {
stroke: v,
strokeWidth: H(T)
},
cx: "50",
cy: "50",
r: "20",
fill: "none"
}, null)])]), k && o("span", {
class: R("text", {
[l]: l
}),
style: {
color: p,
fontSize: H(r)
}
}, [k])])]);
};
}
}), [se, h] = P("list"), de = /* @__PURE__ */ F({
name: se,
props: {
// 加载中 文案
loadingText: {
type: String,
default: "加载中..."
},
// 加载完成 文案
finishedText: {
type: String,
default: "没有更多了~"
},
// 加载失败 文案
errorText: {
type: String,
default: "请求失败,点击重新加载"
},
// 容器高度
height: {
type: [Number, String],
default: "auto"
},
// 唯一键名称
keyName: {
type: String,
default: "_index"
},
// 列表数组
dataSource: {
type: Array,
default: () => []
},
// 是否在初始化时立即执行滚动位置检查
immediateCheck: {
type: Boolean,
default: !0
},
// 滚动条与底部距离小于多少时触发加载
loadOffset: {
type: Number,
default: 300
},
// 是否使用虚拟列表
virtual: {
type: Boolean,
default: !1
},
// 缓冲区比例
bufferScale: {
type: Number,
default: 1
},
// 列表子项预估高度
itemHeight: {
type: [String, Number],
default: "80"
},
// 是否是不定高度子项
dynamicItemHeight: {
type: Boolean,
default: !1
}
},
emits: ["load"],
setup(e, {
slots: n,
emit: i,
expose: l
}) {
const f = d(0), m = d(!1), u = d("normal"), x = d(), v = d(), T = d(), C = d([]), s = d(0), p = d(0), r = d([]), k = S(() => ne(e.height) ? `${e.height}px` : e.height), w = S(() => r.value.length ? r.value[r.value.length - 1].bottom : 0), B = S(() => {
if (e.virtual) {
const t = s.value - M.value, a = p.value + V.value;
return E.value.slice(t, a);
}
return E.value;
}), M = S(() => Math.min(s.value, e.bufferScale * $.value)), V = S(() => Math.min(e.dataSource.length - p.value, e.bufferScale * $.value)), $ = S(() => Math.ceil(f.value / parseInt(String(e.itemHeight)))), E = S(() => e.dataSource.map((t, a) => (t[e.keyName] = a, t))), A = () => m.value ? document.documentElement.scrollTop || document.body.scrollTop : x.value.scrollTop, G = () => m.value ? document.documentElement.scrollHeight : x.value.scrollHeight, L = () => {
u.value !== "loading" && (u.value = "loading", i("load", (t) => {
if (u.value === "loading")
switch (t) {
case "error":
u.value = "error";
break;
case "finished":
u.value = "finished", e.virtual && D(), e.virtual && e.dynamicItemHeight && j();
break;
default:
u.value = "normal", e.virtual && (j(), e.dataSource.length < $.value + V.value && L());
}
}));
}, z = () => {
u.value === "normal" && G() - A() - f.value <= e.loadOffset && L();
}, D = () => {
r.value = E.value.map((t, a) => {
const c = parseInt(String(e.itemHeight));
return {
index: a,
height: c,
top: a * c,
bottom: (a + 1) * c
};
});
}, j = () => {
D();
for (let t = 1; t < r.value.length; t++)
r.value[t].top = r.value[t - 1].bottom, r.value[t].bottom = r.value[t].top + r.value[t].height;
}, W = (t, a) => {
let c = 0, N = t.length - 1, g = -1;
for (; c <= N; ) {
const y = Math.floor((c + N) / 2), b = t[y].bottom;
if (b === a)
return y + 1;
b < a ? c = y + 1 : b > a && ((g === -1 || g > y) && (g = y), N = y - 1);
}
return g;
}, Y = (t) => W(r.value, t), O = () => {
if (z(), e.virtual) {
const t = A();
U(t);
}
}, U = (t) => {
if (!v.value)
return;
const a = t || 0;
if (e.dynamicItemHeight) {
s.value = Y(a), p.value = s.value + $.value;
const c = r.value[s.value - M.value].top ? r.value[s.value - M.value].top : 0;
v.value.style.transform = `translate3d(0, ${c}px, 0)`;
} else {
s.value = Math.floor(a / parseInt(String(e.itemHeight))), p.value = s.value + $.value;
const c = s.value * parseInt(String(e.itemHeight)) - M.value * parseInt(String(e.itemHeight));
v.value.style.transform = `translate3d(0, ${c}px, 0)`;
}
}, q = () => {
if (!v.value || !T.value)
return;
const t = v.value.children;
t && t.length > 0 && [...t].forEach((a) => {
if (a instanceof HTMLDivElement) {
const c = a.getBoundingClientRect(), {
height: N
} = c, g = Number(a.dataset.index), b = r.value[g].height - N;
if (b) {
r.value[g].bottom -= b, r.value[g].height = N;
for (let I = g + 1; I < r.value.length; I++)
r.value[I].top = r.value[I - 1].bottom, r.value[I].bottom -= b;
}
}
});
};
return l({
...e,
checkIsScrollToBottom: z,
loadData: L
}), K(() => {
e.height !== "auto" ? (m.value = !1, f.value = x.value.clientHeight) : e.height === "auto" && (m.value = !0, f.value = document.documentElement.clientHeight, document.addEventListener("scroll", O)), e.virtual && (D(), U()), e.immediateCheck && z();
}), Q(async () => {
var t, a;
if (e.virtual && e.dynamicItemHeight) {
if (await X(), !((a = (t = v.value) == null ? void 0 : t.children) != null && a.length))
return;
q();
}
}), Z(() => {
m.value && document.removeEventListener("scroll", O);
}), () => o("div", {
ref: x,
class: `${h()} ${e.virtual ? h({
virtual: !0
}) : ""}`,
style: {
height: k.value
},
onScroll: O
}, [e.virtual && o("div", {
ref: T,
class: h("phantom"),
style: {
height: `${w.value}px`
}
}, null), o("div", {
ref: v,
class: h("content")
}, [B.value.map((t) => {
var a;
return o("div", {
ref: C,
class: h("item"),
"data-index": t._index
}, [(a = n.default) == null ? void 0 : a.call(n, {
item: t
})]);
})]), u.value === "loading" && o("div", {
class: h({
loading: !0
})
}, [n.loading ? n.loading() : o(ce, {
"text-location": "right"
}, {
default: () => [ee("加载中...")]
})]), u.value === "finished" && o("div", {
class: h({
finished: !0
})
}, [e.finishedText]), u.value === "error" && o("div", {
class: h("error"),
role: "presentation",
onClick: L
}, [e.errorText])]);
}
});
function fe(e) {
const n = e;
return n.install = (i) => {
const { name: l } = e;
l && i.component(l, e);
}, n;
}
const ge = fe(de);
export {
ge as default
};