feat(ui): min(), max() and clamp(); insets as percentages of the containing block
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
355201f094
commit
12f4ba8431
13 changed files with 150 additions and 21 deletions
48
packages/ludic.ui/calc_fns.ludic
Normal file
48
packages/ludic.ui/calc_fns.ludic
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# calc_fns.ludic - min(a, b, ...), max(a, b, ...) and clamp(least, want, most) over lengths or plain
|
||||
# numbers, inside calc() or on their own. Comparing needs a length: a percentage there has no room yet.
|
||||
# the function a value starts with at `at` (calc, min, max or clamp), or ""
|
||||
function ca_fn_at(s: string, at: int) -> string {
|
||||
if ca_word(s, at, "calc(") { return "calc" }
|
||||
if ca_word(s, at, "min(") { return "min" }
|
||||
if ca_word(s, at, "max(") { return "max" }
|
||||
if ca_word(s, at, "clamp(") { return "clamp" }
|
||||
return ""
|
||||
}
|
||||
function ca_word(s: string, at: int, w: string) -> bool { return at + len(w) <= len(s) and s[at..at + len(w)] == w }
|
||||
function ca_fn(f: string) -> CaVal {
|
||||
ca_i = ca_i + len(f) + 1
|
||||
let args = new []CaVal
|
||||
while ca_bad == "" {
|
||||
push(args, ca_sum())
|
||||
ca_ws()
|
||||
if ca_i < len(ca_s) and ca_s[ca_i] == 44 { ca_i += 1 } else { break }
|
||||
}
|
||||
if ca_bad == "" and (ca_i >= len(ca_s) or ca_s[ca_i] != 41) { ca_bad = "a closing )" }
|
||||
ca_i += 1
|
||||
if ca_bad != "" { return new CaVal }
|
||||
if f == "clamp" and len(args) != 3 {
|
||||
ca_bad = "clamp(least, want, most)"
|
||||
return new CaVal
|
||||
}
|
||||
for i in 0 .. len(args) {
|
||||
if args[i].pct != 0.0 {
|
||||
ca_bad = `lengths in {f}(), not a percentage`
|
||||
return new CaVal
|
||||
}
|
||||
}
|
||||
if f == "clamp" { return ca_pick(ca_pick(args[1], args[0], false), args[2], true) }
|
||||
var r = args[0]
|
||||
for i in 1 .. len(args) { r = ca_pick(r, args[i], f == "min") }
|
||||
return r
|
||||
}
|
||||
# the smaller (or the larger) of two, a bare number beside a length being px
|
||||
function ca_pick(a: CaVal, b: CaVal, smaller: bool) -> CaVal {
|
||||
if a.bare and b.bare {
|
||||
if (b.n < a.n) == smaller and b.n != a.n { return b }
|
||||
return a
|
||||
}
|
||||
let la = ca_len(a)
|
||||
let lb = ca_len(b)
|
||||
if (lb.px < la.px) == smaller and lb.px != la.px { return lb }
|
||||
return la
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue