@loadbare/app 0.24.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 (56) 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 +61 -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 +23 -37
  20. package/dist/hub/lb-apply.d.ts.map +1 -1
  21. package/dist/hub/lb-apply.js +205 -518
  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 +159 -132
  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 +20 -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 +100 -185
  43. package/docs/reference/names.md +11 -27
  44. package/docs/reference/page-files.md +4 -14
  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 +66 -56
  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 +100 -185
  52. package/skills/loadbare-app/references/miswarts.md +2 -2
  53. package/skills/loadbare-app/references/names.md +11 -27
  54. package/skills/loadbare-app/references/page-files.md +4 -14
  55. package/skills/loadbare-app/references/server.md +0 -1
  56. package/docs/temp-proposals.md +0 -251
@@ -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.24.0",
4
+ "version": "0.26.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: loadbare-app
3
- description: Build server-bound web applications with Loadbare/app. Covers the file conventions the builder finds by name (`chrome.html`, `*.page.html`, `*.queries.ts`, `*.requests.ts`, `imports.ts`, `<tag>.html`, `<tag>.browser.ts`); the `lb-*` attribute vocabulary that lands query rows on HTML and issues requests (`lb-query`, `lb-column`, `lb-show`, `lb-request`); queries declared with `row(key, run)` and `rows(key, run)`; the URL as the hub's own query `lb-url`, with `lb-url-link`, `lb-url-parm`, `lb-url-push` and `lb-url-unknown`; the user's order and filters as the hub's query `lb-choices`, read by `lb-order` and `lb-filter`; whether the page loaded and the server answers as the hub's query `lb-hub`; one form pointed at a row by the `--lb-edit`, `--lb-new` and `--lb-release` commands; rows that hold still under `lb-manual` and are placed again with `--lb-place`; build-time expansion with `exp-*` parameters, `lb-exp-slot` and `lb-exp-template`; custom elements as form-associated controls and row hosts; the Express wiring with `hubRoutes`; and the `@loadbare/widgets` library. Use whenever a task involves `@loadbare/app`, `@loadbare/widgets`, `loadbare-app-build`, an `lb-` attribute, or a page, query, request or custom element file in a Loadbare application. The model is not React, htmx or REST, and cannot be inferred from them.
3
+ description: Build server-bound web applications with Loadbare/app. Covers the file conventions the builder finds by name (`chrome.html`, `*.page.html`, `*.queries.ts`, `*.requests.ts`, `imports.ts`, `<tag>.html`, `<tag>.browser.ts`); the `lb-*` attribute vocabulary that lands query rows on HTML and issues requests (`lb-query`, `lb-column`, `lb-show`, `lb-request`); queries declared with `row(key, run)` and `rows(key, run)`; the URL as the hub's own query `lb-url`, with `lb-url-link`, `lb-url-parm`, `lb-url-push` and `lb-url-unknown`; the user's order and filters as the hub's queries `lb-sort` and `lb-filters`, read by `lb-filter`; whether the page loaded and the server answers as the hub's query `lb-hub-status`; one form pointed at a row by the `--lb-edit`, `--lb-new` and `--lb-release` commands; rows that hold still under `lb-manual` and are placed again with `--lb-place`; build-time expansion with `exp-*` parameters, `lb-exp-slot` and `lb-exp-template`; custom elements as form-associated controls and row hosts; the Express wiring with `hubRoutes`; and the `@loadbare/widgets` library. Use whenever a task involves `@loadbare/app`, `@loadbare/widgets`, `loadbare-app-build`, an `lb-` attribute, or a page, query, request or custom element file in a Loadbare application. The model is not React, htmx or REST, and cannot be inferred from them.
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  package: "@loadbare/app"
@@ -75,7 +75,7 @@ server.ts
75
75
  The chrome carries `<lb-hub>` inside `<body>`, an empty `<main>` inside the
76
76
  hub, and `<script src="/client.js" defer>`. Everything a user touches sits
77
77
  inside `<lb-hub>`. The chrome belongs to no page, so it names only the
78
- hub's queries, `lb-url`, `lb-choices` and `lb-hub`, and sends no declared
78
+ hub's queries, `lb-url`, `lb-sort`, `lb-filters` and `lb-hub-status`, and sends no declared
79
79
  request.
80
80
 
81
81
  A page is an HTML fragment that lands in `<main>`:
@@ -183,13 +183,23 @@ from it.
183
183
 
184
184
  **A column never holds rows.** Master-detail is a `row` query and a `rows`
185
185
  query under two names. Many masters with their details is one `rows` query
186
- of joined rows, ordered by the master first and shown in groups. A
186
+ of joined rows, ordered by the master first. A
187
187
  query nested inside another query's row template receives the same rows in
188
188
  every outer row; use it for a picker, never for per-row detail. Inside a
189
189
  form, the live rows of a query nested in the form's own are gathered as
190
190
  `rows: { <query>: [{ key, values }] }` beside `values`, so a master and a
191
191
  subtable of its details (one input per type, say) are entered in one
192
- submit, and the master's handler writes both. A new outer
192
+ submit, and the master's handler writes both. A detail not yet entered
193
+ is added by a button with `commandfor` naming the nested list and
194
+ `command="--lb-new"`: it adds a row with the empty key and sends nothing,
195
+ the form's submit carries it as `{ key: "", values }`, the handler inserts
196
+ each row with no key, and it leaves when the submit succeeds. So a master
197
+ and its details are one save, before or after the master is on record; never
198
+ gate the details behind `lb-show` on the master being saved. A form bound
199
+ by Edit or New reads its nested lists again (`lb-read`) with the bound key
200
+ as the parm named for its key column, so the details query reads that parm
201
+ and follows the row the form is bound to; New sends it empty. The form needs
202
+ a submit. A new outer
193
203
  row is filled from the nested query's last answer, whatever order they land
194
204
  in.
195
205
 
@@ -213,21 +223,19 @@ JSON number or is declared one: `types: { amount: "number" }` beside
213
223
  hold a place.
214
224
 
215
225
  **The user's order and filters are choices, not query parms.** The hub
216
- serves a second query, `lb-choices`, keyed by `lb-path`, one column per
217
- choice, named by the application. A control inside
218
- `lb-query="lb-choices"` with `lb-request="lb-row-update"` makes a choice.
219
- `lb-order="<choice>"` on the element carrying `lb-query` places its rows by
220
- the order that choice holds, in place of the server's while it is not
221
- empty. `lb-filter="col, col"` there hides each row that does not pass the
222
- choice of the same name: `^=Amazon`, `>=2026-01-01 <=2026-03-31`, or plain
223
- text for contains. A choice shows with no round trip, then the server's
224
- `onChoices(ctx, choices)` hears every choice, to keep them;
225
- `onPageEnter` returns `choices()` to restore them. Choices hold until the
226
- page changes. A filter that decides which rows the server sends is a query
227
- parm.
226
+ serves them as two queries, `lb-sort` and `lb-filters`, one row per query
227
+ keyed by the query's name. `lb-sort` holds each query's order as the
228
+ server resolved it; `lb-filters` holds each query's filter values.
229
+ `lb-filter="col, col"` on the element carrying `lb-query` hides each row
230
+ that does not pass its query's filter of the same name: `^=Amazon`,
231
+ `>=2026-01-01 <=2026-03-31`, or plain text for contains. The server's
232
+ `onChoices(ctx, { query, sort, filters })` hears each change, to keep it;
233
+ `onPageEnter` returns `sort()` and `filters()` to restore them. Choices
234
+ hold until the page changes. A filter that decides which rows the server
235
+ sends is a query parm.
228
236
 
229
237
  **A page that failed to load says so.** The hub serves a third query,
230
- `lb-hub`, and stamps its columns on `<lb-hub>` too: `lb-load-state`
238
+ `lb-hub-status`, and stamps its columns on `<lb-hub>` too: `lb-load-state`
231
239
  (`loading`, `loaded`, `failed`), `lb-server-state` (`reachable`, `failing`,
232
240
  `unreachable`), `lb-error` (`network`, `timeout` or the HTTP status),
233
241
  `lb-pending` and `lb-as-of`. Show a server that is down from the chrome's
@@ -235,19 +243,10 @@ stylesheet, `lb-hub[lb-load-state="failed"] .load-failed`, rather than
235
243
  leaving an empty page; see
236
244
  [`references/chrome.md`](references/chrome.md#the-hubs-state).
237
245
 
238
- **Groups are templates.** A `<template lb-group>` holds a heading and one
239
- nested `<template>`, the next level or the row template; the nth breaks on
240
- the order's nth term, to any depth. Contents land before the nested
241
- template, so put it inside the heading's element for a container and beside
242
- the heading for a heading row. `<tbody>` and `<optgroup>` do not nest. The
243
- heading is filled from the group's first row. `lb-count`, `lb-sum="col"`,
244
- `lb-avg`, `lb-min` and `lb-max` total the rows showing in the nearest group,
245
- or in the whole list outside any.
246
-
247
246
  **Animate with CSS.** The hub stamps `lb-row-created`, `lb-row-changed`,
248
247
  `lb-row-moved` (its values changed and it now stands elsewhere), and
249
248
  `lb-row-requested` for this page's request, and marks a
250
- leaving row or group `lb-row-leaving` or `lb-group-leaving`, removing it once
249
+ leaving row `lb-row-leaving`, removing it once
251
250
  its animations end. Scrolling to a row is script, in `lbRowsLanded`.
252
251
 
253
252
  **Every request has one shape.** `lb-request` names the request, and the
@@ -296,7 +295,11 @@ not a form.) The form's `lb-key-value` is the row's key, empty
296
295
  for a new row, absent when not in use, and a stylesheet shows Save or Save
297
296
  new by it. A successful request from the form, or its dialog closing, lets
298
297
  it go. Which row is being edited is never a query parm. A row that must be
299
- fetched to be edited is another page, with that row as its master.
298
+ fetched to be edited is another page, with that row as its master. A
299
+ pointed form edits only what its row holds: a query nested in it shows the
300
+ page's answer, not the pointed row's details, so give the row a column per
301
+ detail when the details are a fixed set, or make the row the page's master
302
+ by a parm.
300
303
 
301
304
  **Three requests are Loadbare's.** `lb-row-insert` needs `query` and
302
305
  `values`, `lb-row-update` needs `query`, `key` and `values`, and
@@ -309,22 +312,13 @@ request the page does not declare. One that arrives anyway, from a script,
309
312
  is warned about on the server console and answered with nothing.
310
313
 
311
314
  **An empty key is a row not yet entered.** A `row` query answering with an
312
- empty key, or a form `--lb-new` pointed, carries `lb-key-value=""`. The hub
315
+ empty key, a form `--lb-new` pointed, or a row `--lb-new` added to a list,
316
+ carries `lb-key-value=""`. The hub
313
317
  sends inserts and declared requests from it with no `key`, and sends no
314
318
  update or delete at all, silently. So a control with
315
319
  `lb-request="lb-row-update"` saves on a row on record and only holds its
316
320
  value on a new one. Never write script to stop such an update.
317
321
 
318
- **Select rows with `lb-select`, never with a column.** An
319
- `<input type="checkbox" lb-select>` in a row template selects its row; the
320
- hub stamps `lb-row-selected`. A request for that query naming no one row,
321
- such as a form outside the rows, carries the ticked rows as `keys`.
322
- `rowUpdate` and `rowDelete` then run once per key with no new code; a
323
- declared request gets `keys` itself. With none ticked an update or delete
324
- is not sent. Success clears the selection, and so does `lb-show` hiding a
325
- selector. A selecting mode kept in the URL reaches the rows as a column the
326
- query computes from the parm.
327
-
328
322
  **Refuse with `refusal()`, never with a plain throw.** `throw
329
323
  refusal("message")`, `throw refusal({ column: "message" })` or both, from
330
324
  `@loadbare/app/server`. The whole-request message lands as the
@@ -427,9 +421,9 @@ whole data channel.
427
421
 
428
422
  **The developer writes `lb-*` attributes in markup, and script never
429
423
  assigns them.** The builder refuses any `lb-` attribute other than the
430
- eighteen in [Attributes](references/names.md#attributes): `lb-query`,
431
- `lb-column`, `lb-show`, `lb-order`, `lb-filter`, `lb-manual`, `lb-group`, `lb-count`,
432
- `lb-sum`, `lb-avg`, `lb-min`, `lb-max`, `lb-select`, `lb-request`,
424
+ ten in [Attributes](references/names.md#attributes): `lb-query`,
425
+ `lb-column`, `lb-show`, `lb-filter`, `lb-manual`,
426
+ `lb-request`,
433
427
  `lb-url-link`, `lb-url-parm`, `lb-url-push` and `lb-url-unknown`. `lb-exp-slot` and
434
428
  `lb-exp-template` are expansion's, and never reach the page. Everything
435
429
  else with the prefix is a stamp the hub or the builder writes.
@@ -515,28 +509,44 @@ The application's own definition of a tag overrides a package's.
515
509
  Read these when the summary above does not settle the question. They ship
516
510
  with the package, so no network is needed.
517
511
 
518
- - [`references/overview.md`](references/overview.md) — the map of the
519
- reference, by part of the application.
512
+ [`references/overview.md`](references/overview.md) is the map of the
513
+ reference, in the groups below.
514
+
515
+ The application shell:
516
+
517
+ - [`references/chrome.md`](references/chrome.md) — the chrome, the URL as
518
+ the query `lb-url`, and the hub's state.
519
+ - [`references/server.md`](references/server.md) — the Express server, the
520
+ request context, and where the database layer fits.
521
+
522
+ Building the app:
523
+
524
+ - [`references/builder.md`](references/builder.md) — the builder's options,
525
+ what it reads, where it looks, and what it writes.
526
+ - [`references/css.md`](references/css.md) — how stylesheets are ordered, and
527
+ the stamps a stylesheet selects on.
528
+ - [`references/dev-server.md`](references/dev-server.md) — `devServer` from
529
+ `@loadbare/app/dev`, and the parts to assemble another from.
530
+
531
+ Application pages:
532
+
533
+ - [`references/page-files.md`](references/page-files.md) — what page
534
+ files are, queries, `onPageEnter`, `onChoices`, handlers, `crud`, refresh
535
+ and patch, `url()`, `sort()` and `filters()`.
520
536
  - [`references/data-binding.md`](references/data-binding.md) — landing,
521
537
  gathering, requests, conditions and request state. Start here for
522
538
  anything in a page.
523
- - [`references/page-files.md`](references/page-files.md) — what page
524
- files are, queries, `onPageEnter`, `onChoices`, handlers, `crud`, refresh
525
- and patch, `url()` and `choices()`.
539
+
540
+ Custom elements:
541
+
526
542
  - [`references/custom-elements.md`](references/custom-elements.md) —
527
543
  expansion, parameters, slots, destinations, and custom element code and
528
544
  when it runs.
529
- - [`references/chrome.md`](references/chrome.md) — the chrome, and the URL
530
- as the query `lb-url`.
531
- - [`references/server.md`](references/server.md) — the Express server and
532
- the request context.
533
- - [`references/builder.md`](references/builder.md) — the builder's options,
534
- what it reads, and where it looks.
535
- - [`references/dev-server.md`](references/dev-server.md) — `devServer` from
536
- `@loadbare/app/dev`, and the parts to assemble another from.
537
- - [`references/css.md`](references/css.md) — how stylesheets are ordered.
538
545
  - [`references/widgets.md`](references/widgets.md) — the basic widget
539
546
  library as a package; each widget is in the loadbare-widgets skill.
547
+
548
+ Names:
549
+
540
550
  - [`references/names.md`](references/names.md) — every name Loadbare
541
551
  owns, the constants, and the section defining each. Check a name here
542
552
  before designing around something the other references do not mention.
@@ -69,7 +69,6 @@ in the stamp, so the selector reads the number and not its text. See
69
69
  | Select | For |
70
70
  |----------------------|-------------------------------------------------|
71
71
  | `[lb-row-live]` | Every live row of a list |
72
- | `[lb-row-selected]` | A row its `lb-select` checkbox ticks |
73
72
  | `[lb-row-editing]` | The row a pointed form is editing |
74
73
  | `[lb-key-value="…"]` | One row, by its key |
75
74
  | `[hidden]` | A row a filter hides; the browser hides it |
@@ -86,24 +85,12 @@ landed inside a list, such as a total in a table's foot, carries a key and
86
85
  is not one of the list's rows.
87
86
 
88
87
  ```css
89
- [lb-row-selected] { background: var(--selected); }
90
88
  [lb-row-editing] { outline: 2px solid var(--accent); }
91
89
  ```
92
90
 
93
- See [Rows](./data-binding.md#rows), [Selecting rows](./data-binding.md#selecting-rows)
91
+ See [Rows](./data-binding.md#rows)
94
92
  and [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form).
95
93
 
96
- ### A group
97
-
98
- Each top-level element of a group carries `lb-group-live`, the column it
99
- breaks on as `lb-group-column`, and its value there as `lb-group-value`:
100
-
101
- ```css
102
- [lb-group-column="category"][lb-group-value="Income"] { color: var(--income); }
103
- ```
104
-
105
- See [Groups](./data-binding.md#groups).
106
-
107
94
  ### What just happened to a row
108
95
 
109
96
  The hub stamps what its last landing did, so a stylesheet animates with
@@ -115,7 +102,7 @@ nothing else:
115
102
  | `[lb-row-changed]` | A row whose values changed |
116
103
  | `[lb-row-moved]` | A row whose values changed and now stands elsewhere; it carries `lb-row-changed` too |
117
104
  | `[lb-row-requested]` | Any of the three, done by this page's request, as `created`, `changed` or `moved` |
118
- | `[lb-row-leaving]`, `[lb-group-leaving]` | A row or group on its way out; the hub removes it when its animations end |
105
+ | `[lb-row-leaving]` | A row on its way out; the hub removes it when its animations end |
119
106
 
120
107
  ```css
121
108
  [lb-row-created] { animation: arrive 200ms; }
@@ -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 |