Split pane tree equalization logic

This commit is contained in:
Neil
2026-08-29 02:36:26 -07:00
parent 2ee53cb8d7
commit 4875b64293
3 changed files with 60 additions and 62 deletions
-1
View File
@@ -61,7 +61,6 @@ inline src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts
inline src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts
inline src/renderer/src/hooks/useAutomationDispatchEvents.ts
inline src/renderer/src/hooks/useSettingsNavigationMetadata.ts
inline src/renderer/src/lib/pane-manager/pane-tree-ops.ts
inline src/renderer/src/runtime/remote-runtime-terminal-multiplexer.ts
inline src/renderer/src/runtime/runtime-file-client.ts
inline src/renderer/src/runtime/sync-runtime-graph.ts
@@ -0,0 +1,59 @@
/** Find non-divider children (panes and splits) of an element. */
export function findPaneChildren(parent: HTMLElement): HTMLElement[] {
return Array.from(parent.children).filter(
(child): child is HTMLElement =>
child instanceof HTMLElement &&
(child.classList.contains('pane') || child.classList.contains('pane-split'))
)
}
function getSplitDirection(split: HTMLElement): 'vertical' | 'horizontal' {
return split.classList.contains('is-horizontal') ? 'horizontal' : 'vertical'
}
function getEqualizeWeight(el: HTMLElement, direction: 'vertical' | 'horizontal'): number {
if (!el.classList.contains('pane-split') || getSplitDirection(el) !== direction) {
return 1
}
const children = findPaneChildren(el)
return Math.max(
1,
children.reduce((sum, child) => sum + getEqualizeWeight(child, direction), 0)
)
}
export function equalizePaneSplitSizes(root: HTMLElement | null): boolean {
if (!root) {
return false
}
let changed = false
const visit = (el: HTMLElement): void => {
if (!el.classList.contains('pane-split')) {
return
}
const direction = getSplitDirection(el)
const children = findPaneChildren(el)
if (children.length >= 2) {
for (const child of children) {
// Why: same-axis nested splits need pane-count weighting so three
// side-by-side panes become thirds, not 50/25/25.
const weight = getEqualizeWeight(child, direction)
const nextFlex = `${weight} 1 0%`
if (child.style.flex !== nextFlex) {
child.style.flex = nextFlex
changed = true
}
}
}
for (const child of children) {
visit(child)
}
}
visit(root)
return changed
}
@@ -1,4 +1,3 @@
/* eslint-disable max-lines -- Why: split-tree DOM reparent, promote, and equalize rules need one consistent owner. */
import type {
DropZone,
ManagedPane,
@@ -16,6 +15,7 @@ export {
type SafeFitContinuationHandle
} from './pane-fit'
export { captureScrollState, restoreScrollState } from './pane-scroll'
export { equalizePaneSplitSizes, findPaneChildren } from './pane-tree-equalization'
// ---------------------------------------------------------------------------
// Split-tree manipulation: detach, insert, promote sibling
@@ -242,66 +242,6 @@ export function removeDividers(parent: HTMLElement): void {
}
}
/** Find non-divider children (panes and splits) of an element. */
export function findPaneChildren(parent: HTMLElement): HTMLElement[] {
return Array.from(parent.children).filter(
(child): child is HTMLElement =>
child instanceof HTMLElement &&
(child.classList.contains('pane') || child.classList.contains('pane-split'))
)
}
function getSplitDirection(split: HTMLElement): 'vertical' | 'horizontal' {
return split.classList.contains('is-horizontal') ? 'horizontal' : 'vertical'
}
function getEqualizeWeight(el: HTMLElement, direction: 'vertical' | 'horizontal'): number {
if (!el.classList.contains('pane-split') || getSplitDirection(el) !== direction) {
return 1
}
const children = findPaneChildren(el)
return Math.max(
1,
children.reduce((sum, child) => sum + getEqualizeWeight(child, direction), 0)
)
}
export function equalizePaneSplitSizes(root: HTMLElement | null): boolean {
if (!root) {
return false
}
let changed = false
const visit = (el: HTMLElement): void => {
if (!el.classList.contains('pane-split')) {
return
}
const direction = getSplitDirection(el)
const children = findPaneChildren(el)
if (children.length >= 2) {
for (const child of children) {
// Why: same-axis nested splits need pane-count weighting so three
// side-by-side panes become thirds, not 50/25/25.
const weight = getEqualizeWeight(child, direction)
const nextFlex = `${weight} 1 0%`
if (child.style.flex !== nextFlex) {
child.style.flex = nextFlex
changed = true
}
}
}
for (const child of children) {
visit(child)
}
}
visit(root)
return changed
}
/**
* Create a flex split wrapper that replaces `existingContainer` in the DOM,
* then places [existing] [divider] [new] inside it.