diff --git a/src/App.svelte b/src/App.svelte index 4836b9b..7d5306c 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -56,6 +56,11 @@ if (activeLeafId === id) activeLeafId = null; } + // Bumped to force a full Pane unmount+remount when the tree's structure + // changes in a way the DOM-hide workaround can't simulate (specifically, + // when ALL panes have been closed and we need to render a fresh leaf). + let renderKey = $state(0); + // ---- tree mutation handlers (closures over tree $state) ----------------- function handleSplit(leafId: NodeId, orientation: Orientation) { const parent = findLeaf(tree, leafId); @@ -73,21 +78,45 @@ void killPane(paneId).catch((e) => console.warn("killPane failed:", e)); orch.paneIdByLeaf.delete(leafId); } - // Hide the closed pane's flex container and the adjacent gutter so the - // sibling pane visually fills the freed space. + + // DOM-hide the .side wrapping this leaf and the adjacent gutter so the + // sibling pane visually fills. If both sides of the parent split are + // now hidden, bubble up and hide that whole split too (recursive + // collapse — needed for nested closes). const leafEl = document.querySelector(`[data-leaf-id="${leafId}"]`); - const sideEl = leafEl?.closest(".side") as HTMLElement | null; - const splitEl = sideEl?.parentElement; - if (sideEl && splitEl) { + let sideEl = leafEl?.closest(".side") as HTMLElement | null; + while (sideEl) { sideEl.style.display = "none"; + const splitEl = sideEl.parentElement; + if (!splitEl) break; + // Hide the gutter in this split (only one). Array.from(splitEl.children).forEach((c) => { const child = c as HTMLElement; if (child.classList.contains("gutter")) child.style.display = "none"; }); + // If a sibling side is still visible, flex will auto-fill; we're done. + const visibleSiblings = Array.from(splitEl.children).filter((c) => { + const child = c as HTMLElement; + return ( + child.classList.contains("side") && + child.style.display !== "none" + ); + }); + if (visibleSiblings.length > 0) break; + // Otherwise, this whole split is empty — climb up and hide its parent side. + sideEl = splitEl.closest(".side") as HTMLElement | null; } - // Update tree state (used by broadcast routing, palette, persistence). + + // Update tree state for persistence / palette / broadcast routing. const next = closeLeaf(tree, leafId); - tree = next ?? newLeaf({ distro: defaultDistro }); + if (next === null) { + // Tree fully collapsed. The DOM-hide workaround can't simulate + // mounting a brand-new leaf, so force a clean remount via key bump. + tree = newLeaf({ distro: defaultDistro }); + renderKey += 1; + } else { + tree = next; + } clearActiveIf(leafId); } @@ -332,7 +361,9 @@
{#if ready} - + {#key renderKey} + + {/key} {/if}