Internal helpers
The functions the catalogue calls on itself. They are documented so the file reads end to end, not because they are API — copy eui_builders.sl into your application and they are yours to rename.
node(kind, style, children)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
return node("box", flat, children)
Real use — app/controllers/tracker_controller.sl:852
editable(kind, value, on_change, o)
What both of them are. The border is reserved at rest and only coloured later, for the reason `button_variant` gives below: a border that appears when a value goes wrong would shove every field under it sideways. Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
editable("input", value, on_change, o)
Real use — eui_builders.sl (inside `input`):138
space_px(ix, density)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
inner = erp_content_px(lay) - 2 * space_px(lay["wide"] ? 6 : 4, lay["density"]) - 2 * space_px(5, lay["density"])
Real use — app/controllers/live_controller.sl:808
bp_px(name)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
width >= bp_px(name)
Real use — eui_builders.sl (inside `bp_min`):235
bp_min(width, name)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
wide = bp_min(w, "md")
Real use — app/controllers/tracker_controller.sl:1358
restyle(n, patch)
Narrowing a widget after it is built only reaches its resting style: the hover and pressed styles are declared inside the local handlers, where a `n["s"]["pad"] = …` cannot see them. The pointer then snaps the node back to the catalogue's geometry, which is the same layout shift as a border that onl Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
return restyle(
Real use — app/controllers/tracker_controller.sl:928
size_spec(size)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
m = size_spec(size)
Real use — eui_builders.sl (inside `control_metrics`):383
control_metrics(size)
Box geometry only. The text scale is not here: `size` styles a text node, and only `fg` inherits, so a label takes its size from `control_text_size`. Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
base = control_metrics(size).merge({
Real use — eui_builders.sl (inside `control`):482
control_text_size(size)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
"size": control_text_size(size),
Real use — eui_builders.sl (inside `checkbox`):634
checkbox_box_px(size)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
box = checkbox_box_px(size)
Real use — eui_builders.sl (inside `checkbox`):592
control_px(size, density)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
Defined but never called in the catalogue — dead code as it stands.
tone_resting(tone, lit)
Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
base = base.merge(tone_resting(tone, lit))
Real use — eui_builders.sl (inside `control`):491
a11y_props(o)
The semantics a widget declares about itself. Props are a generic bag the client already reads by name, so these cost no wire change and an older client ignores them; what they buy is a checkbox that reaches a screen reader as a checkbox rather than as a button named by its label. Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
props = a11y_props(o)
Real use — eui_builders.sl (inside `control`):503
stateful(base, tone, on)
Wire the four pointer events onto an already-final resting style. `base` must be the style the node actually carries — the deltas are merged over it, so whatever the caller changed is already inside every state. Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
built["on"] = here ? {"click": "go_room"} : stateful(resting, {
Real use — app/controllers/chat_controller.sl:1590
control(o)
One options hash, so a widget gains a capability without its callers changing: key required and unique. 07 §3 names a node by key and the arena's key map is flat, so a duplicate silently restyles someone else. kind "box" by default. tone a TONES name; "quiet" by default. size " Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
control({
Real use — eui_builders.sl (inside `checkbox`):619
lazy(id, shown, placeholder, make)
A dialog is a stack: a dimming overlay, then the panel, centred. A region of the tree that is built only when something asks for it. `make` is a thunk — `fn() { ... }` — and it is not called at all unless `id` is in `shown`. That is the whole mechanism: an unopened modal, an unselected tab and a co Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
[lazy("forecast", shown, placeholder, fn() { erp_forecast_body(state, lay) })]
Real use — app/controllers/live_controller.sl:1194
chip_remove(on_remove, props, label)
The × that drops a chip. A button carries its hover and press styles with it, so reusing one here and narrowing only the live style let the × jump back to a button's padding under the pointer. This one is a fixed box: what changes on hover is the colour, which 03 §5 animates without ever running lay Internal to the catalogue — it composes part of a widget rather than being called from a view. Documented so the file reads end to end; treat it as implementation detail.
parts = parts.concat([chip_remove(on_remove, props, label)]) if on_remove.present?
Real use — eui_builders.sl (inside `chip`):1742