UNPKG

@chahindb7/vue-masonry-wall

Version:

Responsive masonry layout with SSR support and zero dependencies for Vue 3 (modified by Chahin).

209 lines (208 loc) 5.71 kB
import { defineComponent as Y, ref as M, nextTick as F, onBeforeUnmount as H, onMounted as U, watch as q, toRefs as G, openBlock as p, createElementBlock as m, createElementVNode as _, toDisplayString as j, normalizeStyle as $, Fragment as A, renderList as C, unref as J, renderSlot as K, createTextVNode as P } from "vue"; function Q(n, l) { try { let o; return (...c) => { o !== void 0 && clearTimeout(o), o = setTimeout(() => n(...c), l); }; } catch (o) { console.error("Error debouncing", o); } } function X({ columns: n, columnWidth: l, emit: o, gap: c, items: u, maxColumns: i, minColumns: g, nextTick: s, onBeforeUnmount: b, onMounted: S, rtl: f, scrollContainer: a, ssrColumns: h, vue: L, wall: w, watch: k }) { function R(t, e, r, y) { try { const d = z(r); return y + e + d <= t ? R( t, e, r + 1, y + e + d ) : r; } catch (d) { console.error("Error counting iteratively", d); } } function z(t) { try { const e = Array.isArray(l.value) ? l.value : [l.value]; return e[t % e.length]; } catch (e) { console.error("Error getting column width target", e); } } function N() { try { const t = R( w.value.getBoundingClientRect().width, c.value, 0, // Needs to be offset my negative gap to prevent gap counts being off by one -c.value ), e = W(V(t)); return e > 0 ? e : 1; } catch (t) { console.error("Error getting column count", t); } } function V(t) { try { const e = i == null ? void 0 : i.value; return e && t > e ? e : t; } catch (e) { console.error("Error getting below max", e); } } function W(t) { try { const e = g == null ? void 0 : g.value; return e && t < e ? e : t; } catch (e) { console.error("Error getting above min", e); } } let B = 0; async function T(t, e) { try { if (t >= u.value.length || (await s(), B !== e)) return; const r = [...w.value.children]; f.value && r.reverse(); const y = r.reduce( (d, x) => x.getBoundingClientRect().height < d.getBoundingClientRect().height ? x : d ); n.value[+y.dataset.index].push(t), await T(t + 1, e); } catch (r) { console.error("Error filling columns", r); } } async function E(t = !1) { try { const e = N(); if (n.value.length === e && !t) { o(L === 2 ? "redraw-skip" : "redrawSkip"); return; } n.value = D(e); const r = a == null ? void 0 : a.value, y = r ? r.scrollTop : window.scrollY; await T(0, ++B), r && r instanceof HTMLElement && (r == null || r.scrollBy({ top: y - r.scrollTop })), o("redraw"); } catch (e) { console.error("Error redrawing", e); } } const v = typeof ResizeObserver > "u" ? void 0 : new ResizeObserver(Q(() => E())); if (S(() => { E(), v == null || v.observe(w.value); }), b(() => v == null ? void 0 : v.unobserve(w.value)), k([u, f], () => E(!0)), k([l, c, g, i], () => E()), h.value > 0) { console.log("Creating SSR columns"); try { const t = D(h.value); console.log("SSR columns created", t), u.value.forEach( (e, r) => t[r % h.value].push(r) ), console.log("SSR columns filled", t), n.value = [[0], [1], [2], []]; } catch (t) { console.error("Error creating SSR columns", t); } } return { getColumnWidthTarget: z }; } function D(n) { try { return Array.from({ length: n }).map(() => []); } catch (l) { return console.error("Error creating columns", l), []; } } const Z = { style: { "margin-bottom": "10px", color: "black" } }, O = ["data-index"], ee = /* @__PURE__ */ Y({ __name: "MasonryWall", props: { columnWidth: { default: 400 }, items: {}, gap: { default: 0 }, rtl: { type: Boolean, default: !1 }, ssrColumns: { default: 0 }, scrollContainer: { default: null }, minColumns: { default: 1 }, maxColumns: {}, keyMapper: {} }, emits: ["redraw", "redrawSkip"], setup(n, { emit: l }) { const o = n, c = l, u = M([]), i = M(); console.log("zjzzjzjzjzzj"); const { getColumnWidthTarget: g } = X({ columns: u, emit: c, nextTick: F, onBeforeUnmount: H, onMounted: U, vue: 3, wall: i, watch: q, ...G(o) }); return (s, b) => (p(), m("div", null, [ _("div", Z, j(u.value), 1), _("div", { ref_key: "wall", ref: i, class: "masonry-wall", style: $({ display: "flex", gap: `${s.gap}px` }) }, [ (p(!0), m(A, null, C(u.value, (S, f) => (p(), m("div", { key: f, class: "masonry-column", "data-index": f, style: $({ display: "flex", "flex-basis": `${J(g)(f)}px`, "flex-direction": "column", "flex-grow": 1, gap: `${s.gap}px`, height: [ "-webkit-max-content", "-moz-max-content", "max-content" ], "min-width": 0 }) }, [ (p(!0), m(A, null, C(S, (a, h) => (p(), m("div", { key: a, class: "masonry-item" }, [ K(s.$slots, "default", { item: s.items[a], column: f, row: h, index: a }, () => [ P(j(s.items[a]), 1) ]) ]))), 128)) ], 12, O))), 128)) ], 4) ])); } }); export { ee as default }; //# sourceMappingURL=vue-masonry-wall.es.js.map