litewire 1.0.2 → 1.0.3

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 (2) hide show
  1. package/README.MD +89 -22
  2. package/package.json +1 -1
package/README.MD CHANGED
@@ -1,8 +1,13 @@
1
- # Litewire 1.0.2
1
+ # Litewire 1.0.3
2
2
 
3
- Litewire is a browser-side HTML-over-the-wire library. It binds requests and
4
- reactive behaviors to HTML attributes, swaps server-rendered HTML into the
5
- page, and can load ES module components on demand.
3
+ Litewire is a small browser-side HTML-over-the-wire library. It binds HTTP
4
+ requests, reactive state, and event expressions to HTML attributes, swaps
5
+ server-rendered HTML into the page, and can load ES module components on
6
+ demand.
7
+
8
+ Version 1.0.3 adds reactive `lw:class` bindings, iterable lists with
9
+ `template[lw:for]`, and event-triggered component mounting. It also improves
10
+ radio model initialization and browser-history markup restoration.
6
11
 
7
12
  ## Contents
8
13
 
@@ -10,6 +15,7 @@ page, and can load ES module components on demand.
10
15
  - [Configuration](#configuration)
11
16
  - [AJAX requests](#ajax-requests)
12
17
  - [Reactive state and bindings](#reactive-state-and-bindings)
18
+ - [Lists](#lists)
13
19
  - [Dynamic components](#dynamic-components)
14
20
  - [HTML swaps and DOM updates](#html-swaps-and-dom-updates)
15
21
  - [Browser history](#browser-history)
@@ -34,10 +40,10 @@ continues scanning elements added later.
34
40
 
35
41
  ### Use the npm package
36
42
 
37
- If version 1.0.2 is available from your configured npm registry:
43
+ Install version 1.0.3 from your configured npm registry:
38
44
 
39
45
  ```sh
40
- npm install litewire@1.0.2
46
+ npm install litewire@1.0.3
41
47
  ```
42
48
 
43
49
  Import the package from your application's JavaScript entry point:
@@ -162,9 +168,9 @@ the element is scanned:
162
168
 
163
169
  ## Reactive state and bindings
164
170
 
165
- Litewire 1.0.2 adds a small reactive layer using `lw:state`, `lw:model`,
166
- `lw:text`, `lw:show`, and event-expression attributes. The colon in these
167
- attribute names is intentional.
171
+ Litewire provides a small reactive layer using `lw:state`, `lw:model`,
172
+ `lw:text`, `lw:show`, `lw:class`, `lw:for`, and event-expression attributes.
173
+ The colon in these attribute names is intentional.
168
174
 
169
175
  ### Local state
170
176
 
@@ -181,9 +187,10 @@ object:
181
187
  ```
182
188
 
183
189
  Assignments and deletions of top-level state properties trigger rendering of
184
- descendant `lw:text` and `lw:show` bindings owned by that state root. State is
185
- shallowly reactive: mutating a nested object or array in place does not itself
186
- trigger a render. Replace the top-level property to trigger one, for example
190
+ bindings on that element and its descendants that belong to that state root.
191
+ State is shallowly reactive:
192
+ mutating a nested object or array in place does not itself trigger a render.
193
+ Replace the top-level property to trigger one, for example
187
194
  `settings = { ...settings, enabled: false }`.
188
195
 
189
196
  Nested `lw:state` elements establish their own state scope. A binding uses the
@@ -196,10 +203,38 @@ global models instead.
196
203
  text. `null` and `undefined` render as an empty string.
197
204
  - `lw:show="expression"` sets the element's `hidden` property based on the
198
205
  truthiness of the result.
206
+ - `lw:class="{ className: expression }"` adds each class whose expression is
207
+ truthy and removes classes previously managed by this binding when they
208
+ become false. Other classes on the element are left alone; a key may contain
209
+ multiple space-separated class names.
199
210
 
200
211
  Expressions are evaluated when the element is first scanned and again when
201
- their owning local state renders. Global model updates also update matching
202
- `lw:text` bindings.
212
+ their owning local state renders. Global model updates refresh matching
213
+ `lw:text` bindings and reevaluate global `lw:class` bindings and loops.
214
+
215
+ ### Lists
216
+
217
+ Use `lw:for` on a `<template>` to repeat its contents for each value in an
218
+ iterable. The repeated expressions can access the item name and `$index`;
219
+ `(item, index)` also declares a named index:
220
+
221
+ ```html
222
+ <ul lw:state="{ items: ['Apples', 'Pears'] }">
223
+ <template lw:for="(item, index) of items">
224
+ <li>
225
+ <span lw:text="index + 1"></span>.
226
+ <span lw:text="item"></span>
227
+ </li>
228
+ </template>
229
+ </ul>
230
+ ```
231
+
232
+ The expression must evaluate to an iterable, such as an array, string, `Set`,
233
+ or `Map`; `null` and `undefined` render no rows. Assign a new array to the
234
+ top-level state property to refresh the list. Litewire recreates the repeated
235
+ DOM when the owning state renders; it does not key or preserve individual rows
236
+ across updates. `lw:for` also works with global models set through
237
+ `litewire.setModel()`.
203
238
 
204
239
  ### Form models
205
240
 
@@ -216,7 +251,8 @@ their owning local state renders. Global model updates also update matching
216
251
  The default `lw:model` and `lw:model.live` listen for `input`.
217
252
  `lw:model.change` listens for `change`, and `lw:model.blur` listens for `blur`.
218
253
  For checkboxes, the model value is a boolean; for radio inputs, it is the
219
- checked value or `null`; other controls use their value.
254
+ checked value or `null`. Unchecked radio buttons do not initialize or overwrite
255
+ the shared model; other controls use their value.
220
256
 
221
257
  Without a local `lw:state` root, models are stored globally and can be read or
222
258
  written with the instance methods `litewire.getModel(name)` and
@@ -271,6 +307,10 @@ Supported event modifiers:
271
307
  | `.throttle` | Runs at most once per 250 ms |
272
308
 
273
309
  Modifiers can be combined, for example `lw:click.prevent.once="save()"`.
310
+ Debounce and throttle delays can be customized in milliseconds, for example
311
+ `lw:input.debounce.400ms="search()"` or
312
+ `lw:click.throttle.1000ms="refresh()"`. `.outside` listens at the document
313
+ level so it can observe events outside the element.
274
314
 
275
315
  ## Dynamic components
276
316
 
@@ -297,7 +337,30 @@ export default class Greeting {
297
337
  ```
298
338
 
299
339
  New components inserted by a swap or added to the document are discovered
300
- automatically. A given element is mounted only once.
340
+ automatically. By default, and with `lw-trigger="load"`, a component mounts
341
+ when discovered. Set `lw-trigger` to another event name to defer mounting
342
+ until that event fires. On a triggered component, `lw-target` optionally
343
+ selects the element passed to the component constructor; the component path
344
+ and `data-*` parameters still come from the element carrying `lw-component`.
345
+ A component is mounted only once after a successful mount. To load one after
346
+ an event and mount it into another element, put `lw-trigger` and `lw-target`
347
+ on the component source:
348
+
349
+ ```html
350
+ <button
351
+ type="button"
352
+ lw-component="components/widget.js"
353
+ lw-trigger="click"
354
+ lw-target="#widget"
355
+ data-mode="compact"
356
+ >
357
+ Load widget
358
+ </button>
359
+ <div id="widget"></div>
360
+ ```
361
+
362
+ The module path and `data-*` parameters come from the element carrying
363
+ `lw-component`; `lw-target` is the element passed to the component.
301
364
 
302
365
  ## HTML swaps and DOM updates
303
366
 
@@ -332,11 +395,13 @@ a custom URL as the attribute value:
332
395
  </a>
333
396
  ```
334
397
 
335
- Litewire stores the URL, target selector, and target HTML in history state.
336
- When navigating with Back or Forward, it restores cached HTML when the state
337
- contains a selector and markup and the target still exists. Otherwise it
338
- attempts to fetch the stored URL. This caches only the selected target's HTML,
339
- not the complete document or JavaScript state.
398
+ Litewire stores the URL, target selector, swap type, and target markup in
399
+ history state. When it creates the initial history entry, it saves the current
400
+ markup so Back can restore the prior view. For `outerHTML`, cached markup
401
+ includes the target element itself. When navigating with Back or Forward,
402
+ Litewire restores cached markup when the target still exists; otherwise it
403
+ attempts to fetch the stored URL. This caches only the selected target's
404
+ markup, not the complete document or JavaScript state.
340
405
 
341
406
  ## Lifecycle events
342
407
 
@@ -387,7 +452,7 @@ untrusted user input.
387
452
  | Attribute / API | Description |
388
453
  |---|---|
389
454
  | `lw-get`, `lw-post`, `lw-put`, `lw-delete` | Request path and HTTP method |
390
- | `lw-trigger` | Event name; defaults to `click` or form `submit`; `load` runs immediately |
455
+ | `lw-trigger` | Request event (defaults to `click` or form `submit`; `load` runs on scan); for components, event to defer mounting |
391
456
  | `lw-target` | CSS selector for the response target |
392
457
  | `lw-swap` | `innerHTML`, `outerHTML`, `prepend`, or `append` |
393
458
  | `lw-indicator` | CSS selector for loading indicators |
@@ -397,6 +462,8 @@ untrusted user input.
397
462
  | `lw:model`, `.live`, `.change`, `.blur` | Bind a form control to a state or global model |
398
463
  | `lw:text` | Render an expression as text |
399
464
  | `lw:show` | Toggle the element's `hidden` property from an expression |
465
+ | `lw:class` | Add or remove classes reactively from an object expression |
466
+ | `template[lw:for]` | Repeat template contents for an iterable expression; item and index variables are available to bindings |
400
467
  | `lw:click`, `lw:input`, `lw:change`, `lw:submit`, `lw:keydown`, `lw:keyup`, `lw:focus`, `lw:blur` | Evaluate an expression in response to an event; supports the modifiers documented above |
401
468
  | `litewire.getModel(name)` | Read a global model |
402
469
  | `litewire.setModel(name, value)` | Set a global model and update matching bindings |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litewire",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A lightweight HTML-driven request engine with reactive state and dynamic ES module components.",
5
5
  "main": "./litewire.js",
6
6
  "module": "./litewire.js",