kopular 1.3.0 → 1.3.2

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/GUIDE.md CHANGED
@@ -25,6 +25,12 @@ hint — so running a separate build before it only adds a round-trip (the build
25
25
  well under a second). `ks check src/app.ks` type-checks without building, for when you only
26
26
  want the errors.
27
27
 
28
+ **A fresh `kp new` project's `src/` is exactly three files, all shown in this guide:**
29
+ `app.ks` (the block above), `counter.ks` (the `Counter` class under Components, plus
30
+ `using "kopular";`), and `counter.html` (its template, right below it). `index.html` already
31
+ maps every Kopular module and never needs editing. There's nothing else to discover — read
32
+ the task, then write your files.
33
+
28
34
  ## The language you need
29
35
 
30
36
  - `Type name = value;` for every local — no `let`/`var`, no inference on declarations.
@@ -102,9 +108,11 @@ class Counter : Component {
102
108
  <button (click)="Increment()">Count: {{ Count.Value }}</button>
103
109
  ```
104
110
 
105
- `state<T>` referenced directly in a template auto-subscribes — no manual `Subscribe`
106
- needed. State reached *indirectly* (through a method, or `this.SomeService.Count`) does
107
- need one: `this.SomeService.Count.Subscribe((v) => this.Update());` in the constructor.
111
+ A `state<T>` field the template reads auto-subscribes — no manual `Subscribe` needed —
112
+ whether it's named directly (`{{ Count.Value }}`) or read through the component's own
113
+ methods (`*for="Todo t of Visible()"`, `{{ CountText() }}`, followed transitively). Event
114
+ handlers don't count. State on *another* object does still need one:
115
+ `this.SomeService.Count.Subscribe((v) => this.Update());` in the constructor.
108
116
 
109
117
  **Template bindings**: `{{ expr }}` text, `[prop]="expr"` (real fields for
110
118
  `id`/`className`/`value`/`disabled`/`checked`; anything else is a plain attribute),
package/LLM.md CHANGED
@@ -451,11 +451,12 @@ class Counter : Component {
451
451
  component composition" below). Unlike `*if`/`*for`, it composes with either — `*for="Row
452
452
  r of Rows" *mount="r"` (one mounted child per loop item) is the headline case, not an
453
453
  error. See kopscript's own `LLM.md`/`README.md` for the full syntax.
454
- - A `state<T>` field declared directly on the class and referenced directly in the
455
- template (`Count` above) gets `Subscribe((v) => this.Update())` wired automatically —
456
- no manual `Subscribe` in the constructor for that field. State reached indirectly
457
- (through a method, or `this.SomeService.Count`) still needs a manual `Subscribe`, same
458
- as a hand-written `Render()` always has.
454
+ - A `state<T>` field declared on the class gets `Subscribe((v) => this.Update())` wired
455
+ automatically when the template reads it — directly (`Count` above) or through the
456
+ class's own methods a render-time binding calls, followed transitively
457
+ (`*for="Todo t of Visible()"`). Event handlers aren't followed. State on another object
458
+ (`this.SomeService.Count`) still needs a manual `Subscribe`, as does any hand-written
459
+ `Render()`.
459
460
  - **Two-way binding**: `[(value)]="Field"` desugars to `[value]="Field"` +
460
461
  `(input)="Field = e.target.value"` — `value` only, and `Field` must be a bare name or
461
462
  `this.Field` (see KopScript's own LLM.md `KS5017`/`KS5018` for the two rejected cases).
package/README.md CHANGED
@@ -33,8 +33,8 @@ Generating Kopular code with an AI coding assistant? Point it at **[`LLM.md`](./
33
33
  `.html` file — interpolation (`{{ }}`), event/property bindings (`(click)="..."`,
34
34
  `[prop]="..."`), and `*if`/`*for` structural directives — desugared by the KopScript
35
35
  compiler into the exact same code a hand-written `Render()` would produce, with
36
- automatic `Subscribe`/`Update()` wiring for `state<T>` fields referenced directly in the
37
- markup. See "Templates" below.
36
+ automatic `Subscribe`/`Update()` wiring for the `state<T>` fields the markup reads,
37
+ directly or through the component's own methods. See "Templates" below.
38
38
  - **Reactive state, no RxJS**: components hold `state<number>`/`state<string>`/... (a
39
39
  KopScript language feature — see the [KopScript](https://dev.azure.com/koppinator/Koppindependence/_git/KopScript)
40
40
  repo) and subscribe once, in their constructor, to call `Update()` on change. No
@@ -137,9 +137,8 @@ class Counter : Component {
137
137
 
138
138
  Both produce the same `Render()`, and can be mixed freely across a codebase — nothing
139
139
  about `Component`, `Update()`, or any other Kopular API differs between them. The manual
140
- `Subscribe` call is still exactly what you need the moment state is reached *indirectly*
141
- — through a method call, or through an injected service's own state
142
- (`this.Service.Count`, say) — which is why the real, production `Counter` on the
140
+ `Subscribe` call is still exactly what you need the moment state lives on *another*
141
+ object — an injected service's own state (`this.Service.Count`, say) — which is why the real, production `Counter` on the
143
142
  [KopularDemo](https://dev.azure.com/koppinator/Koppindependence/_git/KopularDemo) site
144
143
  (it injects a `CounterService` rather than holding `Count` itself) uses a template but
145
144
  still has one manual `Subscribe`. `*if`/`*for` in a template are covered under
package/bin/kp.mjs CHANGED
@@ -180,15 +180,8 @@ const COUNTER_KS_TEMPLATE = `using "kopular";
180
180
 
181
181
  class Counter : Component {
182
182
  public state<number> Count;
183
-
184
- constructor() : base() {
185
- this.Count = state(0);
186
- }
187
-
188
- public void Increment() {
189
- this.Count.Value = this.Count.Value + 1;
190
- }
191
-
183
+ constructor() : base() { this.Count = state(0); }
184
+ public void Increment() { this.Count.Value = this.Count.Value + 1; }
192
185
  template from "./counter.html";
193
186
  }
194
187
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kopular",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
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",
@@ -66,7 +66,7 @@
66
66
  "@types/jsdom": "^30.0.0",
67
67
  "@types/node": "^20.14.0",
68
68
  "jsdom": "^25.0.1",
69
- "kopscript": "^1.1.0",
69
+ "kopscript": "^1.2.0",
70
70
  "typescript": "^5.5.0",
71
71
  "vitest": "^4.1.11"
72
72
  },