@loadbare/app 0.26.0 → 0.27.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 (40) hide show
  1. package/dist/build/assemble.d.ts.map +1 -1
  2. package/dist/build/assemble.js +37 -1
  3. package/dist/build/assemble.js.map +1 -1
  4. package/dist/core/lb-constants.d.ts +14 -2
  5. package/dist/core/lb-constants.d.ts.map +1 -1
  6. package/dist/core/lb-constants.js +42 -6
  7. package/dist/core/lb-constants.js.map +1 -1
  8. package/dist/hub/lb-apply.d.ts +5 -2
  9. package/dist/hub/lb-apply.d.ts.map +1 -1
  10. package/dist/hub/lb-apply.js +402 -78
  11. package/dist/hub/lb-apply.js.map +1 -1
  12. package/dist/hub/lb-hub.browser.d.ts.map +1 -1
  13. package/dist/hub/lb-hub.browser.js +1 -2
  14. package/dist/hub/lb-hub.browser.js.map +1 -1
  15. package/dist/hub/lb-lifecycle.d.ts +2 -2
  16. package/dist/hub/lb-lifecycle.d.ts.map +1 -1
  17. package/dist/hub/lb-lifecycle.js +6 -5
  18. package/dist/hub/lb-lifecycle.js.map +1 -1
  19. package/docs/comparison.md +29 -22
  20. package/docs/miswarts.md +2 -2
  21. package/docs/opinions.md +2 -2
  22. package/docs/reference/chrome.md +8 -10
  23. package/docs/reference/css.md +20 -8
  24. package/docs/reference/custom-elements.md +19 -14
  25. package/docs/reference/data-binding.md +163 -61
  26. package/docs/reference/names.md +23 -8
  27. package/docs/reference/page-files.md +25 -16
  28. package/docs/reference/server.md +3 -3
  29. package/docs/roadmap.md +2 -2
  30. package/docs/testing.md +8 -6
  31. package/package.json +1 -1
  32. package/skills/loadbare-app/SKILL.md +16 -7
  33. package/skills/loadbare-app/references/chrome.md +8 -10
  34. package/skills/loadbare-app/references/css.md +20 -8
  35. package/skills/loadbare-app/references/custom-elements.md +19 -14
  36. package/skills/loadbare-app/references/data-binding.md +163 -61
  37. package/skills/loadbare-app/references/miswarts.md +2 -2
  38. package/skills/loadbare-app/references/names.md +23 -8
  39. package/skills/loadbare-app/references/page-files.md +25 -16
  40. package/skills/loadbare-app/references/server.md +3 -3
@@ -209,9 +209,9 @@ observable, and no client cache that answers a request.
209
209
  to place rows again when the user makes a choice. Nothing else is read
210
210
  from it in place of asking the server.
211
211
  - The hub keeps a little state of its own: the name of the current page,
212
- the user's choices for it as the row of its query `lb-choices`, the live
213
- row each form is pointed at, the refusals on show, and, until a request
214
- completes, the form it gathered from.
212
+ the user's order and filters for it as the rows of `lb-sort` and
213
+ `lb-filters`, the live row each form is pointed at, the refusals on show,
214
+ and, until a request completes, the form it gathered from.
215
215
 
216
216
  The server is the source of truth for everything else. A query takes no
217
217
  argument from the browser; its only input is `ctx`, which the application
@@ -254,7 +254,7 @@ At run time the hub performs a closed set of operations:
254
254
 
255
255
  | Trigger | Operation |
256
256
  | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
257
- | Navigation | Clone the page's `<template>` into `<main>`, land `lb-url`, land `lb-choices` empty |
257
+ | Navigation | Clone the page's `<template>` into `<main>`, land `lb-url`, land `lb-sort` and `lb-filters` empty |
258
258
  | A value for a control | Set `value`, and stamp `lb-column-value` |
259
259
  | A value for another native element | Set `textContent`, and stamp `lb-column-value` |
260
260
  | A value for a custom element that is not a control | Stamp `lb-column-value` |
@@ -264,9 +264,11 @@ At run time the hub performs a closed set of operations:
264
264
  | All rows | Place every row by the query's order, or the user's; remove rows whose keys did not arrive |
265
265
  | An answer to a request, under `lb-manual` | Leave the rows already showing where they stand, stamp `lb-row-unplaced` on each out of place |
266
266
  | A patch | Upsert the rows named, remove the keys named, leave other rows in place |
267
+ | A group template | Build a group where the order breaks, keep it while its run goes on, remove it with its last row |
268
+ | An aggregate (`lb-aggregate`) | Set the element from the rows showing in its group, or in the whole list |
267
269
  | A row changes, moves or leaves | Stamp `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` or `lb-row-leaving`; remove a leaving row once its animations finish |
268
270
  | After rows land | Stamp `lb-query-row-count`, `lb-query-unplaced-count` and `lb-query-order` |
269
- | The user makes a choice | Land `lb-choices`, place and filter the rows already held again, tell the server |
271
+ | The user makes a sort or a filter | Land `lb-sort` and `lb-filters`, place and filter the rows already held again, tell the server |
270
272
  | A row the user's filter does not pass | Set `hidden` on it |
271
273
  | An `lb-show` column | Move the element into, or out of, a `<template lb-show>` |
272
274
  | A `commandfor` button with `--lb-edit` or `--lb-new` | Fill the form from the held row, or empty it; stamp `lb-key-value` and `lb-row-editing`; open its `<dialog>` |
@@ -320,7 +322,7 @@ There are two kinds of placeholder, and they run at different times.
320
322
  a whole attribute value or a whole text node. The tag supplies it with an
321
323
  `exp-name` attribute. An unsupplied placeholder with no default drops the
322
324
  attribute. The value becomes permanent in the shipped HTML.
323
- - Run time. Data lands through `lb-column`,
325
+ - Run time. Data lands through `lb-column`, `lb-aggregate`,
324
326
  `lb-query` with a row or group `<template>`, and `lb-show`. There is no
325
327
  run-time interpolation into attribute values or text.
326
328
 
@@ -492,7 +494,8 @@ query declared.
492
494
 
493
495
  A column holds one value. A set of values is a query of its own. A row
494
496
  never contains rows. Master-detail is a row and rows answered under two
495
- names. Many masters with their details is one `rows` query of joined rows.
497
+ names. Many masters with their details is one `rows` query of joined rows,
498
+ shown in groups by a group template.
496
499
 
497
500
  The application designs no endpoints, routes or serialization format. The
498
501
  names in the markup are the keys in the page's `.queries.ts` and
@@ -687,8 +690,8 @@ for the mechanisms by project.
687
690
  - The query string rides on every round trip, and the server hands its parms
688
691
  to `contextFor`.
689
692
  - The user's order and filters for rows already on the page are not query
690
- parms. They are choices, the row of the hub's query `lb-choices`, and
691
- hold until the page changes.
693
+ parms. They are the rows of the hub's queries `lb-sort` and `lb-filters`,
694
+ and hold until the page changes.
692
695
  - The application must be served from the origin root. The hub reaches
693
696
  `/lb` by absolute path, and the chrome links `/client.js` and `/app.css`.
694
697
  - The hub sets `document.title` from `lb-page-label`. On entering a page,
@@ -753,7 +756,7 @@ Checked at build time, as errors:
753
756
  the browser's lifecycle callbacks
754
757
  - a chrome without exactly one `<lb-hub>` and one empty `<main>` inside it,
755
758
  and a page carrying either
756
- - an `lb-` attribute in markup that is not one of the eighteen a developer
759
+ - an `lb-` attribute in markup that is not one of the ten a developer
757
760
  writes; the rest are stamps, and script never assigns them
758
761
  - an `lb-request` value beginning with `lb-` that is not one of the three
759
762
  requests Loadbare provides
@@ -763,14 +766,18 @@ Checked at build time, as errors:
763
766
  `<lb-hub>`
764
767
  - `lb-show` on a `<template>`, on a row template's root, with no `lb-query`
765
768
  around it, or written `!` or `!!column`
766
- - `lb-order` or `lb-filter` on an element not carrying `lb-query`, or naming
769
+ - `lb-group` on anything but a `<template>` holding a `<template>`, and
770
+ `lb-aggregate` on a `<template>`, naming no function it knows, or naming
771
+ no column for any but `count`
772
+ - `lb-filter` on an element not carrying `lb-query`, or naming
767
773
  no column
768
774
  - a `command` beginning `--lb-` that is not one of the three, and one of the
769
775
  three with no `commandfor`
770
776
  - an `lb-query` naming a query the page does not declare, an `lb-request`
771
777
  naming a request it does not declare under `handlers`, and one of the
772
778
  three requests for a query whose `crud` entry lacks it. The chrome names
773
- only `lb-url` and `lb-choices`. The builder reads the declarations by
779
+ only `lb-url`, `lb-sort`, `lb-filters` and `lb-hub-status`. The builder
780
+ reads the declarations by
774
781
  loading the page modules, so their import-time code runs during the build.
775
782
  - a `.queries.ts` or `.requests.ts` with no matching page
776
783
 
@@ -817,8 +824,8 @@ Nothing is scoped, renamed, added or removed.
817
824
  `lb-request-error` and `lb-request-refused`. An empty `rows` query is
818
825
  styled with `[lb-query-row-count="0"]`.
819
826
  - Every change the hub makes to a list is stamped: `lb-row-created`,
820
- `lb-row-changed`, `lb-row-moved`, `lb-row-requested` and
821
- `lb-row-leaving`, and a row an answer left out of place carries
827
+ `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-leaving` and
828
+ `lb-group-leaving`, and a row an answer left out of place carries
822
829
  `lb-row-unplaced`. A leaving row is removed once its animations finish,
823
830
  so an application animates rows with CSS alone.
824
831
 
@@ -842,7 +849,7 @@ Nothing is scoped, renamed, added or removed.
842
849
  Loadbare/app ships no server. It ships:
843
850
 
844
851
  - `createHub(pages)`, an engine with no HTTP code, in `@loadbare/app/server`,
845
- beside `row`, `rows`, `patch`, `url`, `choices` and `refusal`
852
+ beside `row`, `rows`, `patch`, `url`, `sort`, `filters` and `refusal`
846
853
  - `hubRoutes(hub, contextFor, options)`, an Express 5 router, in
847
854
  `@loadbare/app/express`. Express is an optional peer dependency.
848
855
  - `pages.ts`, generated by the builder, which imports every page's queries
@@ -979,8 +986,8 @@ cross-reference.
979
986
 
980
987
  | Owned | Count | Names |
981
988
  | ------------------------------------ | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
982
- | `lb-*` attributes a developer writes | 11 | `lb-query`, `lb-column`, `lb-show`, `lb-order`, `lb-filter`, `lb-manual`, `lb-request`, `lb-url-link`, `lb-url-parm`, `lb-url-push`, `lb-url-unknown` |
983
- | `lb-*` stamps | 23 | `lb-column-value`, `lb-key-value`, `lb-row-live`, `lb-query-row-count`, `lb-query-unplaced-count`, `lb-query-order`, `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-unplaced`, `lb-row-leaving`, `lb-row-editing`, `lb-request-pending`, `lb-request-error`, `lb-request-refused`, `lb-page`, `lb-page-title`, and on `<lb-hub>` `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` |
989
+ | `lb-*` attributes a developer writes | 12 | `lb-query`, `lb-column`, `lb-show`, `lb-group`, `lb-aggregate`, `lb-filter`, `lb-manual`, `lb-request`, `lb-url-link`, `lb-url-parm`, `lb-url-push`, `lb-url-unknown` |
990
+ | `lb-*` stamps | 27 | `lb-column-value`, `lb-key-value`, `lb-row-live`, `lb-query-row-count`, `lb-query-unplaced-count`, `lb-query-order`, `lb-group-live`, `lb-group-column`, `lb-group-value`, `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-unplaced`, `lb-row-leaving`, `lb-group-leaving`, `lb-row-editing`, `lb-request-pending`, `lb-request-error`, `lb-request-refused`, `lb-page`, `lb-page-title`, and on `<lb-hub>` `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` |
984
991
  | `lb-*` build-time attributes | 2 | `lb-exp-slot`, `lb-exp-template` |
985
992
  | Requests Loadbare provides | 3 | `lb-row-insert`, `lb-row-update`, `lb-row-delete` |
986
993
  | Commands for `commandfor` | 4 | `--lb-edit`, `--lb-new`, `--lb-release`, `--lb-place` |
@@ -988,11 +995,11 @@ cross-reference.
988
995
  | Attribute namespace for expansion | 1 | `exp-*` |
989
996
  | Reserved tags | 1 | `<lb-hub>` |
990
997
  | Reserved events | 2 | `lb-request`, `lb-request-done` |
991
- | Queries the hub serves | 3 | `lb-url`, with columns `lb-path`, `lb-page-label`; `lb-choices`, keyed by `lb-path`; `lb-hub-status`, with columns `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` |
998
+ | Queries the hub serves | 4 | `lb-url`, with columns `lb-path`, `lb-page-label`; `lb-sort` and `lb-filters`, keyed by the query's name; `lb-hub-status`, with columns `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` |
992
999
  | Builder flags | 3 | `--src`, `--out`, `--minify` |
993
1000
  | Reserved file names and patterns | 8 | `chrome.html`, `imports.ts`, `*.page.html`, `*.queries.ts`, `*.requests.ts`, `<tag>.html`, `<tag>.browser.ts`, `*.css` |
994
1001
  | Reserved `package.json` keys | 1 | `loadbare.widgets` |
995
- | Server functions | 8 | `row`, `rows`, `patch`, `url`, `choices`, `refusal`, `createHub`, `hubRoutes` |
1002
+ | Server functions | 9 | `row`, `rows`, `patch`, `url`, `sort`, `filters`, `refusal`, `createHub`, `hubRoutes` |
996
1003
  | Browser exports | 2 | `applyRow`, `applyResponse` |
997
1004
 
998
1005
  Theory states that the whole vocabulary fits in one technical reference,
@@ -1141,7 +1148,7 @@ Each is current behavior or an open item named in the
1141
1148
  | File inputs | Not landed and not gathered. |
1142
1149
  | Field validation | No per-keystroke mechanism. A handler's refusal lands on each control through the browser's own validity; validation placement is an open question. |
1143
1150
  | Concurrent writers | No version or conflict check. Open question. |
1144
- | Chrome-level queries | The chrome names only `lb-url` and `lb-choices`; an application query there is a build error. On the roadmap. |
1151
+ | Chrome-level queries | The chrome names only `lb-url`, `lb-sort`, `lb-filters` and `lb-hub-status`; an application query there is a build error. On the roadmap. |
1145
1152
  | A widget receiving a whole row | Not available. On the roadmap. |
1146
1153
  | Compound foreign keys | A picker offers the same choices on every row; a choice restricted by another column of its row cannot be expressed. Roadmap. |
1147
1154
  | Configurable request deadline | Fixed at ten seconds. |
@@ -1401,8 +1408,8 @@ Each equivalent is approximate.
1401
1408
  | `lb-exp-slot`, `lb-exp-template` | Default slot and named slots; `ng-content` with `select` |
1402
1409
  | `lbRowsLanded` | An effect after a list renders |
1403
1410
  | `lbAttached`, `lbDetached` | Mount and unmount; `onMounted` and `onUnmounted` (Vue); `onMount` and `onDestroy` (Svelte) |
1404
- | `order` | `ORDER BY` with report-writer control breaks (`BREAK ON`, group bands) |
1405
- | `lb-choices`, `lb-order`, `lb-filter` | A data grid's sort and filter model |
1411
+ | `order`, `lb-group` | `ORDER BY` with report-writer control breaks (`BREAK ON`, group bands) |
1412
+ | `lb-sort`, `lb-filters`, `lb-filter` | A data grid's sort and filter model |
1406
1413
  | `ctx` / `HubContext` | `event.locals` (SvelteKit); loader `context` (React Router 7); request-scoped dependency injection |
1407
1414
  | `imports.ts` | Installing and registering a component library |
1408
1415
  | `pages.ts` | Generated route manifest |
package/docs/miswarts.md CHANGED
@@ -68,7 +68,7 @@ gathered.
68
68
  ## Rows hidden by a filter
69
69
 
70
70
  **What.** A row that does not pass the user's filter gets the `hidden`
71
- attribute.
71
+ attribute, and so does a group whose rows are all hidden.
72
72
 
73
73
  **Rule broken.** The hub writes only its own stamps, which always
74
74
  begin with `lb-`.
@@ -78,7 +78,7 @@ over rows already on the page needs no round trip, and `hidden` is HTML's
78
78
  own word for an element that is present but not shown. A stamp of our
79
79
  own would make every stylesheet restate what the browser already does.
80
80
 
81
- **Why it terminates.** It applies only to live rows under a
81
+ **Why it terminates.** It applies only to live rows and groups under a
82
82
  filter.
83
83
 
84
84
  ## Leaving rows are inert
package/docs/opinions.md CHANGED
@@ -109,8 +109,8 @@ every link and every query parm follows this rule. See
109
109
 
110
110
  What the framework itself keeps is presented as rows. The URL is the
111
111
  query `lb-url`, of kind `row`, and lands like any server query. User
112
- preferences and choices on a page are sent as `lb-row-update` for `lb-choices`,
113
- and can land anywhere on the page.
112
+ preferences and choices on a page are sent as `lb-row-update` for `lb-sort`
113
+ and `lb-filters`, and can land anywhere on the page.
114
114
 
115
115
  Most frameworks keep their own state in a store with its own interface.
116
116
  In Loadbare/app, a developer shows the current page's label or a
@@ -101,7 +101,6 @@ server's row lands, so a chrome shows where the page is with no code:
101
101
  |-------------------|---------------------------------------------------------|
102
102
  | `lb-path` | The path, such as `/members`. The row's key |
103
103
  | `lb-page-label` | The page's title, or its stub when it has none |
104
- | `lb-page-unknown` | `true` when no page's stub matches the path |
105
104
  | Any other name | The query parm of that name, or empty when it is absent |
106
105
 
107
106
  The path names a page, never a resource: `/accounts/42` is not a way to
@@ -116,9 +115,9 @@ page file carries; see [page files](./page-files.md#the-page-title). The hub
116
115
  sets the document title to `lb-page-label` whenever it is not null, so the
117
116
  tab and the browser history show the page.
118
117
 
119
- `lb-url` is one of two queries a page may use that the server does not
120
- declare. The other is [`lb-choices`](./data-binding.md#choices). A page
121
- names either the same way, anywhere inside the hub.
118
+ `lb-url` is one of the queries a page may use that the server does not
119
+ declare. The others are `lb-sort`, `lb-filters` and `lb-hub-status`. A page
120
+ names any the same way, anywhere inside the hub.
122
121
 
123
122
  ### Where focus starts
124
123
 
@@ -223,8 +222,8 @@ pushes one instead when the element carrying `lb-request` also carries
223
222
  The hub answers the request itself, with no round trip, then reloads the
224
223
  page's queries at the new URL. The page stays in place, and rows that come
225
224
  back keep their place. A request that leaves the URL as it was does
226
- nothing. `lb-page-label` and `lb-page-unknown` are the hub's, and a request
227
- never sets them.
225
+ nothing. `lb-page-label` is the hub's, and a request
226
+ never sets it.
228
227
 
229
228
  A request that gives `lb-path` a new value enters that page, pushes a
230
229
  history entry, and the new URL carries only the query parms the request
@@ -288,8 +287,8 @@ it; a per-session database role means an id outside the caller's reach
288
287
  finds nothing.
289
288
 
290
289
  An order or a filter the hub applies to rows the page already holds is not
291
- a query parm. It is a [choice](./data-binding.md#choices), which holds until
292
- the page changes.
290
+ a query parm. It is a [sort or a filter](./data-binding.md#sort-and-filters),
291
+ which holds until the page changes.
293
292
 
294
293
  The hub sends the query parms with every round trip, and the server hands
295
294
  them to `contextFor`; see [the Express server](./server.md#database-layer).
@@ -308,8 +307,7 @@ show the path:
308
307
  </dialog>
309
308
  ```
310
309
 
311
- When no page's stub matches the path, `lb-page-unknown` is `true`,
312
- `lb-page-label` is null, `<main>` keeps the page it had, the hub calls
310
+ When the path names a page that does not exist, `lb-page-label` is null, `<main>` keeps the page it had, the hub calls
313
311
  `showModal()` on the dialog, and reports the path to the console. A chrome
314
312
  with no dialog shows nothing. `lb-url` lands before the page is looked up,
315
313
  so the dialog shows the path by naming it like any other element.
@@ -91,6 +91,17 @@ is not one of the list's rows.
91
91
  See [Rows](./data-binding.md#rows)
92
92
  and [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form).
93
93
 
94
+ ### A group
95
+
96
+ Each top-level element of a group carries `lb-group-live`, the column it
97
+ breaks on as `lb-group-column`, and its value there as `lb-group-value`:
98
+
99
+ ```css
100
+ [lb-group-column="category"][lb-group-value="Income"] { color: var(--income); }
101
+ ```
102
+
103
+ See [Groups](./data-binding.md#groups).
104
+
94
105
  ### What just happened to a row
95
106
 
96
107
  The hub stamps what its last landing did, so a stylesheet animates with
@@ -102,7 +113,7 @@ nothing else:
102
113
  | `[lb-row-changed]` | A row whose values changed |
103
114
  | `[lb-row-moved]` | A row whose values changed and now stands elsewhere; it carries `lb-row-changed` too |
104
115
  | `[lb-row-requested]` | Any of the three, done by this page's request, as `created`, `changed` or `moved` |
105
- | `[lb-row-leaving]` | A row on its way out; the hub removes it when its animations end |
116
+ | `[lb-row-leaving]`, `[lb-group-leaving]` | A row or group on its way out; the hub removes it when its animations end |
106
117
 
107
118
  ```css
108
119
  [lb-row-created] { animation: arrive 200ms; }
@@ -166,18 +177,19 @@ form:not([lb-key-value=""]) .save-new { display: none; }
166
177
 
167
178
  See [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form).
168
179
 
169
- ### The user's choices
180
+ ### The user's order and filters
170
181
 
171
- An order or a filter the user chose is a column of `lb-choices`, so the
172
- element showing it carries it as `lb-column-value`. Style anything else by
173
- it with `:has()`:
182
+ The order the user chose is the `order` column of `lb-sort`, and a filter
183
+ is a column of `lb-filters`, so the element showing either carries it as
184
+ `lb-column-value`. Style anything else by it with `:has()`:
174
185
 
175
186
  ```css
176
- table:has([lb-column="accounts_order"][lb-column-value="-balance"])
177
- th.balance::after { content: "▼"; }
187
+ :has([lb-column="name"][lb-column-value="^=Amazon"]) th.name::after {
188
+ content: "🔍";
189
+ }
178
190
  ```
179
191
 
180
- See [Choices](./data-binding.md#choices).
192
+ See [Sort and filters](./data-binding.md#sort-and-filters).
181
193
 
182
194
  ### Content shown by condition
183
195
 
@@ -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-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-group-*`, `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, or
319
- creates a live row. It places the chrome and a page as
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
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 has finished leaving, and when it shows
322
+ element when a live row or a group 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.
@@ -572,18 +572,21 @@ missing a field its name needs, and stamps the dispatching element with
572
572
 
573
573
  Let the event bubble, so an ancestor can stop it before the hub sends it.
574
574
 
575
- A request with `lb-row-update` for `lb-url` or `lb-choices` is keyed by the
576
- path, so an element anywhere on the page may set a query parm or make a
577
- [choice](./data-binding.md#choices) without sitting inside the query:
575
+ A request with `lb-row-update` for `lb-url` is keyed by the path; one for
576
+ `lb-sort` or `lb-filters` is keyed by the query's name. An element anywhere
577
+ on the page may set a query parm or make a
578
+ [sort or a filter](./data-binding.md#sort-and-filters) without sitting
579
+ inside the query:
578
580
 
579
581
  ```ts
580
- import { CHOICES_QUERY, LB_EVENT_NAME, REQUEST_ROW_UPDATE } from "@loadbare/app/constants";
582
+ import { SORT_QUERY, LB_EVENT_NAME, REQUEST_ROW_UPDATE } from "@loadbare/app/constants";
581
583
  import type { HubRequest } from "@loadbare/app/types";
582
584
 
583
585
  const detail: HubRequest = {
584
586
  name: REQUEST_ROW_UPDATE,
585
- query: CHOICES_QUERY,
586
- values: { ledger_order: "-amount" },
587
+ query: SORT_QUERY,
588
+ key: "ledger",
589
+ values: { order: "-amount" },
587
590
  };
588
591
  this.dispatchEvent(new CustomEvent(LB_EVENT_NAME, { bubbles: true, detail }));
589
592
  ```
@@ -616,8 +619,8 @@ listener. Import its name as `LB_DONE_EVENT_NAME`.
616
619
  `items` is every response item that landed because of the request, in
617
620
  order. `refusal` is set beside `error` when the handler refused the
618
621
  request, holding its `message` and `columns`. An answer that moved the URL contributes its `lb-url` item, which
619
- carries a key only the server knew, and the page load. A choice contributes
620
- the row of `lb-choices` it made. `error` is set when
622
+ carries a key only the server knew, and the page load. A sort or a filter contributes
623
+ the row of `lb-sort` or `lb-filters` it made. `error` is set when
621
624
  the round trip failed, and then nothing landed. A new row's key is in the
622
625
  answer only when the handler returned it in a patch: a refresh sends all
623
626
  rows, and nothing marks which one is new.
@@ -633,7 +636,8 @@ had there hears the event, and no custom element the hub has removed hears
633
636
 
634
637
  The hub lands every row template itself, places every row by the query's
635
638
  order (see [Placing by hand](./data-binding.md#placing-by-hand)
636
- for when it does not). A
639
+ for when it does not), and builds every group the markup's group templates describe; see
640
+ [Order](./data-binding.md#order) and [Groups](./data-binding.md#groups). A
637
641
  plain element carrying `lb-query` with a row template inside it needs no
638
642
  code, so a custom element holds rows only to do something with them once
639
643
  they land.
@@ -661,7 +665,8 @@ Everything else is the hub's:
661
665
  | Cloning | Clones the row template once per new key |
662
666
  | Matching | Fills the live row already showing that key, when its values changed |
663
667
  | 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` |
664
- | Filtering | Hides a row the user's filter does not pass |
668
+ | Filtering | Hides a row the user's filter does not pass, and a group whose rows are all hidden |
669
+ | Grouping | Builds a group where the order breaks, keeps it while its run goes on, and removes it with its last row |
665
670
  | Removing | Marks the live rows the response says are gone as leaving, and removes them |
666
671
  | Stamping | Stamps each live row with `lb-row-live`, `lb-key-value`, and what happened to it |
667
672
  | 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 |