feat(lang): L11 views and templates - the UI is markup, not code
A `view Name { field = x; function q(..); on e(..) }` declaration is the one bridge between a
program and its UI: it writes view_<name>() -> UiView, whose model is a Value of every field and
whose call runs a query or an event by name.
ludic.ui is a template runtime:
- HTML-shaped XML screens and components, loaded at run time;
- {expression} bindings, if/else/each, props, slots, per-instance state;
- on-press / onclick actions (event, set, emit);
- component libraries (export="true", <import src as>).
Styling:
- stylesheets in <style> or importable .lss files (@import);
- CSS selectors (#id, .class, [attr=v], descendant and > combinators, :hover, :disabled,
:first-child, :last-child, :nth-child, :not) weighed by specificity;
- the box model and flex under CSS's property names.
Also:
- default parameters, and positional-then-named calls;
- Value gains a float kind;
- a function shadowing a runtime one is refused;
- an index is evaluated before the slice is read;
- runtime errors name the right file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
334469ef61
commit
66a2bc2214
64 changed files with 74806 additions and 63975 deletions
44
packages/ludic.ui/cascade.ludic
Normal file
44
packages/ludic.ui/cascade.ludic
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# cascade.ludic - once the frame's tree is built, every element is styled as a browser would:
|
||||
# the default sheet, then the file's rules from least to most specific, then its style="...", then
|
||||
# its own attributes. Then what is display: none leaves the tree.
|
||||
function cs_tree(n: UiNode) -> void {
|
||||
for i in 0 .. len(n.children) {
|
||||
let c = n.children[i]
|
||||
c.parent = n
|
||||
c.index = i
|
||||
}
|
||||
if n.tag != "" { cs_node(n) }
|
||||
for i in 0 .. len(n.children) { cs_tree(n.children[i]) }
|
||||
var shown = new []UiNode
|
||||
for i in 0 .. len(n.children) {
|
||||
if not n.children[i].hidden { push(shown, n.children[i]) }
|
||||
}
|
||||
n.children = shown
|
||||
}
|
||||
function cs_node(n: UiNode) -> void {
|
||||
cs_sheet(n, ua_sheet())
|
||||
if n.sheet != null { cs_sheet(n, n.sheet) }
|
||||
if n.style != null { cs_rule(n, n.style) }
|
||||
for i in 0 .. len(n.akeys) { el_apply(n, n.akeys[i], n.vals[i]) }
|
||||
}
|
||||
function cs_sheet(n: UiNode, sh: UiSheet) -> void {
|
||||
for i in 0 .. len(sh.rules) {
|
||||
if sel_match(sh.rules[i].sel, n) { cs_rule(n, sh.rules[i]) }
|
||||
}
|
||||
}
|
||||
function cs_rule(n: UiNode, r: UiRule) -> void {
|
||||
for j in 0 .. len(r.keys) { el_attr(n, r.keys[j], ui_eval(r.vals[j], n.env)) }
|
||||
}
|
||||
# what every element looks like before anyone styles it, as a browser's own sheet does
|
||||
const UA_LSS: string = "h1 { font-size: 32 } h2 { font-size: 26 } h3 { font-size: 22 } h4 { font-size: 19 } h5 { font-size: 16 } h6 { font-size: 14 } small { font-size: 13 } button { padding: 5 10 } hr { height: 1; width: fill; background: #808080; margin: 4 0 } scroll { width: fill; height: fill } img { width: 24; height: 24 }"
|
||||
var ua_sh: UiSheet = null
|
||||
function ua_sheet() -> UiSheet {
|
||||
if ua_sh != null { return ua_sh }
|
||||
let f = new UiFile
|
||||
f.path = "the default sheet"
|
||||
f.imp = new []UiFile
|
||||
f.own = new []UiRule
|
||||
lss_text(f, UA_LSS)
|
||||
ua_sh = sheet_of(f)
|
||||
return ua_sh
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue