- 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>
53 lines
1.9 KiB
Text
53 lines
1.9 KiB
Text
# cascade_merge.ludic - a component's root is styled by its own sheet and by the sheet of every user
|
|
# that passed a class down to it, all at once: the rules that match, from all of them, ordered by
|
|
# specificity as one sheet's are. On a tie the user's rule wins (the outermost user's last), as a
|
|
# later rule does. Then `order`, which rearranges a flex box's children without touching the tree.
|
|
function cs_merged(n: UiNode) -> void {
|
|
let rules = new []UiRule
|
|
let envs = new []UiEnv
|
|
let seen = new []UiSheet
|
|
if n.sheet != null { cs_gather(n, n.sheet, n.env, rules, envs, seen) }
|
|
for i in 0 .. len(n.ups) {
|
|
if n.ups[i].sheet != null { cs_gather(n, n.ups[i].sheet, n.ups[i].env, rules, envs, seen) }
|
|
}
|
|
for i in 0 .. len(rules) { cs_rule_in(n, rules[i], envs[i]) }
|
|
}
|
|
# a sheet's matching rules into the list, each after every rule at most as specific (stable)
|
|
function cs_gather(n: UiNode, sh: UiSheet, e: UiEnv, rules: []UiRule, envs: []UiEnv, seen: []UiSheet) -> void {
|
|
for i in 0 .. len(seen) {
|
|
if seen[i] == sh { return }
|
|
}
|
|
push(seen, sh)
|
|
for i in 0 .. len(sh.rules) {
|
|
let r = sh.rules[i]
|
|
if md_ok(r) and sel_match(r.sel, n) {
|
|
push(rules, r)
|
|
push(envs, e)
|
|
var j = len(rules) - 1
|
|
while j > 0 and rules[j - 1].spec > r.spec {
|
|
rules[j] = rules[j - 1]
|
|
envs[j] = envs[j - 1]
|
|
j -= 1
|
|
}
|
|
rules[j] = r
|
|
envs[j] = e
|
|
}
|
|
}
|
|
}
|
|
# CSS's order: the children placed by it, lowest first, the tree's order kept between equals
|
|
function cs_order(n: UiNode) -> void {
|
|
var any = false
|
|
for i in 0 .. len(n.children) {
|
|
if ly_order(n.children[i]) != 0 { any = true }
|
|
}
|
|
if not any { return }
|
|
for i in 1 .. len(n.children) {
|
|
let c = n.children[i]
|
|
var j = i
|
|
while j > 0 and ly_order(n.children[j - 1]) > ly_order(c) {
|
|
n.children[j] = n.children[j - 1]
|
|
j -= 1
|
|
}
|
|
n.children[j] = c
|
|
}
|
|
}
|