Schema-driven panels
The editor must not know what destroyable means — only how to render an
editor for it from a description. Same for a tool's options. So there is one
renderer, JSON Schema in, SVG UI widgets out, and it serves both.
const panel = schemaPanel({
schema: turretSchema,
values: piece.features.turret,
handleChange: (key, value) => edit(`turret ${key}`, () => { ... }),
})
Two hand-rolled panels would drift apart inside a week — the tool panel would grow a nicer number field, the property panel would grow a better label, and neither would get the other. Building it once is also what makes a consumer's feature a first-class citizen: it renders because it has a schema, not because someone added a case for it.
Widget mapping
| schema | widget |
|---|---|
number with minimum/maximum |
slider3d |
boolean |
toggle3d |
string with enum |
select3d |
string |
inputField (an SVG keyboard, so it works in a headset) |
x-unit joins the VALUE for a picker and the label otherwise, because a number
without its unit is how a
range of 260 metres gets typed into a field that wanted kilometres.
Anything unrecognised renders as a disabled label showing the value, not nothing: a field an author cannot see is a field they will assume is unset.