j-templates 7.0.96 → 7.0.98

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.
Files changed (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +462 -0
  3. package/{SYNTAX_PRIMER.md → lib/SYNTAX_PRIMER.md} +93 -64
  4. package/lib/Store/Tree/observableNode.d.ts +83 -0
  5. package/{Store → lib/Store}/Tree/observableNode.js +43 -10
  6. package/{Store → lib/Store}/Tree/observableScope.d.ts +29 -0
  7. package/{Store → lib/Store}/Tree/observableScope.js +29 -0
  8. package/lib/package.json +13 -0
  9. package/package.json +28 -3
  10. package/Store/Tree/observableNode.d.ts +0 -43
  11. /package/{DOM → lib/DOM}/createAssignment.d.ts +0 -0
  12. /package/{DOM → lib/DOM}/createAssignment.js +0 -0
  13. /package/{DOM → lib/DOM}/createAttributeAssignment.d.ts +0 -0
  14. /package/{DOM → lib/DOM}/createAttributeAssignment.js +0 -0
  15. /package/{DOM → lib/DOM}/createEventAssignment.d.ts +0 -0
  16. /package/{DOM → lib/DOM}/createEventAssignment.js +0 -0
  17. /package/{DOM → lib/DOM}/createPropertyAssignment.d.ts +0 -0
  18. /package/{DOM → lib/DOM}/createPropertyAssignment.js +0 -0
  19. /package/{DOM → lib/DOM}/domNodeConfig.d.ts +0 -0
  20. /package/{DOM → lib/DOM}/domNodeConfig.js +0 -0
  21. /package/{DOM → lib/DOM}/elements.d.ts +0 -0
  22. /package/{DOM → lib/DOM}/elements.js +0 -0
  23. /package/{DOM → lib/DOM}/index.d.ts +0 -0
  24. /package/{DOM → lib/DOM}/index.js +0 -0
  25. /package/{DOM → lib/DOM}/svgElements.d.ts +0 -0
  26. /package/{DOM → lib/DOM}/svgElements.js +0 -0
  27. /package/{Node → lib/Node}/component.d.ts +0 -0
  28. /package/{Node → lib/Node}/component.js +0 -0
  29. /package/{Node → lib/Node}/component.types.d.ts +0 -0
  30. /package/{Node → lib/Node}/component.types.js +0 -0
  31. /package/{Node → lib/Node}/nodeConfig.d.ts +0 -0
  32. /package/{Node → lib/Node}/nodeConfig.js +0 -0
  33. /package/{Node → lib/Node}/vNode.d.ts +0 -0
  34. /package/{Node → lib/Node}/vNode.js +0 -0
  35. /package/{Node → lib/Node}/vNode.types.d.ts +0 -0
  36. /package/{Node → lib/Node}/vNode.types.js +0 -0
  37. /package/{Store → lib/Store}/Diff/diffAsync.d.ts +0 -0
  38. /package/{Store → lib/Store}/Diff/diffAsync.js +0 -0
  39. /package/{Store → lib/Store}/Diff/diffSync.d.ts +0 -0
  40. /package/{Store → lib/Store}/Diff/diffSync.js +0 -0
  41. /package/{Store → lib/Store}/Diff/diffTree.d.ts +0 -0
  42. /package/{Store → lib/Store}/Diff/diffTree.js +0 -0
  43. /package/{Store → lib/Store}/Diff/diffWorker.d.ts +0 -0
  44. /package/{Store → lib/Store}/Diff/diffWorker.js +0 -0
  45. /package/{Store → lib/Store}/Diff/workerQueue.d.ts +0 -0
  46. /package/{Store → lib/Store}/Diff/workerQueue.js +0 -0
  47. /package/{Store → lib/Store}/Store/store.d.ts +0 -0
  48. /package/{Store → lib/Store}/Store/store.js +0 -0
  49. /package/{Store → lib/Store}/Store/storeAsync.d.ts +0 -0
  50. /package/{Store → lib/Store}/Store/storeAsync.js +0 -0
  51. /package/{Store → lib/Store}/Store/storeSync.d.ts +0 -0
  52. /package/{Store → lib/Store}/Store/storeSync.js +0 -0
  53. /package/{Store → lib/Store}/index.d.ts +0 -0
  54. /package/{Store → lib/Store}/index.js +0 -0
  55. /package/{Utils → lib/Utils}/animation.d.ts +0 -0
  56. /package/{Utils → lib/Utils}/animation.js +0 -0
  57. /package/{Utils → lib/Utils}/asyncQueue.d.ts +0 -0
  58. /package/{Utils → lib/Utils}/asyncQueue.js +0 -0
  59. /package/{Utils → lib/Utils}/decorators.d.ts +0 -0
  60. /package/{Utils → lib/Utils}/decorators.js +0 -0
  61. /package/{Utils → lib/Utils}/emitter.d.ts +0 -0
  62. /package/{Utils → lib/Utils}/emitter.js +0 -0
  63. /package/{Utils → lib/Utils}/functions.d.ts +0 -0
  64. /package/{Utils → lib/Utils}/functions.js +0 -0
  65. /package/{Utils → lib/Utils}/index.d.ts +0 -0
  66. /package/{Utils → lib/Utils}/index.js +0 -0
  67. /package/{Utils → lib/Utils}/injector.d.ts +0 -0
  68. /package/{Utils → lib/Utils}/injector.js +0 -0
  69. /package/{Utils → lib/Utils}/json.d.ts +0 -0
  70. /package/{Utils → lib/Utils}/json.js +0 -0
  71. /package/{Utils → lib/Utils}/list.d.ts +0 -0
  72. /package/{Utils → lib/Utils}/list.js +0 -0
  73. /package/{Utils → lib/Utils}/router.d.ts +0 -0
  74. /package/{Utils → lib/Utils}/router.js +0 -0
  75. /package/{Utils → lib/Utils}/scheduling.d.ts +0 -0
  76. /package/{Utils → lib/Utils}/scheduling.js +0 -0
  77. /package/{Utils → lib/Utils}/thread.d.ts +0 -0
  78. /package/{Utils → lib/Utils}/thread.js +0 -0
  79. /package/{Utils → lib/Utils}/utils.types.d.ts +0 -0
  80. /package/{Utils → lib/Utils}/utils.types.js +0 -0
  81. /package/{_not_used → lib/_not_used}/array.d.ts +0 -0
  82. /package/{_not_used → lib/_not_used}/array.js +0 -0
  83. /package/{_not_used → lib/_not_used}/avlTree.d.ts +0 -0
  84. /package/{_not_used → lib/_not_used}/avlTree.js +0 -0
  85. /package/{index.d.ts → lib/index.d.ts} +0 -0
  86. /package/{index.js → lib/index.js} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 TypesInCode
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,462 @@
1
+ # j-templates
2
+
3
+ A type-safe, fine-grained reactive framework for building browser applications in TypeScript — with no compile step, no virtual DOM diffing, and no framework lock-in.
4
+
5
+ ## Why j-templates?
6
+
7
+ - **Fine-grained reactivity** — Updates propagate at the property level, not the component level. Only the DOM nodes that depend on changed state are touched.
8
+ - **Zero compile step** — Pure TypeScript with experimental decorators. Works with any bundler (Vite, Webpack, Rollup).
9
+ - **Object identity preservation** — `@Computed` uses diff-based updates so downstream consumers receive the same reference when data hasn't structurally changed, enabling efficient DOM reuse without key-based reconciliation.
10
+ - **Proxy-based deep reactivity** — `@State` wraps objects and arrays in reactive proxies. Nested property writes and array mutations (`push`, `splice`, etc.) are tracked automatically.
11
+ - **Hierarchical dependency injection** — Components resolve dependencies through a parent-chain injector, making it easy to share services across a component tree.
12
+ - **Minimal dependencies** — Zero runtime dependencies. Only TypeScript as a dev dependency.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install j-templates
18
+ ```
19
+
20
+ Requires `experimentalDecorators`, `emitDecoratorMetadata`, and `useDefineForClassFields: false` in your `tsconfig.json`:
21
+
22
+ ```json
23
+ {
24
+ "compilerOptions": {
25
+ "experimentalDecorators": true,
26
+ "emitDecoratorMetadata": true,
27
+ "useDefineForClassFields": false
28
+ }
29
+ }
30
+ ```
31
+
32
+ ## Hello World
33
+
34
+ ```typescript
35
+ import { Component } from "j-templates";
36
+ import { div } from "j-templates/DOM";
37
+
38
+ class HelloWorld extends Component {
39
+ Template() {
40
+ return div({}, () => "Hello world");
41
+ }
42
+ }
43
+
44
+ const helloWorld = Component.ToFunction("hello-world", HelloWorld);
45
+ Component.Attach(document.body, helloWorld({}));
46
+ ```
47
+
48
+ ## Module Structure
49
+
50
+ | Module | Import Path | Exports |
51
+ |---|---|---|
52
+ | Core | `j-templates` | `Component`, `scope`, `gate`, `peek`, `mapped` |
53
+ | DOM | `j-templates/DOM` | 70+ HTML element factories (`div`, `button`, `table`, …), `text`, `fragment` |
54
+ | Store | `j-templates/Store` | `StoreSync`, `StoreAsync`, `ObservableScope`, `ObservableNode` |
55
+ | Utils | `j-templates/Utils` | `@Value`, `@State`, `@Scope`, `@Computed`, `@ComputedAsync`, `@Watch`, `@Inject`, `@Destroy`, `Animation`, `IDestroyable` |
56
+
57
+ ## Reactive State
58
+
59
+ ### `@Value` — Primitive reactive property
60
+
61
+ ```typescript
62
+ import { Component } from "j-templates";
63
+ import { Value } from "j-templates/Utils";
64
+ import { div, button } from "j-templates/DOM";
65
+
66
+ class Counter extends Component {
67
+ @Value() count = 0;
68
+
69
+ Template() {
70
+ return div({}, () => [
71
+ button({ on: { click: () => this.count-- } }, () => "-"),
72
+ div({}, () => this.count),
73
+ button({ on: { click: () => this.count++ } }, () => "+"),
74
+ ]);
75
+ }
76
+ }
77
+ ```
78
+
79
+ ### `@State` — Deep reactive objects and arrays
80
+
81
+ ```typescript
82
+ import { State } from "j-templates/Utils";
83
+
84
+ class TodoList extends Component {
85
+ @State() items: string[] = [];
86
+
87
+ addItem(text: string) {
88
+ this.items.push(text); // Triggers reactive update automatically
89
+ }
90
+
91
+ removeItem(index: number) {
92
+ this.items.splice(index, 1); // Also tracked
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### `@Scope` — Computed value (new reference on change)
98
+
99
+ Best for cheap computations that return primitives or new arrays.
100
+
101
+ ```typescript
102
+ import { Scope } from "j-templates/Utils";
103
+
104
+ class Stats extends Component {
105
+ @Value() count = 0;
106
+
107
+ @Scope()
108
+ get doubled() { return this.count * 2; }
109
+ }
110
+ ```
111
+
112
+ ### `@Computed` — Computed value with object identity preservation
113
+
114
+ Best for expensive computations or when downstream consumers need stable references. Uses `StoreSync` + diff-based updates so the same object reference is returned when the structure hasn't changed.
115
+
116
+ ```typescript
117
+ import { Computed } from "j-templates/Utils";
118
+
119
+ class TodoApp extends Component {
120
+ @State() items: Todo[] = [];
121
+
122
+ @Computed()
123
+ get completedItems(): Todo[] {
124
+ return this.items.filter(t => t.done);
125
+ }
126
+ }
127
+ ```
128
+
129
+ ### `@Watch` — React to state changes
130
+
131
+ ```typescript
132
+ import { Watch, Value } from "j-templates/Utils";
133
+
134
+ class Logger extends Component {
135
+ @Value() message = "";
136
+
137
+ @Watch((self) => self.message)
138
+ onMessageChanged(newValue: string) {
139
+ console.log("message changed to:", newValue);
140
+ }
141
+ }
142
+ ```
143
+
144
+ ## Template System
145
+
146
+ Element functions accept a config object and children:
147
+
148
+ ```typescript
149
+ div({
150
+ props: () => ({ className: "card" }), // Reactive DOM properties
151
+ attrs: { "aria-label": "card" }, // Static HTML attributes
152
+ on: { click: () => handleClick() }, // Event handlers
153
+ data: () => this.items, // Reactive data source
154
+ }, children)
155
+ ```
156
+
157
+ ### Reactive children
158
+
159
+ Pass a function as the second argument to make children reactive:
160
+
161
+ ```typescript
162
+ div({}, () => `Count: ${this.count}`) // Re-renders when count changes
163
+ ```
164
+
165
+ ### List rendering with `data`
166
+
167
+ The `data` property drives iterative rendering. Each item is mapped to a child via a callback:
168
+
169
+ ```typescript
170
+ tbody({ data: () => this.items }, (item: Todo) =>
171
+ tr({}, () => [
172
+ td({}, () => item.text),
173
+ td({}, () => item.done ? "Done" : "Pending"),
174
+ ])
175
+ );
176
+ ```
177
+
178
+ ### Conditional rendering
179
+
180
+ Use ternary expressions inside reactive functions:
181
+
182
+ ```typescript
183
+ div({}, () => this.isLoading ? "Loading…" : "Content");
184
+ ```
185
+
186
+ Or use `data` with a falsy value to hide all children (like `*ngIf`):
187
+
188
+ ```typescript
189
+ // When this.items is null/undefined/false, all children are destroyed
190
+ ul({ data: () => this.items }, (item) =>
191
+ li({}, () => item.name),
192
+ );
193
+ ```
194
+
195
+ Use `fragment()` when you want conditional rendering **without a wrapper DOM node** — its children reconcile directly into the real ancestor:
196
+
197
+ ```typescript
198
+ fragment({ data: () => this.isLoading }, () => div({}, () => "Loading"));
199
+ ```
200
+
201
+ Use `gate()` when the condition shares a children function with frequently-changing siblings — it only re-evaluates when the boolean flips:
202
+
203
+ ```typescript
204
+ gate(() => this.isLoading) ? div({}, () => "Loading") : div({}, () => "Content");
205
+ ```
206
+
207
+ ### Fragment elements
208
+
209
+ `fragment()` creates a container with **no DOM node** — its children are inserted directly into the nearest real ancestor element. Use it when you need a reactive scope or a `data:` iteration but don't want an extra wrapper element in the DOM.
210
+
211
+ ```typescript
212
+ import { fragment } from "j-templates/DOM";
213
+
214
+ // Iteration with no wrapper node
215
+ fragment({ data: () => this.items }, (item) => div({}, () => item.name));
216
+
217
+ // Nested fragments flatten into the real ancestor
218
+ fragment({}, () => [
219
+ div({}, () => "OUTER"),
220
+ fragment({}, () => (this.showExtra ? div({}, () => "EXTRA") : div({}, () => "BASE"))),
221
+ ]);
222
+ ```
223
+
224
+ Key behaviors:
225
+ - **No DOM node** — a falsy `data:` value renders *nothing* (no empty wrapper box left behind).
226
+ - **`data:` behaves like any DOM element** — iterates arrays, wraps truthy scalars, collapses falsy values.
227
+ - **Nesting is fine** — fragments inside fragments flatten into the real ancestor.
228
+ - **Cannot be attached directly** — a fragment has no node to attach; wrap it in a real element (e.g. `div`) first.
229
+
230
+ ## Component Architecture
231
+
232
+ Components are class-based with three generic type parameters:
233
+
234
+ ```typescript
235
+ class MyComponent extends Component<Data, Templates, Events>
236
+ ```
237
+
238
+ - **`Data`** — Shape of data passed to the component factory
239
+ - **`Templates`** — Interface describing injectable template slots
240
+ - **`Events`** — Interface describing events the component fires
241
+
242
+ ### Lifecycle
243
+
244
+ 1. **Constructor** — Avoid overriding. Use `Bound()` instead.
245
+ 2. **`Bound()`** — Called after the component is attached to the DOM. Initialize state, start watchers, fetch data here.
246
+ 3. **`Template()`** — Return the component's virtual DOM.
247
+ 4. **`Destroy()`** — Cleanup. Automatically destroys all `@Value`/`@State`/`@Scope`/`@Computed` scopes and calls `.Destroy()` on `@Destroy`-decorated properties.
248
+
249
+ ### Creating and mounting components
250
+
251
+ ```typescript
252
+ // Convert class to factory function
253
+ const myComp = Component.ToFunction("my-comp", MyComponent);
254
+
255
+ // Mount to DOM
256
+ Component.Attach(document.body, myComp({ data: myData }));
257
+ ```
258
+
259
+ ### Component events
260
+
261
+ ```typescript
262
+ interface ButtonEvents {
263
+ click: { x: number; y: number };
264
+ }
265
+
266
+ class MyButton extends Component<void, void, ButtonEvents> {
267
+ Template() {
268
+ return button({
269
+ on: { click: (e) => this.Fire("click", { x: e.clientX, y: e.clientY }) },
270
+ }, () => "Click me");
271
+ }
272
+ }
273
+ ```
274
+
275
+ ### Component composition with templates
276
+
277
+ ```typescript
278
+ interface RowTemplate<D> {
279
+ row: (data: D) => vNode;
280
+ }
281
+
282
+ class DataTable<D> extends Component<{ items: D[] }, RowTemplate<D>> {
283
+ Template() {
284
+ return tbody({ data: () => this.Data.items }, (item: D) =>
285
+ this.Templates.row(item)
286
+ );
287
+ }
288
+ }
289
+
290
+ // Usage — inject the row template
291
+ const table = Component.ToFunction("data-table", DataTable);
292
+ table({
293
+ data: { items: myItems },
294
+ templates: { row: (item) => tr({}, () => td({}, () => item.name)) },
295
+ });
296
+ ```
297
+
298
+ ## Dependency Injection
299
+
300
+ ```typescript
301
+ import { Inject, Destroy } from "j-templates/Utils";
302
+
303
+ abstract class ApiService {
304
+ abstract fetch(): Promise<Data[]>;
305
+ }
306
+
307
+ class DataView extends Component {
308
+ @Inject(ApiService) api!: ApiService;
309
+ @Destroy() subscription?: IDestroyable;
310
+
311
+ Bound() {
312
+ this.subscription = this.api.fetch();
313
+ }
314
+ }
315
+ ```
316
+
317
+ Injectors are hierarchical — if a dependency isn't found on the current component, the framework walks up the component tree to parent injectors.
318
+
319
+ ## Stores
320
+
321
+ ### `StoreSync` — Synchronous diff-based store
322
+
323
+ ```typescript
324
+ import { StoreSync } from "j-templates/Store";
325
+
326
+ const store = new StoreSync((item) => item.id); // Key function for identity
327
+
328
+ store.Write({ id: "1", name: "Alice" }); // Write & diff
329
+ store.Patch("1", { name: "Bob" }); // Deep merge patch
330
+ store.Push("1", "tags", "admin"); // Push to nested array
331
+ const user = store.Get<User>("1"); // Observable retrieval
332
+ ```
333
+
334
+ ### `StoreAsync` — Asynchronous diff-based store
335
+
336
+ Same API as `StoreSync`, but all mutations return `Promise` and diff computation runs in a Web Worker to keep the main thread free.
337
+
338
+ ```typescript
339
+ import { StoreAsync } from "j-templates/Store";
340
+
341
+ const store = new StoreAsync((item) => item.id);
342
+ await store.Write({ id: "1", name: "Alice" });
343
+ ```
344
+
345
+ ## Observable Primitives
346
+
347
+ For advanced use cases, the reactive primitives are directly accessible:
348
+
349
+ ### `ObservableScope` — Signal-like reactive scope
350
+
351
+ ```typescript
352
+ import { ObservableScope } from "j-templates/Store";
353
+
354
+ const scope = ObservableScope.Create(() => count.value * 2);
355
+ const value = ObservableScope.Value(scope); // Read (registers dependency)
356
+ const peeked = ObservableScope.Peek(scope); // Read without registering
357
+ ObservableScope.Watch(scope, (v) => console.log(v));
358
+ ```
359
+
360
+ ### `ObservableNode` — Proxy-based deep reactivity
361
+
362
+ ```typescript
363
+ import { ObservableNode } from "j-templates/Store";
364
+
365
+ const obj = ObservableNode.Create({ a: 1, b: { c: 2 } });
366
+ obj.a = 10; // Triggers reactive update on leaf scope
367
+ const raw = ObservableNode.Unwrap(obj); // { a: 10, b: { c: 2 } }
368
+ ```
369
+
370
+ ### Inline computed scopes — `scope()`, `gate()`, `peek()`, `mapped()`
371
+
372
+ Memoized computed scopes you can create inline within a watch context (template functions, `@Scope` getters, etc.). All accept `() => T | Promise<T>`.
373
+
374
+ ```typescript
375
+ import { scope, gate, peek, mapped } from "j-templates";
376
+
377
+ // Full reactivity — emits on every recomputation
378
+ scope(() => this.Data.items);
379
+
380
+ // Emission gatekeeper — only emits when the value changes by ===
381
+ gate(() => this.count > 10);
382
+
383
+ // Read without subscribing — no dependency registered
384
+ peek(() => Date.now());
385
+
386
+ // Per-item scope (the mechanism `data:` uses internally)
387
+ mapped(item, (d) => /* ... */);
388
+ ```
389
+
390
+ ## Animation
391
+
392
+ ```typescript
393
+ import { Animation, AnimationType } from "j-templates/Utils";
394
+
395
+ const anim = new Animation(AnimationType.EaseIn, 1000, (next) => {
396
+ element.style.opacity = String(next);
397
+ });
398
+ anim.Animate(0, 1); // Fades from 0 to 1 over 1000ms
399
+ ```
400
+
401
+ ## API Quick Reference
402
+
403
+ ### Decorators
404
+
405
+ | Decorator | Target | Description |
406
+ |---|---|---|
407
+ | `@Value()` | Property | Reactive primitive (number, string, boolean) |
408
+ | `@State()` | Property | Deep reactive object/array via proxy |
409
+ | `@Scope()` | Getter | Cached computed value; new reference on change |
410
+ | `@Computed()` | Getter | Cached computed with identity preservation via diff |
411
+ | `@ComputedAsync(default)` | Getter | Async `@Computed` backed by `StoreAsync` |
412
+ | `@Watch(scopeFn)` | Method | Auto-subscribe method to reactive value changes |
413
+ | `@Inject(type)` | Property | Dependency injection from component injector |
414
+ | `@Destroy()` | Property | Auto-calls `.Destroy()` on property when component is destroyed |
415
+
416
+ ### Component API
417
+
418
+ | Method | Description |
419
+ |---|---|
420
+ | `Template()` | Return virtual DOM — override in subclass |
421
+ | `Bound()` | Lifecycle hook — called after DOM attachment |
422
+ | `Destroy()` | Lifecycle hook — cleanup (auto-cleans decorators) |
423
+ | `Fire(event, data)` | Emit a component event |
424
+ | `Component.ToFunction(name, Class)` | Convert class to factory function |
425
+ | `Component.Register(name, Class)` | Register as Web Component (custom element) |
426
+ | `Component.Attach(node, vNode)` | Mount a vNode to a real DOM node |
427
+
428
+ ### Store API
429
+
430
+ | Method | StoreSync | StoreAsync |
431
+ |---|---|---|
432
+ | `Write(data, key?)` | Sync | `Promise` |
433
+ | `Patch(key, patch)` | Sync | `Promise` |
434
+ | `Push(key, ...data)` | Sync | `Promise` |
435
+ | `Splice(key, start, del?, ...items)` | Sync | `Promise` |
436
+ | `Get(key)` | Sync | Sync |
437
+ | `Destroy()` | — | Stops async queue |
438
+
439
+ ## Documentation
440
+
441
+ ### Tutorials
442
+ - [Getting Started](docs/tutorials/01-getting-started.md)
443
+ - [Your First Component](docs/tutorials/02-your-first-component.md)
444
+ - [Reactive State Basics](docs/tutorials/03-reactive-state-basics.md)
445
+
446
+ ### Patterns
447
+ - [Components](docs/patterns/01-components.md) — Component class, lifecycle, data passing, template functions, events, composition
448
+ - [Reactivity](docs/patterns/02-reactivity.md) — ObservableScope, ObservableNode, stores, decorators (@Value, @State, @Scope, @Computed, @Watch)
449
+ - [Templates & Data](docs/patterns/03-templates-and-data.md) — DOM element functions, reactive bindings, data modeling, animation
450
+ - [Dependency Injection](docs/patterns/04-dependency-injection.md) — Injector hierarchy, @Inject, @Destroy, IDestroyable
451
+
452
+ ### Reference
453
+ - [Syntax Primer v3](docs/SYNTAX_PRIMER_v3.md)
454
+
455
+ ## Examples
456
+
457
+ - [Real-Time Dashboard](examples/real_time_dashboard/) — Full application example
458
+ - [Tutorial Project](examples/tutorial_project/) — Progressive tutorial series
459
+
460
+ ## License
461
+
462
+ MIT