Give a list its own tab instead of a comma line

A list property in the inspector was a single text field holding a comma
separated line -- unreadable past a handful of items, and it could not
carry anything but text. It becomes a button ("3 items") that opens a
sixth centre tab, where every item is a row built by the very widget the
inspector would build for that item kind.

The renderer was free: a PropertyDef of kind 'list' already carries
`items`, so item i becomes a synthetic def of that kind -- number, text,
boolean and colour rows appear without a new branch.

The way into the tab goes through the state (EditorState.listSlot,
openList(), event 'list'), like every other tab switch here; a tab may
not call showTab itself. ListSlot lives next to Selection rather than in
the tab folder, or state.ts would have to import upwards.

A row's handlers must not close over a snapshot of the list: they outlive
a commit, since the tab only rebuilds when the length changes, and the
second edited row would otherwise revive the value the first replaced.

showTab switched five `visible` lines by hand, where a sixth tab is
silently forgotten; it is a Record<CentreTab, Widget> now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-10 10:30:57 +02:00
1 parent 5a440ba433
commit e52e95c0e9
15 files changed
+750 -70

No files matched your search

+5
View File
@@ -223,6 +223,11 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
objectScreen: (id: string) => containerEditor.objectScreen(id),
dropPreview: () => containerEditor.dropInfo(),
},
list: {
info: () => editor.listEditor.debugInfo(),
/** Where an item's widget sits, so a check can click it – a number field has no findable text. */
fieldAt: (index: number) => editor.listEditor.fieldAt(index),
},
world: () => editor.worldSnapshot(),
playInfo: () => editor.playInfo(),
/** Behaviors running without Play (`Run in editor`), and how long they have been at it. */