From 487de9237b2eeebd90d4e8e1ff090f448b473619 Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 23 Nov 2024 13:00:36 +0800 Subject: [PATCH] Masonry: use MutationObserver instead - originally tricks with the reactive system --- src/platform/Masonry.tsx | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/platform/Masonry.tsx b/src/platform/Masonry.tsx index 7071cd8..969e5dd 100644 --- a/src/platform/Masonry.tsx +++ b/src/platform/Masonry.tsx @@ -5,10 +5,8 @@ import { type Ref, createRenderEffect, onCleanup, - children, createEffect, createSignal, - onMount, } from "solid-js"; import { Dynamic, type DynamicProps } from "solid-js/web"; import MasonryLayout from "masonry-layout"; @@ -20,7 +18,6 @@ type MasonryContainer = | Component<{ ref?: Ref; class?: string; - children?: JSX.Element; }>; type ElementOf = @@ -37,7 +34,10 @@ function forwardRef(value: T, ref?: Ref) { (ref as (value: T) => void)(value); } -function createMasonry(element: Element, options: () => MasonryLayout.Options) { +function createCompatMasonry( + element: Element, + options: () => MasonryLayout.Options, +) { const layout = new MasonryLayout(element, { initLayout: false, }); @@ -46,11 +46,21 @@ function createMasonry(element: Element, options: () => MasonryLayout.Options) { const size = createElementSize(element); + const treeMutObx = new MutationObserver(() => { + layout.reloadItems?.(); + }); + + onCleanup(() => treeMutObx.disconnect()); + createRenderEffect(() => { const opts = options(); layout.option?.(opts); }); + createRenderEffect(() => { + treeMutObx.observe(element, { childList: true }); + }); + createRenderEffect(() => { const width = size.width; // only tracking width layout.layout?.(); @@ -61,8 +71,6 @@ function createMasonry(element: Element, options: () => MasonryLayout.Options) { layout.layout?.(); }); } - - return layout; } const supportsCSSMasonryLayout = /* @__PURE__ */ CSS.supports( @@ -85,9 +93,7 @@ if (import.meta.env.VITE_PLATFROM_MASONRY_ALWAYS_COMPAT) { function MasonryCompat( oprops: DynamicProps & { class?: string }, ) { - const [props, rest] = splitProps(oprops, ["ref", "children", "class"]); - - const childrenComponents = children(() => props.children); + const [props, rest] = splitProps(oprops, ["ref", "class"]); return ( ( const [columnGap, setColumnGap] = createSignal(); - const layout = createMasonry(element, () => { + createCompatMasonry(element, () => { return { gutter: columnGap(), }; @@ -115,18 +121,9 @@ function MasonryCompat( setColumnGap(Number(colGap.slice(0, colGap.length - 2))); } }); - - createRenderEffect(() => { - childrenComponents(); // just tracks - setTimeout(() => { - layout.reloadItems?.(); - layout.layout?.(); - }, 0); - }); }} class={`Masonry CompatMasonry ${props.class || ""}`} {...rest} - children={childrenComponents} /> ); }