Purpose-built parameter controls that feel right. Miniature app helper, not app settings replacer.
docs/axes.md— theme axesdocs/themes.md— foundational themesdocs/options.md— panel optionsdocs/controls.md— control typesdocs/signals.md— signals pattern
- If unclear or missing, ask. Do not guess.
- Prefer deletion over expansion.
- If not written, it is undecided.
- Never apply symptomatic fixes (disabling, hiding, workarounds). Find and fix root cause.
/control/*— controls./control/control.jsis base wrapper./theme/*—theme(axes?) → CSS string. Peers, not hierarchy./index.js— settings(), infer(), register().
Controls are signal decorators: factory(sig, opts) → sig with .el, [Symbol.dispose].
control.jswraps template with label/hint/title structure, mounts, handles dispose- Controls pass state explicitly:
value: sig, set: v => { sig.value = v } - No implicit injection — control.js knows nothing about value/set
- Sprae auto-unwraps signals in templates.
:valueis two-way for inputs.
Panel flow: settings() → theme <style> + panel el + root folder + onchange effect
- Folder is self-sufficient: imports infer, receives controls registry
- Folder state is
sprae/store— reactive proxy, one signal per prop - Controls receive store's internal signals directly
- onchange wired at settings() level via single effect
Theme: theme(axes?) → CSS string → <style>. Nested CSS. Axes control intent, theme computes implementation.