jails-js 6.9.7 → 6.9.9

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.
@@ -0,0 +1,556 @@
1
+ # html-if
2
+
3
+ ## Purpose
4
+
5
+ Conditionally render a node based on a JavaScript expression evaluated against the component view scope.
6
+
7
+ ## Syntax
8
+
9
+ ```html
10
+ <div html-if="show">Hello, {{ name }}</div>
11
+ <div html-if="!show">Hidden branch</div>
12
+ ```
13
+
14
+ ## Parameters
15
+
16
+ - Expression string: any valid JavaScript expression available in the render scope.
17
+
18
+ ## Rendering Behavior
19
+
20
+ When the expression is truthy, the element participates in rendered output. When falsy, the element is absent from rendered output. Nested mustache expressions and nested directives are evaluated only for the active rendered branch.
21
+
22
+ ## DOM Behavior
23
+
24
+ The docs show falsy `html-if` nodes removed from output rather than hidden with CSS. Treat the node as created when the condition becomes truthy and removed when it becomes falsy. Any DOM state inside a removed branch is lost unless stored externally.
25
+
26
+ ## Update Behavior
27
+
28
+ The expression is re-evaluated after state updates and parent prop updates. Toggling false to true recreates the branch from the directive template.
29
+
30
+ ## Performance Characteristics
31
+
32
+ Cheap for small branches. Expensive branches should be guarded carefully because truthy transitions create DOM and nested directives. Avoid using it for frequent visibility toggles of large subtrees if CSS visibility would preserve DOM state better.
33
+
34
+ ## Common Patterns
35
+
36
+ - Loading and error states.
37
+ - Optional user data after fetch.
38
+ - Mutually exclusive branches with `html-if="condition"` and `html-if="!condition"`.
39
+
40
+ ## Anti-patterns
41
+
42
+ - Using `html-if` for form inputs whose typed value should persist while hidden.
43
+ - Running expensive expressions in the condition.
44
+ - Depending on event listeners bound directly to children inside the branch; use delegated `on()`.
45
+
46
+ ## Edge Cases
47
+
48
+ - Falsy values include `false`, `0`, `''`, `null`, `undefined`, and `NaN`.
49
+ - If a child component is inside a removed branch, expect its element to be detached and `unmount()` to run.
50
+
51
+ ## Example
52
+
53
+ ```html
54
+ <my-component>
55
+ <p html-if="isVisible">Hey! Now you see me</p>
56
+ <button data-toggle>Toggle</button>
57
+ </my-component>
58
+ ```
59
+
60
+ ```ts
61
+ export default function myComponent({ main, on, state }) {
62
+ main(() => {
63
+ on('click', '[data-toggle]', toggle)
64
+ })
65
+
66
+ const toggle = () => {
67
+ state.set(s => {
68
+ s.isVisible = !s.isVisible
69
+ })
70
+ }
71
+ }
72
+
73
+ export const model = {
74
+ isVisible: true
75
+ }
76
+ ```
77
+
78
+ ## Internal Notes
79
+
80
+ The repository documents output semantics but does not include runtime code. The removal/recreation behavior is inferred from examples where falsy nodes are absent from final HTML.
81
+
82
+ # html-for
83
+
84
+ ## Purpose
85
+
86
+ Repeat an element for each item in an array or object.
87
+
88
+ ## Syntax
89
+
90
+ ```html
91
+ <li html-for="item in list">{{ item.name }} {{ $index }}</li>
92
+ ```
93
+
94
+ ## Parameters
95
+
96
+ - Item alias: local variable name for each value.
97
+ - Iterable expression: array or object expression.
98
+ - Auto variables: `$index` for numeric position; `$key` for object key.
99
+
100
+ ## Rendering Behavior
101
+
102
+ The element carrying `html-for` is used as the repeated template. For each item, Jails renders one copy of that element with the alias, `$index`, and `$key` available to nested expressions and directives.
103
+
104
+ ## DOM Behavior
105
+
106
+ Copies are inserted where the original directive element appears. If the iterable shrinks, extra copies are removed. If it grows, new copies are created. Nested directives run inside each copy with that item scope.
107
+
108
+ ## Update Behavior
109
+
110
+ The loop is re-evaluated after state changes. The docs do not specify keyed reconciliation. Assume position-based updates unless runtime source proves keyed behavior. Use stable, small item markup and avoid depending on preserved local DOM state inside loop items.
111
+
112
+ ## Performance Characteristics
113
+
114
+ Cost grows with item count and nested directive complexity. Deeply nested loops multiply render work. Event delegation keeps listener count low if handlers are registered on the component root.
115
+
116
+ ## Common Patterns
117
+
118
+ - Lists and menus.
119
+ - Rendering object maps with `$key`.
120
+ - Combining with `html-if` inside the repeated item.
121
+
122
+ ## Anti-patterns
123
+
124
+ - Large or nested loops without pagination, virtualization, or static boundaries.
125
+ - Directly binding listeners to every item after render.
126
+ - Performing filtering/sorting inside the directive expression on every update.
127
+
128
+ ## Edge Cases
129
+
130
+ - Missing properties render as empty/undefined values depending on expression context.
131
+ - Nested `html-if` can leave an otherwise repeated item empty, as shown in the docs.
132
+
133
+ ## Example
134
+
135
+ ```html
136
+ <my-component>
137
+ <ul>
138
+ <li html-for="item in list">
139
+ <span html-if="item.show">
140
+ {{ item.name }}
141
+ {{ $index }}
142
+ </span>
143
+ </li>
144
+ </ul>
145
+ </my-component>
146
+ ```
147
+
148
+ ```ts
149
+ state.set({
150
+ list: [
151
+ { name: 'Hello', show: true },
152
+ { name: 'Clark', show: true },
153
+ { name: 'Kent' }
154
+ ]
155
+ })
156
+ ```
157
+
158
+ ## Internal Notes
159
+
160
+ Docs explicitly support arrays and objects and mention `$index` and `$key`. Keyed diffing is not documented.
161
+
162
+ # html-inner
163
+
164
+ ## Purpose
165
+
166
+ Set an element's inner text/content from a state expression while allowing fallback HTML content before JavaScript mounts.
167
+
168
+ ## Syntax
169
+
170
+ ```html
171
+ <strong html-inner="name">Some default value</strong>
172
+ ```
173
+
174
+ ## Parameters
175
+
176
+ - Expression string evaluated against the render scope.
177
+
178
+ ## Rendering Behavior
179
+
180
+ Equivalent in purpose to `{{ }}` interpolation but targeted at a specific element.
181
+
182
+ ## DOM Behavior
183
+
184
+ After mount, the element's existing child content is replaced with the expression result.
185
+
186
+ ## Update Behavior
187
+
188
+ Re-evaluated when state changes. The element remains stable while its content changes.
189
+
190
+ ## Performance Characteristics
191
+
192
+ Lower structural cost than replacing a whole branch. Best for scalar text or simple content.
193
+
194
+ ## Common Patterns
195
+
196
+ - Counters.
197
+ - Labels with server-rendered fallback content.
198
+ - Progressive enhancement where the pre-JS content should be meaningful.
199
+
200
+ ## Anti-patterns
201
+
202
+ - Injecting untrusted HTML.
203
+ - Using for complex nested markup that should be represented as explicit HTML/directives.
204
+
205
+ ## Edge Cases
206
+
207
+ - Existing fallback content is visible until Jails mounts.
208
+ - If expression is `null` or `undefined`, output should be treated as empty or literal based on runtime behavior; avoid ambiguous values.
209
+
210
+ ## Example
211
+
212
+ ```html
213
+ <hello-world>
214
+ <button class="btn add">+</button>
215
+ <span html-inner="counter">0</span>
216
+ <button class="btn subtract">-</button>
217
+ </hello-world>
218
+ ```
219
+
220
+ ## Internal Notes
221
+
222
+ Docs state it "does exactly what `{{ }}` does" but outputs into a specific element.
223
+
224
+ # html-model
225
+
226
+ ## Purpose
227
+
228
+ Provide initial state from markup for a component instance.
229
+
230
+ ## Syntax
231
+
232
+ ```html
233
+ <my-component html-model="{ counter: 5 }">
234
+ <p>{{ counter }}</p>
235
+ </my-component>
236
+ ```
237
+
238
+ ## Parameters
239
+
240
+ - JavaScript object expression.
241
+
242
+ ## Rendering Behavior
243
+
244
+ Initial state includes values from `html-model`. Docs state it overrides props from the current `model`.
245
+
246
+ ## DOM Behavior
247
+
248
+ The directive is an initialization mechanism. It is not rendered as a normal application attribute after Jails processes directives.
249
+
250
+ ## Update Behavior
251
+
252
+ Used at component bootstrap. Later updates should use `state.set()` or parent props.
253
+
254
+ ## Performance Characteristics
255
+
256
+ Cheap. Good for per-instance configuration without additional JavaScript modules.
257
+
258
+ ## Common Patterns
259
+
260
+ - Initial counter values.
261
+ - Per-component options from server-rendered HTML.
262
+
263
+ ## Anti-patterns
264
+
265
+ - Storing large serialized payloads in HTML attributes.
266
+ - Treating `html-model` as reactive after mount.
267
+
268
+ ## Edge Cases
269
+
270
+ - Syntax must be a valid JavaScript expression, not strict JSON only.
271
+ - Prefer `data-*` plus function `model` when values need explicit parsing.
272
+
273
+ ## Example
274
+
275
+ ```html
276
+ <my-component html-model="{ counter: 5 }">
277
+ <span html-inner="counter"></span>
278
+ </my-component>
279
+ ```
280
+
281
+ ## Internal Notes
282
+
283
+ Function models receive `initialState`, which is documented as retrieved from `html-model`.
284
+
285
+ # html-*
286
+
287
+ ## Purpose
288
+
289
+ Bind standard HTML attributes to JavaScript expressions while keeping inactive attributes quiet before JavaScript loads.
290
+
291
+ ## Syntax
292
+
293
+ ```html
294
+ <img html-src="imageUrl" alt="">
295
+ <div html-class="loading ? 'is-loading' : ''"></div>
296
+ <button html-disabled="isSaving">Save</button>
297
+ ```
298
+
299
+ ## Parameters
300
+
301
+ - Attribute name after `html-`: the real DOM attribute to write.
302
+ - Expression string: value to evaluate.
303
+
304
+ ## Rendering Behavior
305
+
306
+ Jails evaluates the expression and writes the real attribute after stripping the `html-` prefix.
307
+
308
+ ## DOM Behavior
309
+
310
+ The source directive attribute is not intended to remain as the final public attribute. Boolean attributes are present only for truthy values and stripped for falsy values. Documented boolean attributes include `selected`, `checked`, `readonly`, `disabled`, and `autoplay`.
311
+
312
+ ## Update Behavior
313
+
314
+ Re-evaluated after state changes. Attribute values change on the same element.
315
+
316
+ ## Performance Characteristics
317
+
318
+ Efficient for scalar attributes. Use `html-src` to avoid premature network requests before JavaScript has valid URLs.
319
+
320
+ ## Common Patterns
321
+
322
+ - Conditional classes.
323
+ - Delayed `src` values for images/iframes.
324
+ - Boolean form states.
325
+
326
+ ## Anti-patterns
327
+
328
+ - Using `html-class` for very complex class composition inside markup.
329
+ - Assuming falsy boolean attributes remain with `"false"` values.
330
+
331
+ ## Edge Cases
332
+
333
+ - Boolean attributes differ from string attributes: falsy removes the attribute.
334
+ - Attribute change listeners can observe changes with `on('[src]', 'iframe', callback)`.
335
+
336
+ ## Example
337
+
338
+ ```html
339
+ <my-component html-class="loading ? 'is-loading' : ''">
340
+ <img html-src="imageUrl" alt="">
341
+ </my-component>
342
+ ```
343
+
344
+ ## Internal Notes
345
+
346
+ Docs explicitly say all `html-*` attributes accept JavaScript expressions and the template system strips the prefix.
347
+
348
+ # html-static
349
+
350
+ ## Purpose
351
+
352
+ Create a static DOM region that Jails skips during virtual DOM updates/diffing.
353
+
354
+ ## Syntax
355
+
356
+ ```html
357
+ <div class="swiper" html-static>...</div>
358
+ <input type="number" value="1" html-static>
359
+ ```
360
+
361
+ ## Parameters
362
+
363
+ No value required.
364
+
365
+ ## Rendering Behavior
366
+
367
+ The marked node and all children are excluded from Jails template updates after recognition.
368
+
369
+ ## DOM Behavior
370
+
371
+ The browser, user input, or third-party library may mutate the subtree without Jails reconciling it back to template state. The node remains in DOM unless surrounding non-static directives remove it.
372
+
373
+ ## Update Behavior
374
+
375
+ State updates skip the marked subtree. Directives and mustache expressions inside `html-static` should be treated as inert after the static boundary.
376
+
377
+ ## Performance Characteristics
378
+
379
+ Reduces diff work for large immutable regions and prevents conflict with libraries that mutate DOM. Useful for form controls where browser-managed value persistence is desired.
380
+
381
+ ## Common Patterns
382
+
383
+ - Third-party widgets such as Swiper or Chart.js wrappers.
384
+ - Inputs, textareas, and selects whose live value should be browser-owned.
385
+ - Static server-rendered markup inside an otherwise reactive component.
386
+
387
+ ## Anti-patterns
388
+
389
+ - Placing dynamic text inside `html-static` and expecting it to update.
390
+ - Marking the entire component static when only one widget subtree needs protection.
391
+ - Mixing Jails-managed state writes with third-party mutation on the same DOM nodes.
392
+
393
+ ## Edge Cases
394
+
395
+ - If an ancestor `html-if` removes the static node, the static subtree is still detached.
396
+ - Events from static children still bubble to component delegated listeners unless stopped.
397
+
398
+ ## Example
399
+
400
+ ```html
401
+ <app-swiper>
402
+ <input type="number" value="1" min="1" max="9" html-static>
403
+ <p>Chosen page: {{ page }}</p>
404
+ <div class="swiper mySwiper" html-static>
405
+ <div class="swiper-wrapper">
406
+ <div class="swiper-slide">Slide 1</div>
407
+ </div>
408
+ </div>
409
+ </app-swiper>
410
+ ```
411
+
412
+ ```ts
413
+ import Swiper from 'swiper'
414
+
415
+ export default function appSwiper({ main, on, elm, state }) {
416
+ const wrapper = elm.querySelector('.swiper')
417
+ const swiper = new Swiper(wrapper)
418
+
419
+ main(() => {
420
+ on('input', 'input[type=number]', goTo)
421
+ })
422
+
423
+ const goTo = e => {
424
+ const page = Number(e.target.value) || 1
425
+ swiper.slideTo(page - 1)
426
+ state.set({ page })
427
+ }
428
+ }
429
+
430
+ export const model = {
431
+ page: 1
432
+ }
433
+ ```
434
+
435
+ ## Internal Notes
436
+
437
+ Docs explicitly state `html-static` bypasses DOM diffing and skips virtual DOM updates for the specified node and children.
438
+
439
+ # mustache interpolation
440
+
441
+ ## Purpose
442
+
443
+ Insert expression results into text positions in component HTML.
444
+
445
+ ## Syntax
446
+
447
+ ```html
448
+ <p>Hello, {{ name }}</p>
449
+ ```
450
+
451
+ ## Parameters
452
+
453
+ - Expression between configured delimiters. Default delimiters are `{{` and `}}`.
454
+
455
+ ## Rendering Behavior
456
+
457
+ Expression result is written into the rendered text/content position.
458
+
459
+ ## DOM Behavior
460
+
461
+ The text node content changes when the expression result changes.
462
+
463
+ ## Update Behavior
464
+
465
+ Re-evaluated after state updates. Delimiters can be changed globally with `templateConfig({ tags: ['@{', '}'] })`.
466
+
467
+ ## Performance Characteristics
468
+
469
+ Good for scalar output. Prefer derived values in `view` for formatting.
470
+
471
+ ## Common Patterns
472
+
473
+ - Labels, counters, names.
474
+ - Displaying `$index` inside loops.
475
+
476
+ ## Anti-patterns
477
+
478
+ - Large logic expressions.
479
+ - Expressions with side effects.
480
+
481
+ ## Edge Cases
482
+
483
+ - Markers may be visible before JavaScript mounts unless placed inside native `<template>` or replaced by `html-inner` fallback.
484
+
485
+ ## Example
486
+
487
+ ```html
488
+ <p>Counter: {{ counter }}</p>
489
+ ```
490
+
491
+ ## Internal Notes
492
+
493
+ Docs state directives and mustache delimiters process values as valid JavaScript expressions.
494
+
495
+ # template element
496
+
497
+ ## Purpose
498
+
499
+ Hide markup from initial page rendering until Jails or application logic needs it.
500
+
501
+ ## Syntax
502
+
503
+ ```html
504
+ <template>
505
+ <div html-if="userData">Welcome, {{ userData.name }}!</div>
506
+ </template>
507
+ ```
508
+
509
+ ## Parameters
510
+
511
+ Native HTML `<template>` content.
512
+
513
+ ## Rendering Behavior
514
+
515
+ The browser does not render `<template>` contents directly. Jails leverages this native behavior to prevent unresolved markers from appearing on initial load.
516
+
517
+ ## DOM Behavior
518
+
519
+ Content remains inert in the template until cloned/processed by the template system.
520
+
521
+ ## Update Behavior
522
+
523
+ Use inside component trees for data-dependent fragments that should not appear before data is available.
524
+
525
+ ## Performance Characteristics
526
+
527
+ Improves first paint correctness by preventing placeholder flash. It does not itself optimize later diff cost unless combined with conditional/static directives.
528
+
529
+ ## Common Patterns
530
+
531
+ - Data-dependent user panels.
532
+ - Fragments that should not show mustache placeholders before mount.
533
+
534
+ ## Anti-patterns
535
+
536
+ - Wrapping all component HTML in `<template>` when SSR-visible content should appear immediately.
537
+
538
+ ## Edge Cases
539
+
540
+ - Native template content is not displayed by the browser, so accessibility content inside it is unavailable until rendered.
541
+
542
+ ## Example
543
+
544
+ ```html
545
+ <my-component>
546
+ <h1>Server-rendered heading</h1>
547
+ <template>
548
+ <div html-if="userData">Welcome, {{ userData.name }}!</div>
549
+ </template>
550
+ </my-component>
551
+ ```
552
+
553
+ ## Internal Notes
554
+
555
+ This is native HTML behavior intentionally reused by Jails.
556
+