feat(lang): UI components as files - component Name { ... } beside Name.xml and Name.lss
The compiler turns a component declaration into: - a record of its props and state; - a constructor, a props setter, a model and a call; - a class, registered with ludic.ui at start. Its template and styles are read from beside it and compiled in, with @import inlined, and a missing template fails the build. In the runtime: - each mounted instance keeps its own props and state, and `set` in a template writes the state; - styles are scoped to the component; - class, style and id on a component's tag land on its root, styled by the parent's sheet too; - ui_reload re-reads a component's files from disk and keeps instances. The package's own module is now ludic_ui, so a program may call a directory of its own ui. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
637d07400e
commit
20d011f8e9
40 changed files with 62224 additions and 49996 deletions
45
packages/ludic.ui/build_class.ludic
Normal file
45
packages/ludic.ui/build_class.ludic
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# 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
|
||||
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) }
|
||||
if k.style != null { n.style2 = k.style }
|
||||
n.sheet2 = k.sheet
|
||||
n.env2 = e
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue