@loadbare/app 0.25.0 → 0.26.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 (55) hide show
  1. package/dist/build/assemble.d.ts +1 -2
  2. package/dist/build/assemble.d.ts.map +1 -1
  3. package/dist/build/assemble.js +11 -53
  4. package/dist/build/assemble.js.map +1 -1
  5. package/dist/build/cli.d.ts +4 -10
  6. package/dist/build/cli.d.ts.map +1 -1
  7. package/dist/build/cli.js +11 -33
  8. package/dist/build/cli.js.map +1 -1
  9. package/dist/build/declared.js +1 -1
  10. package/dist/build/declared.js.map +1 -1
  11. package/dist/core/lb-constants.d.ts +8 -18
  12. package/dist/core/lb-constants.d.ts.map +1 -1
  13. package/dist/core/lb-constants.js +32 -72
  14. package/dist/core/lb-constants.js.map +1 -1
  15. package/dist/core/lb-types.d.ts +12 -11
  16. package/dist/core/lb-types.d.ts.map +1 -1
  17. package/dist/core/lb-types.js +7 -0
  18. package/dist/core/lb-types.js.map +1 -1
  19. package/dist/hub/lb-apply.d.ts +10 -37
  20. package/dist/hub/lb-apply.d.ts.map +1 -1
  21. package/dist/hub/lb-apply.js +139 -522
  22. package/dist/hub/lb-apply.js.map +1 -1
  23. package/dist/hub/lb-hub.browser.d.ts.map +1 -1
  24. package/dist/hub/lb-hub.browser.js +115 -126
  25. package/dist/hub/lb-hub.browser.js.map +1 -1
  26. package/dist/hub/lb-lifecycle.d.ts +2 -2
  27. package/dist/hub/lb-lifecycle.d.ts.map +1 -1
  28. package/dist/hub/lb-lifecycle.js +9 -17
  29. package/dist/hub/lb-lifecycle.js.map +1 -1
  30. package/dist/server/lb-express.d.ts.map +1 -1
  31. package/dist/server/lb-express.js +3 -3
  32. package/dist/server/lb-express.js.map +1 -1
  33. package/dist/server/lb-server.d.ts +35 -19
  34. package/dist/server/lb-server.d.ts.map +1 -1
  35. package/dist/server/lb-server.js +141 -88
  36. package/dist/server/lb-server.js.map +1 -1
  37. package/docs/binding-cases.md +150 -0
  38. package/docs/comparison.md +18 -29
  39. package/docs/miswarts.md +2 -2
  40. package/docs/reference/css.md +2 -15
  41. package/docs/reference/custom-elements.md +6 -8
  42. package/docs/reference/data-binding.md +37 -180
  43. package/docs/reference/names.md +10 -26
  44. package/docs/reference/page-files.md +1 -12
  45. package/docs/reference/server.md +0 -1
  46. package/docs/testing.md +2 -5
  47. package/package.json +1 -1
  48. package/skills/loadbare-app/SKILL.md +52 -54
  49. package/skills/loadbare-app/references/css.md +2 -15
  50. package/skills/loadbare-app/references/custom-elements.md +6 -8
  51. package/skills/loadbare-app/references/data-binding.md +37 -180
  52. package/skills/loadbare-app/references/miswarts.md +2 -2
  53. package/skills/loadbare-app/references/names.md +10 -26
  54. package/skills/loadbare-app/references/page-files.md +1 -12
  55. package/skills/loadbare-app/references/server.md +0 -1
@@ -268,7 +268,7 @@ Each direction has one mechanism for each kind of message:
268
268
 
269
269
  | Direction | What | How | Today |
270
270
  |----------------|--------------------------------------------|-----------------------------|-------|
271
- | Hub to element | State that lasts | An attribute the hub stamps | `lb-column-value`, `lb-key-value`, `lb-query-row-count`, `lb-query-unplaced-count`, `lb-query-order`, `lb-group-*`, `lb-row-*`, `lb-request-pending`, `lb-request-error`, `lb-request-refused` |
271
+ | Hub to element | State that lasts | An attribute the hub stamps | `lb-column-value`, `lb-key-value`, `lb-query-row-count`, `lb-query-unplaced-count`, `lb-query-order`, `lb-row-*`, `lb-request-pending`, `lb-request-error`, `lb-request-refused` |
272
272
  | Hub to element | State the platform already names | A property | A control's `value` |
273
273
  | Hub to element | What the hub did | An optional `lb` method | `lbAttached`, `lbRowsLanded`, `lbRequestDone`, `lbDetached` |
274
274
  | Hub to element | A moment an element started | A bubbling event | `lb-request-done` |
@@ -315,11 +315,11 @@ customElements.define("note-popup", NotePopup);
315
315
  | `lbRequestDone(detail, origin)` | After a request committed by the element, or inside it, has finished |
316
316
  | `lbDetached()` | Once, after it removes the element |
317
317
 
318
- The hub places an element when it starts up the chrome, shows a page,
319
- creates a live row, or builds a group. It places the chrome and a page as
318
+ The hub places an element when it starts up the chrome, shows a page, or
319
+ creates a live row. It places the chrome and a page as
320
320
  the page's first answer lands, or once that round trip fails, so an element
321
321
  in either hears `lbAttached` with the page's data in place. It removes an
322
- element when a live row or a group has finished leaving, and when it shows
322
+ element when a live row has finished leaving, and when it shows
323
323
  another page in place of the one holding it. Write setup in `lbAttached` and its undoing in
324
324
  `lbDetached`; the two pair exactly, so neither guards against running
325
325
  twice.
@@ -633,8 +633,7 @@ had there hears the event, and no custom element the hub has removed hears
633
633
 
634
634
  The hub lands every row template itself, places every row by the query's
635
635
  order (see [Placing by hand](./data-binding.md#placing-by-hand)
636
- for when it does not), and builds every group the markup's group templates describe; see
637
- [Order](./data-binding.md#order) and [Groups](./data-binding.md#groups). A
636
+ for when it does not). A
638
637
  plain element carrying `lb-query` with a row template inside it needs no
639
638
  code, so a custom element holds rows only to do something with them once
640
639
  they land.
@@ -662,8 +661,7 @@ Everything else is the hub's:
662
661
  | Cloning | Clones the row template once per new key |
663
662
  | Matching | Fills the live row already showing that key, when its values changed |
664
663
  | Placing | Places every live row by the user's order or the query's, and leaves them where they stand for an answer under `lb-manual` |
665
- | Filtering | Hides a row the user's filter does not pass, and a group whose rows are all hidden |
666
- | Grouping | Builds a group where the order breaks, keeps it while its run goes on, and removes it with its last row |
664
+ | Filtering | Hides a row the user's filter does not pass |
667
665
  | Removing | Marks the live rows the response says are gone as leaving, and removes them |
668
666
  | Stamping | Stamps each live row with `lb-row-live`, `lb-key-value`, and what happened to it |
669
667
  | Counting | Stamps `lb-query-row-count` with the number of live rows showing, `lb-query-unplaced-count` with the number out of place, and `lb-query-order` with the order placing them |
@@ -2,7 +2,7 @@
2
2
 
3
3
  A page shows server data by naming queries and columns in its HTML, and asks
4
4
  the server to change that data by naming requests. The developer writes
5
- eighteen `lb-` attributes. The server declares every query a page may show and
5
+ fourteen `lb-` attributes. The server declares every query a page may show and
6
6
  every request it may send, and refuses anything it has not declared.
7
7
 
8
8
  Everything is a query. A query is a name for rows, of kind `row` or `rows`,
@@ -48,10 +48,6 @@ each with its key, and permits the three requests on `roster`; see
48
48
  | `lb-show` | Any element but `<template>` | The column that decides whether it is present |
49
49
  | `lb-order` | An element with `lb-query` | The choice holding the user's order; see [Order](#order) |
50
50
  | `lb-filter` | An element with `lb-query` | The columns a choice filters; see [Filters](#filters) |
51
- | `lb-group` | A `<template>` | Nothing: it marks a group template; see [Groups](#groups) |
52
- | `lb-count` | Any element | Nothing: it shows a count of rows; see [Aggregates](#aggregates) |
53
- | `lb-sum`, `lb-avg`, `lb-min`, `lb-max` | Any element | The column aggregated; see [Aggregates](#aggregates) |
54
- | `lb-select` | A checkbox in a row template | Nothing: it selects its live row; see [Selecting rows](#selecting-rows) |
55
51
  | `lb-request` | Any element | The request it sends when it commits |
56
52
  | `lb-url-link` | An `<a>` | A link between pages; see [chrome](./chrome.md#links) |
57
53
  | `lb-url-parm` | An `<a lb-url-link>` in a row | Columns of the row its `href` carries as parms; see [chrome](./chrome.md#a-link-from-a-row) |
@@ -69,11 +65,9 @@ builder writes a stamp, and a stylesheet or a custom element reads it.
69
65
  | `lb-query-row-count` | The number of live rows an element shows |
70
66
  | `lb-query-unplaced-count` | The number of them out of place; see [Placing by hand](#placing-by-hand) |
71
67
  | `lb-query-order` | The order placing them; see [Order](#order) |
72
- | `lb-group-live`, `lb-group-column`, `lb-group-value` | A group, the column it breaks on, and its value; see [Groups](#groups) |
73
68
  | `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-unplaced` | What happened to a row; see [What happened to a row](#what-happened-to-a-row) |
74
- | `lb-row-leaving`, `lb-group-leaving` | A row or group on its way out |
69
+ | `lb-row-leaving` | A row on its way out |
75
70
  | `lb-row-editing` | The row a form is pointed at; see [Editing a row in one form](#editing-a-row-in-one-form) |
76
- | `lb-row-selected` | A row whose `lb-select` is ticked |
77
71
  | `lb-request-pending` | The element's request is in flight |
78
72
  | `lb-request-error` | The element's last request failed |
79
73
  | `lb-request-refused` | The handler refused it; see [Refusals](#refusals) |
@@ -92,8 +86,7 @@ elements as the page needs.
92
86
 
93
87
  What lands depends on the query's kind and on whether the element holds a
94
88
  row template, which is the first `<template>` among its descendants outside
95
- any nested `lb-query`, or, when that template is a [group
96
- template](#groups), the innermost template inside it:
89
+ any nested `lb-query`:
97
90
 
98
91
  | Kind | Row template | The hub |
99
92
  |--------|--------------|----------------------------------------|
@@ -332,8 +325,7 @@ form `--lb-edit` pointed at a row, or a form elsewhere on the page.
332
325
  | The answer | Under `lb-manual`, the row | Side |
333
326
  |----------------------------------------|---------------------------------------------------|----------|
334
327
  | Changes a column the order reads | Stays where it stands | `order` |
335
- | Creates a row | Goes after the last row of its group, or last of all | `order` |
336
- | Changes the column its group breaks on | Stays under its group's heading | `order` |
328
+ | Creates a row | Goes last | `order` |
337
329
  | Changes a row so the filter hides it | Stays showing | `filter` |
338
330
  | Drops a row | Leaves, under either side | |
339
331
 
@@ -394,11 +386,9 @@ its rows the user may filter, separated by commas. The column of
394
386
  </ul>
395
387
  ```
396
388
 
397
- A row that does not pass every filter is `hidden`, and a ticked `lb-select`
398
- in it is cleared. Under `lb-manual="filter"`, a row an answer changed stays
389
+ A row that does not pass every filter is `hidden`. Under `lb-manual="filter"`, a row an answer changed stays
399
390
  showing until the rows are placed again; see
400
- [Placing by hand](#placing-by-hand). A group whose rows are all hidden is hidden too
401
- ([miswart](../miswarts.md#rows-hidden-by-a-filter)). An empty
391
+ [Placing by hand](#placing-by-hand). An empty
402
392
  choice filters nothing.
403
393
 
404
394
  A filter is one or more terms, each an operator followed by a value:
@@ -431,96 +421,6 @@ column that is null or missing, pass only `!=`.
431
421
  `parseFilter`, `passes` and `passesTerm` in `@loadbare/app/types` are the
432
422
  rule the hub applies.
433
423
 
434
- ### Groups
435
-
436
- A group is a run of rows sharing the order's leading term. Write a
437
- `<template lb-group>` where the row template goes, holding the group's
438
- heading and one nested `<template>`: the next group template, or the row
439
- template. The nth group template breaks on the order's nth term.
440
-
441
- ```html
442
- <ul lb-query="roster">
443
- <template lb-group>
444
- <li>
445
- <h3 lb-column="team"></h3>
446
- <ul>
447
- <template><li lb-column="name"></li></template>
448
- </ul>
449
- </li>
450
- </template>
451
- </ul>
452
- ```
453
-
454
- The hub clones the group template where the order breaks, and the group's
455
- contents land immediately before the clone of its nested template, so the
456
- markup's nesting decides the shape:
457
-
458
- | The nested template is | The group's contents land | Example |
459
- |------------------------------|------------------------------------|-----------------------------------|
460
- | Inside the heading's element | Inside it | `<tbody>`, `<li>`, `<details>` |
461
- | Beside the heading | After the heading, as its siblings | A heading `<tr>` in one `<tbody>` |
462
-
463
- `<tbody>` and `<optgroup>` do not nest, so a table's levels below the first
464
- are heading rows beside their rows:
465
-
466
- ```html
467
- <table lb-query="accounts">
468
- <thead><tr><th>Account</th></tr></thead>
469
- <template lb-group>
470
- <tbody>
471
- <tr><th scope="rowgroup" lb-column="category"></th></tr>
472
- <template><tr><td lb-column="account_name"></td></tr></template>
473
- </tbody>
474
- </template>
475
- </table>
476
- ```
477
-
478
- Content after the nested template lands after the group's rows, which is
479
- where a group's footer goes.
480
-
481
- A heading is filled from its group's first row as an element in a row is,
482
- `href`s from `lb-url-parm` included, so it may show a column other than the
483
- one the group breaks on. Under `lb-manual="order"`, a row an answer
484
- moved to another group stays under its old heading, and the heading shows
485
- the row as it stood, until the rows are placed again. The hub stamps each top-level
486
- element of a group with `lb-group-live`, `lb-group-column` and
487
- `lb-group-value`. A row creates its group, and a group leaves with its last
488
- row. When the order changes, a group whose run goes on is kept and moved,
489
- and a group whose run ended leaves.
490
-
491
- A group template with no nested template is reported to the console. More
492
- group templates than the order has terms show each extra level as one
493
- group, and are reported once.
494
-
495
- ### Aggregates
496
-
497
- `lb-count`, `lb-sum="col"`, `lb-avg="col"`, `lb-min="col"` and
498
- `lb-max="col"` set an element from the rows of the nearest group around it,
499
- or of the whole list outside any group:
500
-
501
- ```html
502
- <tr><td><span lb-count></span> people</td><td lb-sum="salary"></td></tr>
503
- ```
504
-
505
- | Attribute | Sets the element to |
506
- |----------------|-----------------------------------------------------------|
507
- | `lb-count` | The number of rows |
508
- | `lb-sum="col"` | The sum of `col` |
509
- | `lb-avg="col"` | The average of `col` |
510
- | `lb-min="col"` | The least value of `col`, by the [order](#order)'s comparison |
511
- | `lb-max="col"` | The greatest, likewise |
512
-
513
- An aggregate lands as a column does, with `lb-column-value`. A sum and an
514
- average are exact decimals, read from JSON numbers and from strings holding
515
- a plain decimal, as Postgres sends `numeric`. A sum has as many places as
516
- the most precise value, and an average up to two more. `null` and empty
517
- values are left out, as SQL leaves them out, and any other value is left
518
- out and reported once. The result lands unformatted.
519
-
520
- An aggregate covers the rows showing, so a row a filter hides is left out.
521
- Where the true total matters beyond what the page shows, have the server
522
- answer it as a row.
523
-
524
424
  ### What happened to a row
525
425
 
526
426
  Every change to a list is one a stylesheet can see:
@@ -533,7 +433,6 @@ Every change to a list is one a stylesheet can see:
533
433
  | `lb-row-requested` | `created`, `changed` or `moved` by this page's request |
534
434
  | `lb-row-unplaced` | Stands where the order or the filter would not leave it |
535
435
  | `lb-row-leaving` | A row on its way out |
536
- | `lb-group-leaving` | A group on its way out |
537
436
 
538
437
  The hub touches a row when an answer names it. `lb-row-created`,
539
438
  `lb-row-changed` and `lb-row-moved` are cleared when it next does, and one
@@ -544,8 +443,8 @@ query, and set only by a landing that answers a request from the page.
544
443
  placed again; see
545
444
  [Placing by hand](#placing-by-hand).
546
445
 
547
- A row or a group that leaves loses `lb-row-live` or `lb-group-live`, takes
548
- `lb-row-leaving` or `lb-group-leaving` and `inert`
446
+ A row that leaves loses `lb-row-live`, takes
447
+ `lb-row-leaving` and `inert`
549
448
  ([miswart](../miswarts.md#leaving-rows-are-inert)), and is removed once its
550
449
  animations finish, at once when there are none.
551
450
 
@@ -569,7 +468,7 @@ The hub keeps each query's last answer until the page changes, with any
569
468
  patch since applied to it. An element that names a query and arrives after
570
469
  that query's answer is filled from what was kept, at the end of the landing
571
470
  that follows its arrival. Such an element is a picker in a new live row, or
572
- scaffolding around rows, such as a group's heading or a ghost row. So
471
+ scaffolding around rows, such as a ghost row. So
573
472
  a query nested in another query's rows need not land again, or land after
574
473
  the outer query, for a new outer row to show its choices.
575
474
 
@@ -637,8 +536,8 @@ answered side by side. A column never holds rows.
637
536
  ```
638
537
 
639
538
  Many masters, each with its own detail, is one `rows` query of joined rows:
640
- each detail row carries its master's columns. A [group template](#groups)
641
- shows each master as a group, ordered by the master's key first.
539
+ each detail row carries its master's columns, ordered by the master's key
540
+ first.
642
541
 
643
542
  A query nested in another query's row template receives the same rows in
644
543
  every live row. That serves a picker offering the same choices on every
@@ -753,8 +652,7 @@ Every request has one shape:
753
652
  ```
754
653
 
755
654
  The hub takes `query`, `key` and `values` from where the element sits, and
756
- sends each when it has one. A request acting on several rows carries `keys`
757
- in place of `key`; see [Selecting rows](#selecting-rows). The server runs the handler for the name and
655
+ sends each when it has one. The server runs the handler for the name and
758
656
  answers with response items, which land like any others.
759
657
 
760
658
  ### Committing
@@ -929,7 +827,7 @@ it, and sends nothing:
929
827
  Its controls start at their HTML defaults, and its `lb-show` branches are
930
828
  as for a row whose every column is null.
931
829
  - It stands after every row of the list, in the order added, and is not
932
- ordered, filtered or aggregated, since it holds no data. It counts in
830
+ ordered or filtered, since it holds no data. It counts in
933
831
  `lb-query-row-count`.
934
832
  - The form's submit carries it in `rows`, with `key: ""`, beside the rows on
935
833
  record: an insert while the master is not on record, an update once it
@@ -1012,7 +910,7 @@ nothing is not sent.
1012
910
  For a query the hub serves, `lb-url` or `lb-choices`, the hub answers
1013
911
  `lb-row-update` itself, with no round trip; see
1014
912
  [Query parms](./chrome.md#query-parms) and [Choices](#choices). The third,
1015
- `lb-hub`, takes no request.
913
+ `lb-hub-status`, takes no request.
1016
914
 
1017
915
  A key comes from a live row, or from an element a `row` landed on, so all
1018
916
  three work against either kind:
@@ -1118,6 +1016,27 @@ The rows a form's answer lands are placed by the list's `lb-manual`, as any
1118
1016
  answer's are, whether the form was pointed by Edit or by New; see
1119
1017
  [Placing by hand](#placing-by-hand).
1120
1018
 
1019
+ A list nested in the form follows the row the form is bound to. When Edit
1020
+ or New binds the form, the hub drops the list's rows not yet entered and
1021
+ asks the server for the list's query again, as the request `lb-read`, with
1022
+ the bound row's key added to the query string as the parm named for the
1023
+ form's key column. `contextFor` receives it among the parms, and the query
1024
+ reads it as it reads any parm, so one query serves a master the URL names
1025
+ and a master Edit binds. New sends the parm empty, and the query answers
1026
+ with no rows:
1027
+
1028
+ ```ts
1029
+ function contextFor(req: Request, parms: URLSearchParams): HubContext {
1030
+ return { db: openDb(), paycheck: parms.get("paycheck_id") ?? "" };
1031
+ }
1032
+
1033
+ deductions: rows("id", (ctx) => ctx.db.deductionsFor(ctx.paycheck)),
1034
+ ```
1035
+
1036
+ A form with no list inside it sends nothing when it is bound. An answer
1037
+ that returns after the form is bound to another row, or after the page
1038
+ moved on, lands nothing.
1039
+
1121
1040
  A successful request from the form lets it go, as Cancel does: the form
1122
1041
  empties, its controls return to their defaults, and the stamps go. A failed
1123
1042
  one leaves the form as the user had it, to correct.
@@ -1145,63 +1064,6 @@ outside a live row of the form's query, Edit for a key the hub holds no row
1145
1064
  for, and any of these three commands aimed at an element that is not a form
1146
1065
  carrying `lb-query`.
1147
1066
 
1148
- ### Selecting rows
1149
-
1150
- A checkbox carrying `lb-select` in a row template selects the live row it
1151
- sits in. It is not a column: it carries no `lb-column`, lands nothing and
1152
- is not gathered. The hub stamps the row `lb-row-selected` while it is
1153
- ticked.
1154
-
1155
- A request for the query that names no one row then acts on the rows
1156
- selected, and carries their keys as `keys`:
1157
-
1158
- ```html
1159
- <tbody lb-query="transactions">
1160
- <template>
1161
- <tr>
1162
- <td><input type="checkbox" lb-select lb-show="selecting" /></td>
1163
- <td lb-column="description"></td>
1164
- <td lb-column="amount"></td>
1165
- </tr>
1166
- </template>
1167
- </tbody>
1168
-
1169
- <form lb-query="transactions" lb-request="lb-row-update">
1170
- <lb-picker lb-query="accounts" lb-column="acct" exp-label="Account" exp-column="name"></lb-picker>
1171
- <button type="submit">Apply</button>
1172
- <button type="button" lb-request="lb-row-delete">Delete</button>
1173
- </form>
1174
- ```
1175
-
1176
- ```json
1177
- { "name": "lb-row-update", "query": "transactions", "keys": ["4", "9"], "values": { "acct": "12" } }
1178
- ```
1179
-
1180
- | Request | With rows selected | With none ticked |
1181
- |------------------|----------------------------------------|----------------------|
1182
- | `lb-row-update` | Sent with `keys` | Not sent |
1183
- | `lb-row-delete` | Sent with `keys` | Not sent |
1184
- | A declared one | Sent with `keys` | Sent with `keys: []` |
1185
- | `lb-row-insert` | Sent as ever; the selection is not its | Sent as ever |
1186
-
1187
- An update or delete with nothing ticked has nothing to act on, and nothing
1188
- is reported. A request from inside a row still names that row alone. The
1189
- server runs the page's `rowUpdate` or `rowDelete` once for each key, as for
1190
- each row alone, and refreshes once; see [crud](./page-files.md#crud).
1191
-
1192
- After the request succeeds, the hub clears the selection. A failed one
1193
- leaves it, to try again.
1194
-
1195
- Only a checkbox that is showing counts. Turning a selector off with
1196
- `lb-show` also clears its tick, so leaving a selecting mode abandons the
1197
- selection rather than keeping it out of sight. With every selector off, a
1198
- request for the query is an ordinary one again.
1199
-
1200
- Which rows are selected, and whether the page is in a selecting mode, is
1201
- interaction state. A mode the URL keeps, such as `?selecting=1`, reaches
1202
- the rows as a column the query computes from the parm, which `lb-show`
1203
- reads.
1204
-
1205
1067
  ### Declared requests
1206
1068
 
1207
1069
  A request name the page declares under `handlers` runs the application's
@@ -1331,7 +1193,7 @@ returns its controls to their defaults, and the hub removes
1331
1193
  `lb-column-value` from each of them. A cancelled reset keeps both.
1332
1194
 
1333
1195
  A page load that fails lands nothing and is reported to the console, and
1334
- the query `lb-hub` says so; see [The hub's state](./chrome.md#the-hubs-state).
1196
+ the query `lb-hub-status` says so; see [The hub's state](./chrome.md#the-hubs-state).
1335
1197
  A load
1336
1198
  started by a request for `lb-url` stamps the element that sent it, as any
1337
1199
  request stamps its element.
@@ -1392,7 +1254,7 @@ The developer writes `lb-` attributes in markup, and script never assigns
1392
1254
  them. The builder checks the markup of the chrome and of every page, after
1393
1255
  expansion, and refuses to build:
1394
1256
 
1395
- - an `lb-` attribute that is not one of the eighteen the developer writes;
1257
+ - an `lb-` attribute that is not one of the fourteen the developer writes;
1396
1258
  `lb-exp-slot` and `lb-exp-template` are consumed by expansion and never
1397
1259
  reach the check
1398
1260
  - `lb-request` naming an `lb-` request other than the three Loadbare provides
@@ -1420,16 +1282,11 @@ expansion, and refuses to build:
1420
1282
  no column
1421
1283
  - `lb-manual` on an element not carrying `lb-query`, or naming anything but
1422
1284
  `order`, `filter` or both
1423
- - `lb-select` on anything but `<input type="checkbox">`, outside a row
1424
- template, or beside `lb-column` or `lb-request`
1425
1285
  - a `command` beginning `--lb-` that is not one of the four commands
1426
1286
  - one of the four commands with no `commandfor`
1427
1287
  - `--lb-new` aimed at an element the markup holds that is neither a
1428
1288
  `<form>` nor a list carrying `lb-query` nested directly in a form's own
1429
1289
  query
1430
- - `lb-group` on anything but a `<template>`, or on one holding no
1431
- `<template>` for its contents
1432
- - an aggregate on a `<template>`, or any but `lb-count` naming no column
1433
1290
  - a chrome without exactly one `<lb-hub>` and exactly one `<main>`, a
1434
1291
  `<main>` outside `<lb-hub>`, or a `<main>` holding anything but whitespace
1435
1292
  - a page carrying an `<lb-hub>` or a `<main>`
@@ -14,10 +14,9 @@ that declares a query, a handler or a `crud` entry whose name begins with
14
14
 
15
15
  | Flag | Default | Names | Defined in |
16
16
  | ---------- | ------- | ----------------------------------------- | --------------------------------------------------- |
17
- | `--src` | `src` | The application's own tree, scanned whole | [Running the builder](./builder.md#running-the-builder) |
18
- | `--out` | `dist` | Where the builder writes | [Running the builder](./builder.md#running-the-builder) |
19
- | `--watch` | off | Rebuild on change under `--src` | [Running the builder](./builder.md#running-the-builder) |
20
- | `--minify` | off | Minify `client.js` and `app.css` | [Running the builder](./builder.md#running-the-builder) |
17
+ | `--src` | `src` | The application's own tree, scanned whole | [Running the builder](./builder.md) |
18
+ | `--out` | `dist` | Where the builder writes | [Running the builder](./builder.md) |
19
+ | `--minify` | off | Minify `client.js` and `app.css` | [Running the builder](./builder.md) |
21
20
 
22
21
  ## Reserved file names
23
22
 
@@ -66,7 +65,7 @@ A widget package declares these. An application never does.
66
65
 
67
66
  ## Attributes
68
67
 
69
- The developer writes eighteen attributes in pages and the chrome, and the
68
+ The developer writes fourteen attributes in pages and the chrome, and the
70
69
  builder refuses any other `lb-` attribute there. `lb-exp-slot` and
71
70
  `lb-exp-template` are written for expansion, which removes them before the
72
71
  check. The hub and the builder write the rest, as stamps, and script never
@@ -80,9 +79,6 @@ assigns one.
80
79
  | `lb-order` | Developer | [Order](./data-binding.md#order) |
81
80
  | `lb-filter` | Developer | [Filters](./data-binding.md#filters) |
82
81
  | `lb-manual` | Developer | [Placing by hand](./data-binding.md#placing-by-hand) |
83
- | `lb-group` | Developer | [Groups](./data-binding.md#groups) |
84
- | `lb-count`, `lb-sum`, `lb-avg`, `lb-min`, `lb-max` | Developer | [Aggregates](./data-binding.md#aggregates) |
85
- | `lb-select` | Developer | [Selecting rows](./data-binding.md#selecting-rows) |
86
82
  | `lb-request` | Developer | [Requests](./data-binding.md#requests) |
87
83
  | `lb-url-link` | Developer | [Links](./chrome.md#links) |
88
84
  | `lb-url-parm` | Developer | [A link from a row](./chrome.md#a-link-from-a-row) |
@@ -96,11 +92,9 @@ assigns one.
96
92
  | `lb-query-row-count` | Hub | [Counting rows](./data-binding.md#counting-rows) |
97
93
  | `lb-query-unplaced-count`, `lb-row-unplaced` | Hub | [Placing by hand](./data-binding.md#placing-by-hand) |
98
94
  | `lb-query-order` | Hub | [Order](./data-binding.md#order) |
99
- | `lb-group-live`, `lb-group-column`, `lb-group-value` | Hub | [Groups](./data-binding.md#groups) |
100
95
  | `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
101
- | `lb-row-leaving`, `lb-group-leaving` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
96
+ | `lb-row-leaving` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
102
97
  | `lb-row-editing` | Hub | [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
103
- | `lb-row-selected` | Hub | [Selecting rows](./data-binding.md#selecting-rows) |
104
98
  | `lb-request-pending` | Hub | [Request state](./data-binding.md#request-state) |
105
99
  | `lb-request-error` | Hub | [Request state](./data-binding.md#request-state) |
106
100
  | `lb-request-refused` | Hub | [Refusals](./data-binding.md#refusals) |
@@ -116,9 +110,9 @@ them, and a page declares none.
116
110
 
117
111
  | Query | Kind | Key | Columns | Defined in |
118
112
  | ------------ | ----- | --------- | --------------------------------------------------------------- | ------------------------------------- |
119
- | `lb-url` | `row` | `lb-path` | `lb-path`, `lb-page-label`, `lb-page-unknown`, every query parm | [The URL](./chrome.md#the-url) |
113
+ | `lb-url` | `row` | `lb-path` | `lb-path`, `lb-page-label`, every query parm | [The URL](./chrome.md#the-url) |
120
114
  | `lb-choices` | `row` | `lb-path` | `lb-path`, every choice | [Choices](./data-binding.md#choices) |
121
- | `lb-hub` | `row` | `lb-path` | `lb-path`, `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` | [The hub's state](./chrome.md#the-hubs-state) |
115
+ | `lb-hub-status` | `row` | `lb-path` | `lb-path`, `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` | [The hub's state](./chrome.md#the-hubs-state) |
122
116
 
123
117
  No query parm is reserved: a column of `lb-url` whose name begins with
124
118
  `lb-` is never a query parm.
@@ -202,13 +196,6 @@ imports them rather than writing a string.
202
196
  | `ATTR_QUERY_ROW_COUNT` | `lb-query-row-count` |
203
197
  | `ATTR_QUERY_UNPLACED_COUNT` | `lb-query-unplaced-count` |
204
198
  | `ATTR_QUERY_ORDER` | `lb-query-order` |
205
- | `ATTR_GROUP` | `lb-group` |
206
- | `ATTR_GROUP_LIVE` | `lb-group-live` |
207
- | `ATTR_GROUP_COLUMN` | `lb-group-column` |
208
- | `ATTR_GROUP_VALUE` | `lb-group-value` |
209
- | `LIVE_GROUP` | `[lb-group-live]`, the selector for a group's element |
210
- | `ATTR_COUNT`, `ATTR_SUM`, `ATTR_AVG`, `ATTR_MIN`, `ATTR_MAX` | `lb-count`, `lb-sum`, `lb-avg`, `lb-min`, `lb-max` |
211
- | `AGGREGATES` | All five aggregate attributes |
212
199
  | `ORDER_DESCENDING` | `-`, written before a column in an order |
213
200
  | `COLUMN_TYPES` | `number`, `boolean`, `text` |
214
201
  | `CHOICES_QUERY` | `lb-choices` |
@@ -224,7 +211,6 @@ imports them rather than writing a string.
224
211
  | `REQUESTED_CREATED`, `REQUESTED_CHANGED`, `REQUESTED_MOVED` | `created`, `changed`, `moved` |
225
212
  | `ATTR_ROW_UNPLACED` | `lb-row-unplaced` |
226
213
  | `ATTR_ROW_LEAVING` | `lb-row-leaving` |
227
- | `ATTR_GROUP_LEAVING` | `lb-group-leaving` |
228
214
  | `ATTR_REQUEST` | `lb-request` |
229
215
  | `LB_EVENT_NAME` | `lb-request`, the event every request travels as |
230
216
  | `LB_DONE_EVENT_NAME` | `lb-request-done` |
@@ -236,13 +222,12 @@ imports them rather than writing a string.
236
222
  | `LB_COMMANDS` | All four commands |
237
223
  | `LB_COMMAND_PREFIX` | `--lb-` |
238
224
  | `ATTR_ROW_EDITING` | `lb-row-editing` |
239
- | `ATTR_SELECT` | `lb-select` |
240
- | `ATTR_ROW_SELECTED` | `lb-row-selected` |
241
225
  | `LB_RESERVED_PREFIX` | `lb-` |
242
226
  | `REQUEST_ROW_INSERT` | `lb-row-insert` |
243
227
  | `REQUEST_ROW_UPDATE` | `lb-row-update` |
244
228
  | `REQUEST_ROW_DELETE` | `lb-row-delete` |
245
229
  | `LB_ROW_REQUESTS` | All three request names |
230
+ | `REQUEST_READ` | `lb-read`, the hub's own read of a bound form's lists; markup never writes it |
246
231
  | `LB_METHODS` | The four reserved methods |
247
232
  | `BROWSER_LIFECYCLE` | The browser callbacks the build refuses |
248
233
  | `KIND_ROW` | `row` |
@@ -250,8 +235,7 @@ imports them rather than writing a string.
250
235
  | `URL_QUERY` | `lb-url` |
251
236
  | `URL_COLUMN_PATH` | `lb-path` |
252
237
  | `URL_COLUMN_PAGE_LABEL` | `lb-page-label` |
253
- | `URL_COLUMN_PAGE_UNKNOWN` | `lb-page-unknown` |
254
- | `HUB_QUERY` | `lb-hub` |
238
+ | `HUB_QUERY` | `lb-hub-status` |
255
239
  | `HUB_COLUMN_LOAD_STATE` | `lb-load-state` |
256
240
  | `HUB_COLUMN_SERVER_STATE` | `lb-server-state` |
257
241
  | `HUB_COLUMN_ERROR` | `lb-error` |
@@ -268,7 +252,7 @@ imports them rather than writing a string.
268
252
  | `ATTR_EXP_TEMPLATE` | `lb-exp-template` |
269
253
  | `ATTR_PAGE` | `lb-page` |
270
254
  | `ATTR_PAGE_TITLE` | `lb-page-title` |
271
- | `DEVELOPER_ATTRIBUTES` | The eighteen attributes a developer writes |
255
+ | `DEVELOPER_ATTRIBUTES` | The fourteen attributes a developer writes |
272
256
  | `HUB_TAG_NAME` | `lb-hub` |
273
257
  | `LB_ENDPOINT` | `/lb` |
274
258
  | `LB_REQUEST_TIMEOUT_MS` | `10000` |
@@ -165,14 +165,11 @@ name:
165
165
  | `name` | The request name, from `lb-request` |
166
166
  | `query` | The query the request is for |
167
167
  | `key` | The key of the row the request is for |
168
- | `keys` | The keys of the rows selected, in place of `key` |
169
168
  | `rows` | A form's nested rows, by query: each `key` and `values` |
170
169
  | `values` | The gathered control values, by column |
171
170
 
172
171
  The hub sends `query`, `key` and `values` when it finds them; see
173
- [Gathering](./data-binding.md#gathering). It sends `keys` for a request that
174
- acts on the rows the user selected; see
175
- [Selecting rows](./data-binding.md#selecting-rows).
172
+ [Gathering](./data-binding.md#gathering).
176
173
 
177
174
  ### onPageEnter
178
175
 
@@ -264,12 +261,6 @@ are one vocabulary:
264
261
  | `lb-row-update` | `rowUpdate` | `query`, `key`, `values`, and `rows` from a form |
265
262
  | `lb-row-delete` | `rowDelete` | `query`, `key` |
266
263
 
267
- An `lb-row-update` or `lb-row-delete` carrying `keys` runs `rowUpdate` or
268
- `rowDelete` once for each key, with that key, so a handler written for one
269
- row serves several. The patches the runs return are laid together, and the
270
- refresh set runs once. A `url()` returned for one of several rows is
271
- reported and ignored. A declared request receives `keys` as it is.
272
-
273
264
  `rows` holds the rows of a query nested in the form the request came from,
274
265
  by query name, each with its `key` and the `values` of its own controls; see
275
266
  [A form over a set of rows](./data-binding.md#a-form-over-a-set-of-rows).
@@ -386,8 +377,6 @@ A change that seems to need a refresh usually has a patch:
386
377
  [order](./data-binding.md#order), or leaves it where it stands under the
387
378
  list's [`lb-manual`](./data-binding.md#placing-by-hand); a refresh would do
388
379
  the same.
389
- - A group that appears or goes: the hub makes a group with its first row
390
- and removes it with its last, so no row stands in for an empty one.
391
380
  - A row whose other columns change with the edit: re-read the row and patch
392
381
  it.
393
382
  - Rows the database removes with a deleted one: select their keys before the
@@ -199,7 +199,6 @@ interface HubRequest {
199
199
  name: string;
200
200
  query?: string;
201
201
  key?: string;
202
- keys?: string[];
203
202
  values?: Record<string, string>;
204
203
  rows?: Record<string, { key: string; values: Record<string, string> }[]>;
205
204
  }
package/docs/testing.md CHANGED
@@ -210,12 +210,11 @@ evidence here.
210
210
  is not counted
211
211
  - the order and the filter place all rows and a patch alike, except where
212
212
  the list's `lb-manual` leaves a side to the user, which keeps its rows
213
- standing and stamped until they are placed again; groups come and go with
214
- their rows to any depth, aggregates follow every landing, and every change
213
+ standing and stamped until they are placed again, and every change
215
214
  leaves a stamp a stylesheet can see (`lb-order.test.ts`)
216
215
  - a filter's text reads and passes values as documented, and a choice of
217
216
  order or filter places the rows already landed again, hiding rows and
218
- groups and leaving them out of counts and aggregates (`lb-choices.test.ts`)
217
+ leaving them out of counts (`lb-choices.test.ts`)
219
218
  - `lb-show` moves an element into a template and back, and landing reaches
220
219
  inside it
221
220
  - a row whose values arrive as it already shows them is not filled again,
@@ -296,8 +295,6 @@ What the hub is tested for here:
296
295
  queries land
297
296
  - a form pointed at a row by `commandfor` fills from the row the hub holds,
298
297
  and a row not yet entered sends no update or delete
299
- - ticked `lb-select` rows travel as `keys`, and the selection clears once
300
- the request succeeds
301
298
  - a refusal lands its message on the element that committed and on each
302
299
  control it names
303
300
  - `lb-request-done` reaches the element that committed and its ancestors
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loadbare/app",
3
3
  "description": "High performance web app framework for server-bound applications",
4
- "version": "0.25.0",
4
+ "version": "0.26.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",