t-fighting-design
Version:
Fighting design can quickly build interactive interfaces in vue3 applications, which looks good.
111 lines (110 loc) • 3.93 kB
JavaScript
import { defineComponent as G, ref as m, reactive as N, watch as I, nextTick as P, onMounted as $, onUnmounted as A, openBlock as W, createElementBlock as y, normalizeClass as B, normalizeStyle as E, Fragment as L, renderList as j, unref as q, renderSlot as F, createElementVNode as O } from "vue";
import { Props as R, Emits as U } from "./index4.js";
const V = ["src"], D = G({
name: "Waterfall"
}), X = /* @__PURE__ */ G({
...D,
props: R,
emits: U,
setup(H, { emit: M }) {
const i = H;
let h = i.cols;
const d = m(), u = N([]), _ = m("auto"), S = () => Math.random().toString(16).substring(2), b = m(0), x = m("0px");
I(
() => i.list.length,
(e) => {
e && setTimeout(() => {
p();
}, 0);
}
);
const T = async (e) => Promise.all(
e.map((t) => new Promise((n) => {
let o = new Image();
o.src = (t == null ? void 0 : t.src) || "", o.onload = () => {
n();
}, o.onerror = () => {
n();
};
}))
), p = (e = !0) => {
let t = d.value.clientWidth;
t = t - (Math.floor(t / i.minWidth) - 1) * parseInt(i.colGap), i.minWidth && (h = Math.floor(t / i.minWidth)), h !== Math.floor(d.value.clientWidth / i.minWidth) && (t = d.value.clientWidth - (Number(h) - 1) * parseInt(i.colGap)), b.value = h;
const n = t / Number(h) + "px";
x.value = n, t = d.value.clientWidth, u.length = 0, u.push(
...i.list.map((o) => ({
src: o.src,
_uuid: S(),
_order: 0,
_width: n,
_minWidth: i.minWidth + "px",
...o
}))
), P(async () => {
e && await T(u);
const o = d.value.querySelectorAll(".f-waterfall-box");
let w = Object.values(o).map((l, r) => ({
height: l.clientHeight,
index: r
}));
const f = Array(h).fill(0).map(() => []);
w = w.sort((l, r) => r.height - l.height), w.forEach((l) => {
f.reduce((s, a) => s.reduce((v, c) => v + ((c == null ? void 0 : c.height) || 0), 0) < a.reduce((v, c) => v + ((c == null ? void 0 : c.height) || 0), 0) ? s : a, f[0]).push({ ...l });
});
const z = f.reduce((l, r) => l.reduce((s, a) => s + ((a == null ? void 0 : a.height) || 0), 0) > r.reduce((s, a) => s + ((a == null ? void 0 : a.height) || 0), 0) ? l : r, f[0]);
_.value = z.reduce((l, r) => l + Number(r.height), 0) + "px", f.flat(1).reverse().forEach((l, r) => {
const s = u[(l == null ? void 0 : l.index) || 0];
s._order = r;
});
});
};
let g = null;
const C = () => {
g && clearTimeout(g), g = setTimeout(() => {
p(!1);
}, 10);
};
$(async () => {
window.onresize = C, p();
}), A(() => {
window.removeEventListener("resize", C);
});
const k = (e) => {
const t = e.target.clientHeight, n = Math.ceil(e.target.scrollTop), o = e.target.scrollHeight;
t + n === o && M("scroll-end");
};
return (e, t) => (W(), y("div", {
ref_key: "waterfall",
ref: d,
class: B(["f-waterfall", [`f-waterfall__${e.type}`]]),
style: E({
"--colCount": b.value,
"--colWidth": x.value,
height: e.type === "flex" ? _.value : "100%",
"--rowGap": e.rowGap,
"row-gap": e.rowGap,
"column-gap": e.colGap
}),
onScroll: k
}, [
(W(!0), y(L, null, j(q(u), (n, o) => (W(), y("div", {
key: `waterfall_${o}`,
class: "f-waterfall-box",
style: E({
order: e.type === "flex" && n._order,
minWidth: e.type === "flex" && n._minWidth,
width: e.type === "flex" && n._width
})
}, [
F(e.$slots, "default", { row: n }, () => [
O("img", {
src: n.src
}, null, 8, V)
])
], 4))), 128))
], 38));
}
});
export {
X as default
};