widget semantics
What a panel control IS, as well as how it draws. Every Widget3d may
say what it is through semantics(): a role (button, toggle, slider,
select, text box, …), its accessible NAME, its value, and how to set or
press it through its own path, exactly as a hand on it would. A panel's
widgets then read as a tree of named controls, which is what an agent's
tools, a screen reader's mirror and the panel name test all read.
import { controlTree, findControl, nameProblems } from 'tosijs-3d/widget-semantics'
const tree = panel.controls() // a Panel3d's rows, header and open popups
findControl(tree, 'Sky/time of day').node.set(18)
findControl(tree, 'Character/save…').node.activate()
nameProblems(tree) // [] when every control has a unique name
A control is addressed by its PATH: the names of the sections and groups
above it and its own, joined by /. Sections (label3d({ collapsible }))
are levels, and a closed section still lists its name (activate it to open
it, then read the tree again). A popup that is open is a level named after
the control that opened it.
Names. A control's own label first. A control with none (an input field)
takes the label beside it in the same row, then its placeholder, then the
label or text just above it. An interactive control with no name, one named
only by a glyph (⋯), or two with the same path, is what nameProblems reports: icons first, but never
nameless.
Pure: no DOM, no Babylon. The widgets implement semantics(); this module
only reads it.