ludic/packages/ludic.ui/build_class.ludic
Orkuncakilkaya 7d8f34de17 feat(ui): flex-shrink, text that wraps beside its siblings, calc(), order, and 0 as a size
- flex-shrink: a line whose children want more room than it has takes it back from those that
  shrink, in proportion to shrink times size and never below a min size, a fixed size or the
  content. A scroll box shrinks (and scrolls), and a box in a column shrinks as far as the scroll
  boxes inside it let it, so a list in a column takes the room its siblings leave with no height.
  `flex: grow shrink`, and `flex-shrink` by name.
- A row wider than its room measures its texts (and boxes without a width) again in the room the
  rest leave them, so a line wraps beside an icon.
- calc() with + - * / and brackets over px, %, em, rem, vw, vh, plain numbers and var(); a width
  or height keeps its percentage, taken of the room it is given. Lengths lists (padding, margin)
  keep a calc()'s spaces.
- `order` places a box's children without touching the tree.
- width: 0 and height: 0 are 0: an unset size is UI_AUTO now, not 0.
- A component root that is itself a component takes each user's class, style and id in turn (the
  outermost's id wins), and the rules of all their sheets are weighed by specificity together; a
  user's rule wins a tie. The parent's sheet used to override the child's whatever its specificity,
  and a middle component's sheet was lost.
- The default sheet lays .ui-track out as a row, so a range's fill is as tall as its track and a
  checked box's knob goes right; a range's thumb is centred on the fill's end.
- ui_boxes.ludic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:54:14 +03:00

49 lines
1.7 KiB
Text

# build_class.ludic - a Ludic component's instance built: the parent's attributes are its props (id,
# class and style go on its root element instead, styled by the parent's sheet as well as its own),
# its model is its props, state and fields, and its template reads nothing else
function bd_class(k: UiTpl, e: UiEnv, key: string, out: []UiNode) -> void {
let cls = k.cls
uc_load(cls)
let it = in_get(key, cls)
let props = Value.object()
for i in 0 .. len(k.keys) {
let a = k.keys[i]
if a != "class" and a != "style" and a != "id" { Value.put(props, a, ui_eval(k.vals[i], e)) }
}
cls.props(it.ptr, props)
let ce = env_new(null)
ce.model = cls.model(it.ptr)
ce.inst = it
ce.ctx = e.ctx
ce.slot = k
ce.slot_env = e
ce.on_names = k.on_keys
ce.on_acts = k.on_acts
ce.on_envs = new []UiEnv
for i in 0 .. len(k.on_keys) { push(ce.on_envs, e) }
lc_note(key, k.on_keys, k.on_acts, e)
let at = len(out)
let root = new []UiTpl
push(root, cls.root)
bd_kids(root, ce, key, out)
if len(out) > at { bd_pass_down(out[at], k, e) }
}
# <Card class="wide" style="margin: 4px" id="c"> puts those on the card's own root element; when that
# root is itself a component, each user in turn adds theirs (the outermost's id wins)
function bd_pass_down(n: UiNode, k: UiTpl, e: UiEnv) -> void {
let c = tpl_attr(k, "class")
if c != null {
let parts = lss_split(ui_eval_text(c, e), 32)
for i in 0 .. len(parts) {
if len(parts[i]) > 0 { push(n.classes, parts[i]) }
}
}
let id = tpl_attr(k, "id")
if id != null { n.id = ui_eval_text(id, e) }
let up = new UiPass
up.sheet = k.sheet
up.style = k.style
up.env = e
if n.ups == null { n.ups = new []UiPass }
push(n.ups, up)
}