@relax.js/core 1.0.0

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 (194) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/dist/DataLoader.d.ts +51 -0
  4. package/dist/DependencyInjection.d.ts +271 -0
  5. package/dist/DependencyInjectionOld.d.ts +35 -0
  6. package/dist/Metadata.d.ts +8 -0
  7. package/dist/SequentialId.d.ts +47 -0
  8. package/dist/_alt/src/MustardEngine.d.ts +30 -0
  9. package/dist/_alt/src/MustardParser.d.ts +63 -0
  10. package/dist/_alt/src/MustardParser2.d.ts +35 -0
  11. package/dist/_alt/src/pipes.d.ts +93 -0
  12. package/dist/_alt/src/template.d.ts +166 -0
  13. package/dist/_alt/src/tools.d.ts +4 -0
  14. package/dist/_alt/tests/pipes.tests.d.ts +1 -0
  15. package/dist/_alt/tests/template.tests.d.ts +1 -0
  16. package/dist/_alt/vitest.config.d.ts +2 -0
  17. package/dist/collections/Index.d.ts +1 -0
  18. package/dist/collections/LinkedList.d.ts +75 -0
  19. package/dist/collections/Pager.d.ts +15 -0
  20. package/dist/collections/index.js +2 -0
  21. package/dist/collections/index.js.map +7 -0
  22. package/dist/collections/index.mjs +2 -0
  23. package/dist/collections/index.mjs.map +7 -0
  24. package/dist/components/Table.d.ts +13 -0
  25. package/dist/components/index.d.ts +4 -0
  26. package/dist/components/index.js +128 -0
  27. package/dist/components/index.js.map +7 -0
  28. package/dist/components/index.mjs +128 -0
  29. package/dist/components/index.mjs.map +7 -0
  30. package/dist/components/lists/Table.d.ts +59 -0
  31. package/dist/components/lists/TreeView.d.ts +67 -0
  32. package/dist/components/lists/index.d.ts +2 -0
  33. package/dist/components/loader.d.ts +60 -0
  34. package/dist/components/menus/MenuItem.d.ts +30 -0
  35. package/dist/components/menus/TopMenu.d.ts +16 -0
  36. package/dist/components/menus/index.d.ts +2 -0
  37. package/dist/components/panels/tabs.d.ts +15 -0
  38. package/dist/di/index.d.ts +1 -0
  39. package/dist/di/index.js +2 -0
  40. package/dist/di/index.js.map +7 -0
  41. package/dist/di/index.mjs +2 -0
  42. package/dist/di/index.mjs.map +7 -0
  43. package/dist/elements/CopyAttributes.d.ts +2 -0
  44. package/dist/elements/dom.d.ts +18 -0
  45. package/dist/elements/index.d.ts +2 -0
  46. package/dist/elements/index.js +2 -0
  47. package/dist/elements/index.js.map +7 -0
  48. package/dist/elements/index.mjs +2 -0
  49. package/dist/elements/index.mjs.map +7 -0
  50. package/dist/errors.d.ts +71 -0
  51. package/dist/forms/FormReader.d.ts +182 -0
  52. package/dist/forms/FormValidator.d.ts +114 -0
  53. package/dist/forms/ValidationRules.d.ts +103 -0
  54. package/dist/forms/index.d.ts +4 -0
  55. package/dist/forms/index.js +2 -0
  56. package/dist/forms/index.js.map +7 -0
  57. package/dist/forms/index.mjs +2 -0
  58. package/dist/forms/index.mjs.map +7 -0
  59. package/dist/forms/setFormData.d.ts +49 -0
  60. package/dist/getParentComponent.d.ts +43 -0
  61. package/dist/html/TableRenderer.d.ts +44 -0
  62. package/dist/html/TreeBinder.d.ts +9 -0
  63. package/dist/html/html.d.ts +55 -0
  64. package/dist/html/index.d.ts +5 -0
  65. package/dist/html/index.js +2 -0
  66. package/dist/html/index.js.map +7 -0
  67. package/dist/html/index.mjs +2 -0
  68. package/dist/html/index.mjs.map +7 -0
  69. package/dist/html/template.d.ts +167 -0
  70. package/dist/http/ServerSentEvents.d.ts +116 -0
  71. package/dist/http/SimpleWebSocket.d.ts +153 -0
  72. package/dist/http/http.d.ts +177 -0
  73. package/dist/http/index.d.ts +3 -0
  74. package/dist/http/index.js +2 -0
  75. package/dist/http/index.js.map +7 -0
  76. package/dist/http/index.mjs +2 -0
  77. package/dist/http/index.mjs.map +7 -0
  78. package/dist/i18n/i18n.d.ts +105 -0
  79. package/dist/i18n/icu.d.ts +64 -0
  80. package/dist/i18n/index.d.ts +2 -0
  81. package/dist/i18n/index.js +2 -0
  82. package/dist/i18n/index.js.map +7 -0
  83. package/dist/i18n/index.mjs +2 -0
  84. package/dist/i18n/index.mjs.map +7 -0
  85. package/dist/index.d.ts +16 -0
  86. package/dist/index.js +5 -0
  87. package/dist/index.js.map +7 -0
  88. package/dist/index.mjs +5 -0
  89. package/dist/index.mjs.map +7 -0
  90. package/dist/lib/DataLoader.d.ts +51 -0
  91. package/dist/lib/DependencyInjection.d.ts +271 -0
  92. package/dist/lib/InvokeParent.d.ts +10 -0
  93. package/dist/lib/Pipes.d.ts +236 -0
  94. package/dist/lib/SequentialId.d.ts +47 -0
  95. package/dist/lib/collections/Index.d.ts +1 -0
  96. package/dist/lib/collections/LinkedList.d.ts +75 -0
  97. package/dist/lib/collections/Pager.d.ts +15 -0
  98. package/dist/lib/collections/TableRenderer.d.ts +44 -0
  99. package/dist/lib/di/index.d.ts +1 -0
  100. package/dist/lib/elements/CopyAttributes.d.ts +2 -0
  101. package/dist/lib/elements/dom.d.ts +18 -0
  102. package/dist/lib/elements/index.d.ts +2 -0
  103. package/dist/lib/errors.d.ts +71 -0
  104. package/dist/lib/forms/FormReader.d.ts +182 -0
  105. package/dist/lib/forms/FormValidator.d.ts +114 -0
  106. package/dist/lib/forms/ValidationRules.d.ts +103 -0
  107. package/dist/lib/forms/index.d.ts +4 -0
  108. package/dist/lib/forms/setFormData.d.ts +49 -0
  109. package/dist/lib/getParentComponent.d.ts +43 -0
  110. package/dist/lib/html/TableRenderer.d.ts +44 -0
  111. package/dist/lib/html/TreeBinder.d.ts +9 -0
  112. package/dist/lib/html/html.d.ts +55 -0
  113. package/dist/lib/html/html2.d.ts +55 -0
  114. package/dist/lib/html/index.d.ts +5 -0
  115. package/dist/lib/html/m.d.ts +167 -0
  116. package/dist/lib/html/m2.d.ts +8 -0
  117. package/dist/lib/html/m3.d.ts +0 -0
  118. package/dist/lib/html/template.d.ts +167 -0
  119. package/dist/lib/http/HttpClient.d.ts +153 -0
  120. package/dist/lib/http/ServerSentEvents.d.ts +116 -0
  121. package/dist/lib/http/SimpleWebSocket.d.ts +153 -0
  122. package/dist/lib/http/http.d.ts +177 -0
  123. package/dist/lib/http/index.d.ts +3 -0
  124. package/dist/lib/i18n/i18n.d.ts +105 -0
  125. package/dist/lib/i18n/icu.d.ts +64 -0
  126. package/dist/lib/i18n/index.d.ts +2 -0
  127. package/dist/lib/index.d.ts +16 -0
  128. package/dist/lib/routing/NavigateRouteEvent.d.ts +52 -0
  129. package/dist/lib/routing/RouteLink.d.ts +7 -0
  130. package/dist/lib/routing/Routing.d.ts +270 -0
  131. package/dist/lib/routing/RoutingTarget.d.ts +22 -0
  132. package/dist/lib/routing/index.d.ts +7 -0
  133. package/dist/lib/routing/navigation.d.ts +70 -0
  134. package/dist/lib/routing/routeMatching.d.ts +21 -0
  135. package/dist/lib/routing/routeTargetRegistry.d.ts +23 -0
  136. package/dist/lib/routing/types.d.ts +130 -0
  137. package/dist/lib/templates/NodeTemplate.d.ts +38 -0
  138. package/dist/lib/templates/accessorParser.d.ts +87 -0
  139. package/dist/lib/templates/parseTemplate.d.ts +6 -0
  140. package/dist/lib/templates/tokenizer.d.ts +76 -0
  141. package/dist/lib/tools.d.ts +30 -0
  142. package/dist/lib/utils/index.d.ts +4 -0
  143. package/dist/pipes.d.ts +236 -0
  144. package/dist/routing/NavigateRouteEvent.d.ts +52 -0
  145. package/dist/routing/RouteLink.d.ts +7 -0
  146. package/dist/routing/RoutingTarget.d.ts +22 -0
  147. package/dist/routing/index.d.ts +7 -0
  148. package/dist/routing/index.js +5 -0
  149. package/dist/routing/index.js.map +7 -0
  150. package/dist/routing/index.mjs +5 -0
  151. package/dist/routing/index.mjs.map +7 -0
  152. package/dist/routing/navigation.d.ts +70 -0
  153. package/dist/routing/routeMatching.d.ts +21 -0
  154. package/dist/routing/routeTargetRegistry.d.ts +23 -0
  155. package/dist/routing/types.d.ts +130 -0
  156. package/dist/templates/NodeTemplate.d.ts +38 -0
  157. package/dist/templates/accessorParser.d.ts +87 -0
  158. package/dist/templates/parseTemplate.d.ts +6 -0
  159. package/dist/templates/tokenizer.d.ts +76 -0
  160. package/dist/tools.d.ts +30 -0
  161. package/dist/utils/index.d.ts +4 -0
  162. package/dist/utils/index.js +2 -0
  163. package/dist/utils/index.js.map +7 -0
  164. package/dist/utils/index.mjs +2 -0
  165. package/dist/utils/index.mjs.map +7 -0
  166. package/docs/Architecture.md +333 -0
  167. package/docs/DependencyInjection.md +237 -0
  168. package/docs/Errors.md +87 -0
  169. package/docs/GettingStarted.md +231 -0
  170. package/docs/Pipes.md +211 -0
  171. package/docs/Translations.md +312 -0
  172. package/docs/WhyRelaxjs.md +336 -0
  173. package/docs/elements/dom.md +102 -0
  174. package/docs/forms/creating-form-components.md +924 -0
  175. package/docs/forms/form-api.md +94 -0
  176. package/docs/forms/forms.md +99 -0
  177. package/docs/forms/patterns.md +311 -0
  178. package/docs/forms/reading-writing.md +365 -0
  179. package/docs/forms/validation.md +351 -0
  180. package/docs/html/TableRenderer.md +292 -0
  181. package/docs/html/html.md +175 -0
  182. package/docs/html/index.md +54 -0
  183. package/docs/html/template.md +422 -0
  184. package/docs/http/HttpClient.md +459 -0
  185. package/docs/http/ServerSentEvents.md +184 -0
  186. package/docs/http/index.md +109 -0
  187. package/docs/i18n/i18n.md +309 -0
  188. package/docs/i18n/intl-standard.md +178 -0
  189. package/docs/routing/RouteLink.md +98 -0
  190. package/docs/routing/Routing.md +332 -0
  191. package/docs/routing/RoutingTarget.md +136 -0
  192. package/docs/routing/layouts.md +207 -0
  193. package/docs/utilities.md +143 -0
  194. package/package.json +93 -0
@@ -0,0 +1,292 @@
1
+ # TableRenderer for Web Components
2
+
3
+ `TableRenderer` is a small helper class that renders table rows inside Web Components using a `<template>` and an array of data. It supports data binding, row updates, and declarative button handlers that call methods on your Web Component.
4
+
5
+ ## ✅ 1. Getting Started
6
+
7
+ ### Minimal Web Component Setup
8
+
9
+ ```ts
10
+ import { TableRenderer } from 'relaxjs/html';
11
+
12
+ class UserTable extends HTMLElement {
13
+ private renderer!: TableRenderer;
14
+
15
+ constructor() {
16
+ super();
17
+ this.attachShadow({ mode: 'open' });
18
+ }
19
+
20
+ connectedCallback() {
21
+ this.shadowRoot!.innerHTML = `
22
+ <table>
23
+ <tbody></tbody>
24
+ </table>
25
+ <template id="row-template">
26
+ <tr>
27
+ <td data-field="name"></td>
28
+ <td data-field="role"></td>
29
+ </tr>
30
+ </template>
31
+ `;
32
+
33
+ const table = this.shadowRoot!.querySelector('table')!;
34
+ const template = this.shadowRoot!.querySelector('#row-template') as HTMLTemplateElement;
35
+
36
+ this.renderer = new TableRenderer(table, template, 'id', this);
37
+ this.renderer.render([
38
+ { id: 1, name: 'Alice', role: 'Admin' },
39
+ { id: 2, name: 'Bob', role: 'User' }
40
+ ]);
41
+ }
42
+ }
43
+
44
+ customElements.define('user-table', UserTable);
45
+ ```
46
+
47
+ **What this does:**
48
+ - Clones the `<template>` row for each item
49
+ - Fills in `<td data-field="name">` using data values
50
+ - Associates each row with its data via the `id` field
51
+
52
+ ## 🛠 2. Updating a Row
53
+
54
+ Use `update()` to refresh a single row without re-rendering everything:
55
+
56
+ ```ts
57
+ this.renderer.update({ id: 2, name: 'Bob Smith', role: 'Moderator' });
58
+ ```
59
+
60
+ If a matching row exists (`idColumn` = `"id"`), it will update in-place. If not, a new row is added.
61
+
62
+ ## 🎯 3. Button Event Binding
63
+
64
+ Add buttons in the template using `onclick="methodName"`.
65
+
66
+ ### Updated Template
67
+
68
+ ```html
69
+ <template id="row-template">
70
+ <tr>
71
+ <td data-field="name"></td>
72
+ <td data-field="role"></td>
73
+ <td>
74
+ <button onclick="edit">Edit</button>
75
+ </td>
76
+ </tr>
77
+ </template>
78
+ ```
79
+
80
+ ### Component Method
81
+
82
+ ```ts
83
+ edit(data: any, event: MouseEvent) {
84
+ console.log('Editing user:', data);
85
+ }
86
+ ```
87
+
88
+ **Behavior:**
89
+ - `edit` is automatically bound for each row
90
+ - It receives the row's `data` as the first argument
91
+ - The second argument is the `MouseEvent`
92
+
93
+ ## 📦 4. Using Arguments in Handlers
94
+
95
+ You can call methods with literal arguments. The remaining arguments are always `data` and `event`.
96
+
97
+ ### Template Example
98
+
99
+ ```html
100
+ <button onclick="remove('soft')">Delete</button>
101
+ ```
102
+
103
+ ### Component Method
104
+
105
+ ```ts
106
+ remove(mode: string, data: any, event: MouseEvent) {
107
+ console.log(`Removing (${mode})`, data);
108
+ }
109
+ ```
110
+
111
+ **How It Works:**
112
+ - The string `'soft'` is passed as the first argument
113
+ - `data` and `event` are appended automatically
114
+
115
+ ## 🧼 5. Re-rendering Safely
116
+
117
+ The `.render()` method replaces all rows and cleans up memory:
118
+
119
+ ```ts
120
+ this.renderer.render([
121
+ { id: 3, name: 'Charlie', role: 'User' }
122
+ ]);
123
+ ```
124
+
125
+ - Clears old rows and their event listeners
126
+ - Rebuilds new rows from the template and data
127
+
128
+ ## 6. Column Sorting with TableSorter
129
+
130
+ `TableSorter` adds click-to-sort behavior to table headers. Click a `<th>` to cycle through ascending, descending, and unsorted.
131
+
132
+ ### Setup
133
+
134
+ ```ts
135
+ import { TableSorter } from 'relaxjs/html';
136
+
137
+ class UserTable extends HTMLElement {
138
+ connectedCallback() {
139
+ this.innerHTML = `
140
+ <table>
141
+ <thead>
142
+ <tr>
143
+ <th name="name">Name</th>
144
+ <th name="role">Role</th>
145
+ <th name="age">Age</th>
146
+ </tr>
147
+ </thead>
148
+ <tbody></tbody>
149
+ </table>
150
+ `;
151
+
152
+ const table = this.querySelector('table')!;
153
+ const sorter = new TableSorter(table, this);
154
+ }
155
+ }
156
+ ```
157
+
158
+ **How it works:**
159
+ - Headers must have a `name` attribute matching the data field
160
+ - Click cycles: none -> ascending (arrow up) -> descending (arrow down) -> none
161
+ - Sort indicators (arrows) are added/removed automatically
162
+
163
+ ### Handling Sort Events
164
+
165
+ `TableSorter` dispatches a `SortChangeEvent` on the component:
166
+
167
+ ```ts
168
+ import { SortChangeEvent, SortColumn } from 'relaxjs/html';
169
+
170
+ this.addEventListener('sortchange', (e: SortChangeEvent) => {
171
+ const sortColumns: SortColumn[] = e.detail;
172
+ // sortColumns = [{ column: 'name', direction: 'asc' }]
173
+ this.fetchSortedData(sortColumns);
174
+ });
175
+ ```
176
+
177
+ ### API
178
+
179
+ | Method | Description |
180
+ |--------|-------------|
181
+ | `getSortColumns()` | Returns current sort state as `SortColumn[]` |
182
+ | `clear()` | Resets all sorting and emits a `sortchange` event |
183
+
184
+ ```typescript
185
+ type SortColumn = { column: string; direction: 'asc' | 'desc' };
186
+ ```
187
+
188
+ ## 7. Pagination with Pager
189
+
190
+ `Pager` renders page navigation buttons (Previous, page numbers, Next) and dispatches events on page change.
191
+
192
+ ### Setup
193
+
194
+ ```ts
195
+ import { Pager, PageSelectedEvent } from 'relaxjs/html';
196
+
197
+ class UserTable extends HTMLElement {
198
+ private pager!: Pager;
199
+
200
+ connectedCallback() {
201
+ this.innerHTML = `
202
+ <table><!-- ... --></table>
203
+ <div id="pager"></div>
204
+ `;
205
+
206
+ const pagerContainer = this.querySelector('#pager')!;
207
+ this.pager = new Pager(pagerContainer, 100, 10); // 100 items, 10 per page
208
+
209
+ pagerContainer.addEventListener('pageselected', (e: PageSelectedEvent) => {
210
+ this.loadPage(e.detail);
211
+ });
212
+ }
213
+
214
+ async loadPage(page: number) {
215
+ const data = await fetchUsers(page);
216
+ this.renderer.render(data);
217
+ }
218
+ }
219
+ ```
220
+
221
+ ### Updating Total Count
222
+
223
+ When the total number of items changes (e.g. after filtering):
224
+
225
+ ```ts
226
+ this.pager.update(newTotalCount);
227
+ ```
228
+
229
+ ### API
230
+
231
+ | Method | Description |
232
+ |--------|-------------|
233
+ | `update(totalCount)` | Updates total count and re-renders page buttons |
234
+ | `getCurrentPage()` | Returns the current page number |
235
+
236
+ ### Combined Example: TableRenderer + TableSorter + Pager
237
+
238
+ ```ts
239
+ import { TableRenderer, TableSorter, Pager } from 'relaxjs/html';
240
+
241
+ class ProductList extends HTMLElement {
242
+ private renderer!: TableRenderer;
243
+ private sorter!: TableSorter;
244
+ private pager!: Pager;
245
+
246
+ connectedCallback() {
247
+ this.innerHTML = `
248
+ <table>
249
+ <thead>
250
+ <tr>
251
+ <th name="name">Name</th>
252
+ <th name="price">Price</th>
253
+ </tr>
254
+ </thead>
255
+ <tbody></tbody>
256
+ </table>
257
+ <template id="row-tpl">
258
+ <tr>
259
+ <td data-field="name"></td>
260
+ <td data-field="price"></td>
261
+ <td><button onclick="edit">Edit</button></td>
262
+ </tr>
263
+ </template>
264
+ <div id="pager"></div>
265
+ `;
266
+
267
+ const table = this.querySelector('table')!;
268
+ const template = this.querySelector('#row-tpl') as HTMLTemplateElement;
269
+
270
+ this.renderer = new TableRenderer(table, template, 'id', this);
271
+ this.sorter = new TableSorter(table, this);
272
+ this.pager = new Pager(this.querySelector('#pager')!, 0, 20);
273
+
274
+ this.addEventListener('sortchange', () => this.reload());
275
+ this.querySelector('#pager')!.addEventListener('pageselected', () => this.reload());
276
+
277
+ this.reload();
278
+ }
279
+
280
+ async reload() {
281
+ const page = this.pager.getCurrentPage();
282
+ const sort = this.sorter.getSortColumns();
283
+ const { items, total } = await fetchProducts(page, sort);
284
+ this.renderer.render(items);
285
+ this.pager.update(total);
286
+ }
287
+
288
+ edit(data: any) {
289
+ console.log('Edit product:', data);
290
+ }
291
+ }
292
+ ```
@@ -0,0 +1,175 @@
1
+ # html Template Engine
2
+
3
+ A lightweight HTML template engine with update capabilities. Creates templates that can be re-rendered with new data without recreating DOM nodes.
4
+
5
+ ## Usage
6
+
7
+ ```typescript
8
+ import { html } from 'relaxjs/html';
9
+
10
+ // Create a template
11
+ const userCard = html`
12
+ <div class="user-card">
13
+ <h2>{{name}}</h2>
14
+ <p>{{email}}</p>
15
+ </div>
16
+ `;
17
+
18
+ // Render with data
19
+ const result = userCard({ name: 'John', email: 'john@example.com' });
20
+ container.appendChild(result.fragment);
21
+
22
+ // Update with new data (no DOM recreation)
23
+ result.update({ name: 'Jane', email: 'jane@example.com' });
24
+ ```
25
+
26
+ ## Features
27
+
28
+ ### Mustache Bindings
29
+
30
+ Use `{{property}}` syntax to bind context properties to text content or attributes:
31
+
32
+ ```typescript
33
+ const template = html`
34
+ <a href="{{url}}" class="{{linkClass}}">{{linkText}}</a>
35
+ `;
36
+ ```
37
+
38
+ ### Template Literal Substitutions
39
+
40
+ Use `${}` for static values or functions:
41
+
42
+ ```typescript
43
+ const staticClass = 'container';
44
+ const template = html`<div class="${staticClass}">{{content}}</div>`;
45
+ ```
46
+
47
+ ### Event Handlers
48
+
49
+ Bind event handlers with context:
50
+
51
+ ```typescript
52
+ const row = html`
53
+ <tr>
54
+ <td>{{name}}</td>
55
+ <td>
56
+ <button onclick=${function() { this.onEdit(this.id); }}>Edit</button>
57
+ </td>
58
+ </tr>
59
+ `;
60
+
61
+ const result = row({
62
+ id: 42,
63
+ name: 'Item',
64
+ onEdit(id) { console.log('Edit:', id); }
65
+ });
66
+ ```
67
+
68
+ ### Context Functions
69
+
70
+ Call methods from the context object:
71
+
72
+ ```typescript
73
+ const template = html`<div>{{formatPrice}}</div>`;
74
+
75
+ const result = template({
76
+ price: 99.99,
77
+ formatPrice() {
78
+ return `$${this.price.toFixed(2)}`;
79
+ }
80
+ });
81
+ ```
82
+
83
+ ### Function Arguments
84
+
85
+ Pass arguments to context functions using the pipe syntax:
86
+
87
+ ```typescript
88
+ const template = html`<div>{{greet|name}}</div>`;
89
+
90
+ const result = template({
91
+ name: 'John',
92
+ greet(name) { return `Hello, ${name}!`; }
93
+ });
94
+ // Result: <div>Hello, John!</div>
95
+ ```
96
+
97
+ The value after `|` is resolved from the context and passed to the function. Multiple arguments use comma separation:
98
+
99
+ ```typescript
100
+ const template = html`<div>{{format|name,title}}</div>`;
101
+
102
+ const result = template({
103
+ name: 'John',
104
+ title: 'Developer',
105
+ format(name, title) { return `${name} - ${title}`; }
106
+ });
107
+ ```
108
+
109
+ For value transformations using pipes (like `uppercase`, `currency`), use [compileTemplate](template.md) instead.
110
+
111
+ ## API
112
+
113
+ ### `html` (tagged template literal)
114
+
115
+ ```typescript
116
+ function html(
117
+ templateStrings: TemplateStringsArray,
118
+ ...substitutions: any[]
119
+ ): (context: any) => RenderTemplate
120
+ ```
121
+
122
+ Creates a template function that accepts a context object and returns a `RenderTemplate`.
123
+
124
+ ### `RenderTemplate`
125
+
126
+ ```typescript
127
+ interface RenderTemplate {
128
+ fragment: DocumentFragment;
129
+ update(context: any): void;
130
+ }
131
+ ```
132
+
133
+ - `fragment`: The rendered DOM fragment. Add to the DOM once.
134
+ - `update(context)`: Re-renders with new data without recreating DOM nodes.
135
+
136
+ ## Design
137
+
138
+ This template engine is designed for **single-use updateable templates**:
139
+
140
+ 1. Create the template once
141
+ 2. Render and add `fragment` to the DOM
142
+ 3. Call `update()` to push changes to the existing nodes
143
+
144
+ For reusable templates that create multiple independent instances, use `compileTemplate` from [template](template.md).
145
+
146
+ ## Property vs Attribute Binding
147
+
148
+ The engine automatically detects when to set element properties vs attributes:
149
+
150
+ ```typescript
151
+ // Sets input.value property (not attribute)
152
+ const input = html`<input value="{{val}}">`;
153
+
154
+ // Sets data-id attribute
155
+ const div = html`<div data-id="{{id}}"></div>`;
156
+ ```
157
+
158
+ ## Custom Elements
159
+
160
+ Custom elements are automatically upgraded when encountered in templates.
161
+
162
+ ## Limitations
163
+
164
+ The `html` template is optimized for simple, updateable templates. For advanced features, use [compileTemplate](template.md):
165
+
166
+ | Feature | `html` | `compileTemplate` |
167
+ |---------|--------|-------------------|
168
+ | Mustache bindings | ✅ | ✅ |
169
+ | Event handlers | ✅ | ❌ |
170
+ | In-place updates | ✅ | ✅ |
171
+ | Nested paths (`user.name`) | ❌ | ✅ |
172
+ | Loops (`loop="item in items"`) | ❌ | ✅ |
173
+ | Conditionals (`if`, `unless`) | ❌ | ✅ |
174
+ | Pipe transformations | ❌ | ✅ |
175
+ | Function calls with args | ✅ (via `\|`) | ✅ |
@@ -0,0 +1,54 @@
1
+ # HTML & Templating
2
+
3
+ This module provides templating utilities for rendering dynamic HTML content.
4
+
5
+ ## Available Features
6
+
7
+ | Feature | Description | Use Case |
8
+ |---------|-------------|----------|
9
+ | [html](html.md) | Tagged template literal with update support | Single-use templates with in-place updates |
10
+ | [compileTemplate](template.md) | Full-featured template compiler | Reusable templates with loops, conditionals, pipes |
11
+ | [Pipes](../Pipes.md) | Value transformation functions | Format dates, currencies, text in templates |
12
+ | [TableRenderer](TableRenderer.md) | Table row renderer for Web Components | Data tables with row updates and button handlers |
13
+
14
+ ## Quick Comparison
15
+
16
+ ### html
17
+
18
+ Best for: Single templates that need efficient updates
19
+
20
+ ```typescript
21
+ const card = html`<div>{{name}}</div>`;
22
+ const result = card({ name: 'John' });
23
+ container.appendChild(result.fragment);
24
+ result.update({ name: 'Jane' }); // Updates in place
25
+ ```
26
+
27
+ ### compileTemplate
28
+
29
+ Best for: Complex templates with loops and conditionals
30
+
31
+ ```typescript
32
+ const { content, render } = compileTemplate(`
33
+ <ul>
34
+ <li loop="item in items" if="item.visible">{{item.name}}</li>
35
+ </ul>
36
+ `);
37
+ render({ items: [...] });
38
+ ```
39
+
40
+ ### TableRenderer
41
+
42
+ Best for: Data tables in Web Components
43
+
44
+ ```typescript
45
+ const renderer = new TableRenderer(table, template, 'id', this);
46
+ renderer.render(data);
47
+ renderer.updateRow(id, newData);
48
+ ```
49
+
50
+ ## Choosing the Right Tool
51
+
52
+ - **Need in-place updates?** → Use `html`
53
+ - **Need loops/conditionals?** → Use `compileTemplate`
54
+ - **Building a data table?** → Use `TableRenderer`