feat(ui): ludic.ui grows toward HTML, CSS and React (Phase 0.U1-U4)
- Natives: ui_native(tag, measure, draw) makes an element the program draws itself; ui_fire runs its on-<event> with event.value. input, select and textarea have simple defaults. - React: - keyed <each>, <let>, <provide> context through components, <fragment>; - named slots, default props on <component>; - on-mount / on-unmount; - inline text inside text elements. - CSS: - custom properties and var(); - position relative/absolute/fixed with insets and z-index; - em/rem/vw/vh and @media; - wrapping text and ellipsis, overflow; - + and ~ combinators, :nth-child(an+b), :checked, :active. - Developing: errors with file:line, ui_errors(), ui_reload() keeping state, and an inspector-style ui_dump. - view fields infer the type of a literal or a named function's result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
66a2bc2214
commit
637d07400e
39 changed files with 42012 additions and 40795 deletions
|
|
@ -15,6 +15,14 @@ function sel_match(s: UiSel, n: UiNode) -> bool {
|
|||
if not sel_one(s, n) { return false }
|
||||
if s.prev == null { return true }
|
||||
if s.comb == 1 { return n.parent != null and sel_match(s.prev, n.parent) }
|
||||
if s.comb == 2 { return n.parent != null and n.index > 0 and sel_match(s.prev, n.parent.children[n.index - 1]) }
|
||||
if s.comb == 3 {
|
||||
if n.parent == null { return false }
|
||||
for i in 0 .. n.index {
|
||||
if sel_match(s.prev, n.parent.children[i]) { return true }
|
||||
}
|
||||
return false
|
||||
}
|
||||
var a = n.parent
|
||||
while a != null {
|
||||
if sel_match(s.prev, a) { return true }
|
||||
|
|
@ -62,13 +70,30 @@ function sel_pseudo_ok(p: string, arg: string, n: UiNode) -> bool {
|
|||
if p == "last-child" { return n.parent != null and n.index == len(n.parent.children) - 1 }
|
||||
if p == "only-child" { return n.parent != null and len(n.parent.children) == 1 }
|
||||
if p == "empty" { return len(n.children) == 0 and n.text == "" }
|
||||
if p == "root" { return n.parent == null or n.parent.tag == "" }
|
||||
if p == "nth-child" {
|
||||
let k = n.index + 1
|
||||
if arg == "odd" { return k % 2 == 1 }
|
||||
if arg == "even" { return k % 2 == 0 }
|
||||
return string(k) == arg
|
||||
}
|
||||
if p == "root" { return n.parent == null }
|
||||
if p == "checked" { return ui_attr_on(n, "checked") }
|
||||
if p == "active" { return n.hovered and fr_down_now }
|
||||
if p == "nth-child" { return sel_nth(arg, n.index + 1) }
|
||||
ui_err(`:{p}: there is no such pseudo-class here`)
|
||||
return false
|
||||
}
|
||||
# :nth-child(odd), (even), (3), (2n+1), (n+2), (-n+3): is the k-th child one of them
|
||||
function sel_nth(arg: string, k: int) -> bool {
|
||||
if arg == "odd" { return k % 2 == 1 }
|
||||
if arg == "even" { return k % 2 == 0 }
|
||||
var npos = -1
|
||||
for i in 0 .. len(arg) {
|
||||
if arg[i] == 110 { npos = i }
|
||||
}
|
||||
if npos < 0 { return string(k) == arg }
|
||||
var a = 1
|
||||
let head: string = arg[0..npos]
|
||||
if head == "-" { a = -1 } else if len(head) > 0 { a = int(el_num(head)) }
|
||||
var b = 0
|
||||
var tail = tpl_words(arg[npos + 1..len(arg)])
|
||||
if len(tail) > 0 and tail[0] == 43 { tail = tpl_words(tail[1..len(tail)]) }
|
||||
if len(tail) > 0 { b = int(el_num(tail)) }
|
||||
if a == 0 { return k == b }
|
||||
let d = k - b
|
||||
return d % a == 0 and d / a >= 0
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue