@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.
- package/dist/build/assemble.d.ts +1 -2
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +11 -53
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/cli.d.ts +4 -10
- package/dist/build/cli.d.ts.map +1 -1
- package/dist/build/cli.js +11 -33
- package/dist/build/cli.js.map +1 -1
- package/dist/build/declared.js +1 -1
- package/dist/build/declared.js.map +1 -1
- package/dist/core/lb-constants.d.ts +8 -18
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +32 -72
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +12 -11
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +7 -0
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +10 -37
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +139 -522
- package/dist/hub/lb-apply.js.map +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +115 -126
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/hub/lb-lifecycle.d.ts +2 -2
- package/dist/hub/lb-lifecycle.d.ts.map +1 -1
- package/dist/hub/lb-lifecycle.js +9 -17
- package/dist/hub/lb-lifecycle.js.map +1 -1
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +3 -3
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +35 -19
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +141 -88
- package/dist/server/lb-server.js.map +1 -1
- package/docs/binding-cases.md +150 -0
- package/docs/comparison.md +18 -29
- package/docs/miswarts.md +2 -2
- package/docs/reference/css.md +2 -15
- package/docs/reference/custom-elements.md +6 -8
- package/docs/reference/data-binding.md +37 -180
- package/docs/reference/names.md +10 -26
- package/docs/reference/page-files.md +1 -12
- package/docs/reference/server.md +0 -1
- package/docs/testing.md +2 -5
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +52 -54
- package/skills/loadbare-app/references/css.md +2 -15
- package/skills/loadbare-app/references/custom-elements.md +6 -8
- package/skills/loadbare-app/references/data-binding.md +37 -180
- package/skills/loadbare-app/references/miswarts.md +2 -2
- package/skills/loadbare-app/references/names.md +10 -26
- package/skills/loadbare-app/references/page-files.md +1 -12
- package/skills/loadbare-app/references/server.md +0 -1
|
@@ -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
|
|
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-
|
|
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,7 +183,7 @@ 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
|
|
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
|
|
@@ -195,7 +195,10 @@ is added by a button with `commandfor` naming the nested list and
|
|
|
195
195
|
the form's submit carries it as `{ key: "", values }`, the handler inserts
|
|
196
196
|
each row with no key, and it leaves when the submit succeeds. So a master
|
|
197
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.
|
|
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
|
|
199
202
|
a submit. A new outer
|
|
200
203
|
row is filled from the nested query's last answer, whatever order they land
|
|
201
204
|
in.
|
|
@@ -220,21 +223,19 @@ JSON number or is declared one: `types: { amount: "number" }` beside
|
|
|
220
223
|
hold a place.
|
|
221
224
|
|
|
222
225
|
**The user's order and filters are choices, not query parms.** The hub
|
|
223
|
-
serves
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
`lb-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
page changes. A filter that decides which rows the server sends is a query
|
|
234
|
-
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.
|
|
235
236
|
|
|
236
237
|
**A page that failed to load says so.** The hub serves a third query,
|
|
237
|
-
`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`
|
|
238
239
|
(`loading`, `loaded`, `failed`), `lb-server-state` (`reachable`, `failing`,
|
|
239
240
|
`unreachable`), `lb-error` (`network`, `timeout` or the HTTP status),
|
|
240
241
|
`lb-pending` and `lb-as-of`. Show a server that is down from the chrome's
|
|
@@ -242,19 +243,10 @@ stylesheet, `lb-hub[lb-load-state="failed"] .load-failed`, rather than
|
|
|
242
243
|
leaving an empty page; see
|
|
243
244
|
[`references/chrome.md`](references/chrome.md#the-hubs-state).
|
|
244
245
|
|
|
245
|
-
**Groups are templates.** A `<template lb-group>` holds a heading and one
|
|
246
|
-
nested `<template>`, the next level or the row template; the nth breaks on
|
|
247
|
-
the order's nth term, to any depth. Contents land before the nested
|
|
248
|
-
template, so put it inside the heading's element for a container and beside
|
|
249
|
-
the heading for a heading row. `<tbody>` and `<optgroup>` do not nest. The
|
|
250
|
-
heading is filled from the group's first row. `lb-count`, `lb-sum="col"`,
|
|
251
|
-
`lb-avg`, `lb-min` and `lb-max` total the rows showing in the nearest group,
|
|
252
|
-
or in the whole list outside any.
|
|
253
|
-
|
|
254
246
|
**Animate with CSS.** The hub stamps `lb-row-created`, `lb-row-changed`,
|
|
255
247
|
`lb-row-moved` (its values changed and it now stands elsewhere), and
|
|
256
248
|
`lb-row-requested` for this page's request, and marks a
|
|
257
|
-
leaving row
|
|
249
|
+
leaving row `lb-row-leaving`, removing it once
|
|
258
250
|
its animations end. Scrolling to a row is script, in `lbRowsLanded`.
|
|
259
251
|
|
|
260
252
|
**Every request has one shape.** `lb-request` names the request, and the
|
|
@@ -327,16 +319,6 @@ update or delete at all, silently. So a control with
|
|
|
327
319
|
`lb-request="lb-row-update"` saves on a row on record and only holds its
|
|
328
320
|
value on a new one. Never write script to stop such an update.
|
|
329
321
|
|
|
330
|
-
**Select rows with `lb-select`, never with a column.** An
|
|
331
|
-
`<input type="checkbox" lb-select>` in a row template selects its row; the
|
|
332
|
-
hub stamps `lb-row-selected`. A request for that query naming no one row,
|
|
333
|
-
such as a form outside the rows, carries the ticked rows as `keys`.
|
|
334
|
-
`rowUpdate` and `rowDelete` then run once per key with no new code; a
|
|
335
|
-
declared request gets `keys` itself. With none ticked an update or delete
|
|
336
|
-
is not sent. Success clears the selection, and so does `lb-show` hiding a
|
|
337
|
-
selector. A selecting mode kept in the URL reaches the rows as a column the
|
|
338
|
-
query computes from the parm.
|
|
339
|
-
|
|
340
322
|
**Refuse with `refusal()`, never with a plain throw.** `throw
|
|
341
323
|
refusal("message")`, `throw refusal({ column: "message" })` or both, from
|
|
342
324
|
`@loadbare/app/server`. The whole-request message lands as the
|
|
@@ -439,9 +421,9 @@ whole data channel.
|
|
|
439
421
|
|
|
440
422
|
**The developer writes `lb-*` attributes in markup, and script never
|
|
441
423
|
assigns them.** The builder refuses any `lb-` attribute other than the
|
|
442
|
-
|
|
443
|
-
`lb-column`, `lb-show`, `lb-
|
|
444
|
-
`lb-
|
|
424
|
+
ten in [Attributes](references/names.md#attributes): `lb-query`,
|
|
425
|
+
`lb-column`, `lb-show`, `lb-filter`, `lb-manual`,
|
|
426
|
+
`lb-request`,
|
|
445
427
|
`lb-url-link`, `lb-url-parm`, `lb-url-push` and `lb-url-unknown`. `lb-exp-slot` and
|
|
446
428
|
`lb-exp-template` are expansion's, and never reach the page. Everything
|
|
447
429
|
else with the prefix is a stamp the hub or the builder writes.
|
|
@@ -527,28 +509,44 @@ The application's own definition of a tag overrides a package's.
|
|
|
527
509
|
Read these when the summary above does not settle the question. They ship
|
|
528
510
|
with the package, so no network is needed.
|
|
529
511
|
|
|
530
|
-
|
|
531
|
-
|
|
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()`.
|
|
532
536
|
- [`references/data-binding.md`](references/data-binding.md) — landing,
|
|
533
537
|
gathering, requests, conditions and request state. Start here for
|
|
534
538
|
anything in a page.
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
539
|
+
|
|
540
|
+
Custom elements:
|
|
541
|
+
|
|
538
542
|
- [`references/custom-elements.md`](references/custom-elements.md) —
|
|
539
543
|
expansion, parameters, slots, destinations, and custom element code and
|
|
540
544
|
when it runs.
|
|
541
|
-
- [`references/chrome.md`](references/chrome.md) — the chrome, and the URL
|
|
542
|
-
as the query `lb-url`.
|
|
543
|
-
- [`references/server.md`](references/server.md) — the Express server and
|
|
544
|
-
the request context.
|
|
545
|
-
- [`references/builder.md`](references/builder.md) — the builder's options,
|
|
546
|
-
what it reads, and where it looks.
|
|
547
|
-
- [`references/dev-server.md`](references/dev-server.md) — `devServer` from
|
|
548
|
-
`@loadbare/app/dev`, and the parts to assemble another from.
|
|
549
|
-
- [`references/css.md`](references/css.md) — how stylesheets are ordered.
|
|
550
545
|
- [`references/widgets.md`](references/widgets.md) — the basic widget
|
|
551
546
|
library as a package; each widget is in the loadbare-widgets skill.
|
|
547
|
+
|
|
548
|
+
Names:
|
|
549
|
+
|
|
552
550
|
- [`references/names.md`](references/names.md) — every name Loadbare
|
|
553
551
|
owns, the constants, and the section defining each. Check a name here
|
|
554
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)
|
|
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]
|
|
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-
|
|
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
|
|
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
|
|
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)
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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`,
|
|
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).
|
|
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
|
|
548
|
-
`lb-row-leaving`
|
|
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
|
|
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
|
|
641
|
-
|
|
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.
|
|
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
|
|
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
|
|
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>`
|
|
@@ -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.
|
|
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
|
|
81
|
+
**Why it terminates.** It applies only to live rows under a
|
|
82
82
|
filter.
|
|
83
83
|
|
|
84
84
|
## Leaving rows are inert
|