A short list opened after a long one drew all its rows stacked on one point. The fault was not in the list tab: rebuild() handed the row stack to setContent() while it was still empty, so the content was sized to max(rows, viewport) = the viewport. The rows arrived after that, and for a short list the same formula yields the same height, so resize() saw no change and skipped layout(). A long list changes the height and never showed it. relayoutContent() now runs whenever the content changed, rather than leaning on resize()'s change detection - that detection is the wrong instrument for "the children moved". The list tab was the only affected caller: the panels use ListView, which positions its rows itself, and the inspector fills its body before setContent. Also drops the comma line under the list. Every section that can carry a list supplies openList, so the comma fallback in fieldFactory was unreachable; listToText/listFromText go with it. The list-value test now covers coerceListItem through coerceValue instead, so the boolean spelling stays guarded. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
39 lines
1.4 KiB
TypeScript
39 lines
1.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { ScrollContainer, Spacer, VStack } from '../../src/ui';
|
|
|
|
/** Row tops after a layout; an unlaid-out stack leaves every child at 0. */
|
|
const tops = (stack: VStack) => stack.children.map((c) => c.y);
|
|
|
|
describe('a scroll container told its content changed', () => {
|
|
it('lays out rows that leave the height pinned to the viewport', () => {
|
|
const scroll = new ScrollContainer();
|
|
scroll.resize(200, 300);
|
|
const rows = new VStack();
|
|
// The list tab hands over the stack before filling it, so the empty content is measured first
|
|
// and pinned to the viewport height.
|
|
scroll.setContent(rows);
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
|
|
// 60 < 300, so the content keeps the height it already had: `resize` alone would see no
|
|
// change and skip the layout, leaving all three rows stacked at the top.
|
|
scroll.relayoutContent();
|
|
expect(tops(rows)).toEqual([0, 20, 40]);
|
|
});
|
|
|
|
it('still lays out rows that make the content taller than the viewport', () => {
|
|
const scroll = new ScrollContainer();
|
|
scroll.resize(200, 50);
|
|
const rows = new VStack();
|
|
scroll.setContent(rows);
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
|
|
scroll.relayoutContent();
|
|
expect(tops(rows)).toEqual([0, 20, 40]);
|
|
expect(scroll.maxScroll).toBe(10);
|
|
});
|
|
});
|