kopular 0.21.3 → 0.21.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LLM.md +14 -12
- package/README.md +21 -17
- package/package.json +2 -2
package/LLM.md
CHANGED
|
@@ -300,12 +300,12 @@ w.Bump(); // re-render + diff + patch
|
|
|
300
300
|
now returns (see `kopscript`'s own `LLM.md`) for a subscription made in the constructor.
|
|
301
301
|
A component built once at app startup and never removed (every `Router` page, most real
|
|
302
302
|
apps' top-level structure) never needs this at all.
|
|
303
|
-
- `Router`'s own outlet
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
-
|
|
308
|
-
|
|
303
|
+
- `Router`'s own outlet uses this mechanism too — `Render()` embeds the matched page via
|
|
304
|
+
`VElement.Mount`, not the older `AfterRender` pattern above (that migration landed once
|
|
305
|
+
this existed; a single, always-present slot never needed the reordering/removal part,
|
|
306
|
+
but there was no reason not to use the same real mechanism everywhere).
|
|
307
|
+
- Templates get the same capability via `*mount="expr"` — see `kopscript`'s own `LLM.md`
|
|
308
|
+
for the syntax; it desugars to exactly this `VElement.Mount` call.
|
|
309
309
|
- **Content projection (React's `children`/Angular's `<ng-content>`) needs no separate
|
|
310
310
|
mechanism** — pass a `() => VElement` into a child's constructor and call it from inside
|
|
311
311
|
its own `Render()`; it's invoked fresh every render and closes over the parent's `this`,
|
|
@@ -766,12 +766,14 @@ class CounterService {
|
|
|
766
766
|
of the tree's own data, not wired against a live DOM node until `Materialize`/`Patch`
|
|
767
767
|
runs) — an event Kopular doesn't have a named field for isn't reachable from `Render()`
|
|
768
768
|
at all yet.
|
|
769
|
-
- **A `Component` embedded via `AfterRender`/`Mount()` (imperative
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
769
|
+
- **A `Component` embedded via `AfterRender`/`Mount()` (imperative) is NOT the same as one
|
|
770
|
+
embedded via `VElement.Mount()` (declarative, part of the tree)** — only the latter gets
|
|
771
|
+
real reconciliation (patch in place, reorder, tear down); this includes `Router`'s own
|
|
772
|
+
outlet, which uses `VElement.Mount` internally, not the older `AfterRender` pattern. If
|
|
773
|
+
you find yourself calling `.Mount()`/`.Update()` on a child by hand from `AfterRender`
|
|
774
|
+
for anything that needs to be added, removed, or reordered, use
|
|
775
|
+
`VElement.Mount(component)` in `Render()` (or `*mount="expr"` in a template) instead —
|
|
776
|
+
see "Component" above.
|
|
775
777
|
|
|
776
778
|
## Does not exist
|
|
777
779
|
|
package/README.md
CHANGED
|
@@ -188,11 +188,12 @@ class RoutedApp : Component {
|
|
|
188
188
|
return VElement.Create("div");
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
//
|
|
194
|
-
//
|
|
195
|
-
//
|
|
191
|
+
// VElement.Mount(this.Nav) in Render() (see "Nested component composition"
|
|
192
|
+
// below) would work here too, but a single, always-present root slot has
|
|
193
|
+
// no reordering or removal to get right, so the older, simpler
|
|
194
|
+
// AfterRender is just as correct — it's called with the real DOM node
|
|
195
|
+
// Render()'s tree just became, once Mount()/Update() has actually
|
|
196
|
+
// materialized/patched it, here that's the container itself.
|
|
196
197
|
protected override void AfterRender(Element root) {
|
|
197
198
|
this.Nav.Mount(root);
|
|
198
199
|
}
|
|
@@ -245,10 +246,10 @@ nav.AddRoute("/dogs/:id", new DogPage(nav));
|
|
|
245
246
|
el.TextContent = "Dog #" + this.Nav.Param;
|
|
246
247
|
```
|
|
247
248
|
|
|
248
|
-
`Param` is a plain `string`, deliberately not `state<T>` — Router's own `
|
|
249
|
-
|
|
250
|
-
which re-runs that page's `Render()` (reading the fresh `Param`)
|
|
251
|
-
`Subscribe()` needed on it.
|
|
249
|
+
`Param` is a plain `string`, deliberately not `state<T>` — `Router`'s own `Render()` already
|
|
250
|
+
re-embeds the matched page into its outlet (via `VElement.Mount`) on every
|
|
251
|
+
`Navigate()`/`popstate`, which re-runs that page's `Render()` (reading the fresh `Param`)
|
|
252
|
+
with no extra step. No `Subscribe()` needed on it.
|
|
252
253
|
|
|
253
254
|
**More than one dynamic segment**, and a trailing **wildcard** segment, both work too —
|
|
254
255
|
read each by name via `Router.Params(name)` instead (`Param` above still holds the
|
|
@@ -493,11 +494,14 @@ must stop, not just outlive an app that was going to unload anyway. Removing a c
|
|
|
493
494
|
that itself mounted further children tears the *whole* subtree down, however many levels
|
|
494
495
|
deep — a middle component overriding its own `OnUnmount()` doesn't skip its children's.
|
|
495
496
|
|
|
496
|
-
`Router`'s own outlet
|
|
497
|
-
|
|
498
|
-
|
|
497
|
+
`Router`'s own outlet uses this mechanism too — its `Render()` embeds the matched page via
|
|
498
|
+
`VElement.Mount`, not the older `AfterRender`-based pattern still shown in "Router, and
|
|
499
|
+
deploying it" below for mounting the `Router` itself into an app's root container (a
|
|
500
|
+
single, always-present slot, where there's nothing this mechanism would add). Reach for
|
|
499
501
|
`VElement.Mount` for anything with real add/remove/reorder: a list of components, a modal
|
|
500
|
-
that comes and goes, anything genuinely dynamic.
|
|
502
|
+
that comes and goes, anything genuinely dynamic. A template gets the same capability via
|
|
503
|
+
`*mount="expr"` — see "Templates" in `kopscript`'s own README/LLM.md for the syntax; it
|
|
504
|
+
desugars to exactly this call.
|
|
501
505
|
|
|
502
506
|
## Content projection — a parent giving a child what to render
|
|
503
507
|
|
|
@@ -863,10 +867,10 @@ v1 / hobby-project scope, same as KopScript itself. `Update()` diffs and patches
|
|
|
863
867
|
live child Component can be embedded directly in a parent's own tree via
|
|
864
868
|
`VElement.Mount(child)` — see "Nested component composition" above — so a parent's
|
|
865
869
|
re-render really can create/patch/reorder/tear down nested children declaratively now,
|
|
866
|
-
closing what used to be documented here as the framework's biggest reconciliation gap.
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
+
closing what used to be documented here as the framework's biggest reconciliation gap. A
|
|
871
|
+
template (`.html`) embeds one too, via `*mount="expr"` (`kopscript@0.25.0`+), the same way
|
|
872
|
+
`*if`/`*for` embed structural logic — see "Templates" in `kopscript`'s own docs. A list
|
|
873
|
+
child (`Mounted` or plain) without a stable
|
|
870
874
|
`VElement.Id` still renders correctly across a reorder, but isn't guaranteed to keep the
|
|
871
875
|
same real DOM node (see "Structural directives" above). `Update()` called before `Mount()`
|
|
872
876
|
is a safe no-op — see `LLM.md`'s `Component` section for exactly when that happens
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kopular",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.4",
|
|
4
4
|
"description": "Kopular: a small component framework for KopScript — components, reactive state, constructor-injected services, routing, real compiled templates, and HTTP, with no DI container",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@types/jsdom": "^30.0.0",
|
|
63
63
|
"@types/node": "^20.14.0",
|
|
64
64
|
"jsdom": "^25.0.1",
|
|
65
|
-
"kopscript": "^0.
|
|
65
|
+
"kopscript": "^0.25.0",
|
|
66
66
|
"typescript": "^5.5.0",
|
|
67
67
|
"vitest": "^4.1.11"
|
|
68
68
|
},
|