@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.
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +37 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/core/lb-constants.d.ts +14 -2
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +42 -6
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +5 -2
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +402 -78
- 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 +1 -2
- 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 +6 -5
- package/dist/hub/lb-lifecycle.js.map +1 -1
- package/docs/comparison.md +29 -22
- package/docs/miswarts.md +2 -2
- package/docs/opinions.md +2 -2
- package/docs/reference/chrome.md +8 -10
- package/docs/reference/css.md +20 -8
- package/docs/reference/custom-elements.md +19 -14
- package/docs/reference/data-binding.md +163 -61
- package/docs/reference/names.md +23 -8
- package/docs/reference/page-files.md +25 -16
- package/docs/reference/server.md +3 -3
- package/docs/roadmap.md +2 -2
- package/docs/testing.md +8 -6
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +16 -7
- package/skills/loadbare-app/references/chrome.md +8 -10
- package/skills/loadbare-app/references/css.md +20 -8
- package/skills/loadbare-app/references/custom-elements.md +19 -14
- package/skills/loadbare-app/references/data-binding.md +163 -61
- package/skills/loadbare-app/references/miswarts.md +2 -2
- package/skills/loadbare-app/references/names.md +23 -8
- package/skills/loadbare-app/references/page-files.md +25 -16
- package/skills/loadbare-app/references/server.md +3 -3
|
@@ -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
|
+
ten `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`,
|
|
@@ -46,8 +46,9 @@ each with its key, and permits the three requests on `roster`; see
|
|
|
46
46
|
| `lb-query` | Any element | The query whose rows land in it |
|
|
47
47
|
| `lb-column` | Any element | The column it shows, and the column it gathers |
|
|
48
48
|
| `lb-show` | Any element but `<template>` | The column that decides whether it is present |
|
|
49
|
-
| `lb-
|
|
50
|
-
| `lb-
|
|
49
|
+
| `lb-filter` | An element with `lb-query` | The columns the user may filter; see [Filters](#filters) |
|
|
50
|
+
| `lb-group` | A `<template>` | Nothing: it marks a group template; see [Groups](#groups) |
|
|
51
|
+
| `lb-aggregate` | Any element | The function it applies to `lb-column`; see [Aggregates](#aggregates) |
|
|
51
52
|
| `lb-request` | Any element | The request it sends when it commits |
|
|
52
53
|
| `lb-url-link` | An `<a>` | A link between pages; see [chrome](./chrome.md#links) |
|
|
53
54
|
| `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) |
|
|
@@ -65,8 +66,9 @@ builder writes a stamp, and a stylesheet or a custom element reads it.
|
|
|
65
66
|
| `lb-query-row-count` | The number of live rows an element shows |
|
|
66
67
|
| `lb-query-unplaced-count` | The number of them out of place; see [Placing by hand](#placing-by-hand) |
|
|
67
68
|
| `lb-query-order` | The order placing them; see [Order](#order) |
|
|
69
|
+
| `lb-group-live`, `lb-group-column`, `lb-group-value` | A group, the column it breaks on, and its value; see [Groups](#groups) |
|
|
68
70
|
| `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) |
|
|
69
|
-
| `lb-row-leaving` | A row on its way out |
|
|
71
|
+
| `lb-row-leaving`, `lb-group-leaving` | A row or group on its way out |
|
|
70
72
|
| `lb-row-editing` | The row a form is pointed at; see [Editing a row in one form](#editing-a-row-in-one-form) |
|
|
71
73
|
| `lb-request-pending` | The element's request is in flight |
|
|
72
74
|
| `lb-request-error` | The element's last request failed |
|
|
@@ -86,7 +88,8 @@ elements as the page needs.
|
|
|
86
88
|
|
|
87
89
|
What lands depends on the query's kind and on whether the element holds a
|
|
88
90
|
row template, which is the first `<template>` among its descendants outside
|
|
89
|
-
any nested `lb-query
|
|
91
|
+
any nested `lb-query`, or, when that template is a [group
|
|
92
|
+
template](#groups), the innermost template inside it:
|
|
90
93
|
|
|
91
94
|
| Kind | Row template | The hub |
|
|
92
95
|
|--------|--------------|----------------------------------------|
|
|
@@ -178,7 +181,7 @@ or `""`:
|
|
|
178
181
|
|
|
179
182
|
A checkbox lands what it sends, so it shows the same state after a round
|
|
180
183
|
trip through a query whose values are strings, such as `lb-url` or
|
|
181
|
-
`lb-
|
|
184
|
+
`lb-filters`. A query parm the URL does not carry lands as `""`, so the
|
|
182
185
|
checkbox is unchecked. Unchecked sends `"false"` rather than nothing, so a
|
|
183
186
|
flag can be set back. A checkbox carrying a `value` attribute is not a flag
|
|
184
187
|
but one of a set, holding a query parm the URL repeats; see
|
|
@@ -264,25 +267,22 @@ roster: rows("id", (ctx) => ctx.db.members(), { order: "team,name" }),
|
|
|
264
267
|
With no order, rows show in the order they arrived, and a patch's new rows
|
|
265
268
|
go last.
|
|
266
269
|
|
|
267
|
-
The user's order replaces the server's.
|
|
268
|
-
|
|
269
|
-
column holds an order written the same way
|
|
270
|
-
server's order places the rows:
|
|
270
|
+
The user's order replaces the server's. The hub serves the query
|
|
271
|
+
[`lb-sort`](#sort-and-filters), one row per `rows` query, keyed by the
|
|
272
|
+
query's name, whose `order` column holds an order written the same way.
|
|
273
|
+
While it is empty, the server's order places the rows:
|
|
271
274
|
|
|
272
275
|
```html
|
|
273
|
-
<
|
|
274
|
-
<select lb-column="roster_order" lb-request="lb-row-update">
|
|
275
|
-
<option value="">By team</option>
|
|
276
|
-
<option value="name">By name</option>
|
|
277
|
-
<option value="-joined">Newest first</option>
|
|
278
|
-
</select>
|
|
279
|
-
</div>
|
|
280
|
-
|
|
281
|
-
<ul lb-query="roster" lb-order="roster_order">
|
|
276
|
+
<ul lb-query="roster">
|
|
282
277
|
<template><li lb-column="name"></li></template>
|
|
283
278
|
</ul>
|
|
284
279
|
```
|
|
285
280
|
|
|
281
|
+
A control makes a choice by sending `lb-row-update` for `lb-sort`, keyed by
|
|
282
|
+
the query's name; the `<lb-table>` widget's sortable headings do this for
|
|
283
|
+
each column. The hub places the rows again from the ones it already holds,
|
|
284
|
+
and tells the server through `onChoices`.
|
|
285
|
+
|
|
286
286
|
| Values | Compare |
|
|
287
287
|
|----------------------|----------------------------------------------|
|
|
288
288
|
| Two numbers | Numerically |
|
|
@@ -314,7 +314,7 @@ user works through them. It names `order`, `filter` or both, separated by a
|
|
|
314
314
|
space:
|
|
315
315
|
|
|
316
316
|
```html
|
|
317
|
-
<lb-table lb-query="entries"
|
|
317
|
+
<lb-table lb-query="entries"
|
|
318
318
|
lb-filter="description, is_unmatched" lb-manual="order filter">
|
|
319
319
|
```
|
|
320
320
|
|
|
@@ -325,7 +325,8 @@ form `--lb-edit` pointed at a row, or a form elsewhere on the page.
|
|
|
325
325
|
| The answer | Under `lb-manual`, the row | Side |
|
|
326
326
|
|----------------------------------------|---------------------------------------------------|----------|
|
|
327
327
|
| Changes a column the order reads | Stays where it stands | `order` |
|
|
328
|
-
| Creates a row | Goes last
|
|
328
|
+
| Creates a row | Goes after the last row of its group, or last of all | `order` |
|
|
329
|
+
| Changes the column its group breaks on | Stays under its group's heading | `order` |
|
|
329
330
|
| Changes a row so the filter hides it | Stays showing | `filter` |
|
|
330
331
|
| Drops a row | Leaves, under either side | |
|
|
331
332
|
|
|
@@ -374,21 +375,22 @@ the move.
|
|
|
374
375
|
|
|
375
376
|
Write `lb-filter` on the element carrying `lb-query`, naming the columns of
|
|
376
377
|
its rows the user may filter, separated by commas. The column of
|
|
377
|
-
[`lb-
|
|
378
|
+
[`lb-filters`](#sort-and-filters) of the same name holds the filter for
|
|
379
|
+
each:
|
|
378
380
|
|
|
379
381
|
```html
|
|
380
|
-
<div lb-query="lb-choices">
|
|
381
|
-
<input lb-column="name" lb-request="lb-row-update" placeholder="Name" />
|
|
382
|
-
</div>
|
|
383
|
-
|
|
384
382
|
<ul lb-query="roster" lb-filter="name, team">
|
|
385
383
|
<template><li lb-column="name"></li></template>
|
|
386
384
|
</ul>
|
|
387
385
|
```
|
|
388
386
|
|
|
387
|
+
A filter is made by sending `lb-row-update` for `lb-filters`, keyed by the
|
|
388
|
+
query's name; the `<lb-table>` widget's selection does this.
|
|
389
|
+
|
|
389
390
|
A row that does not pass every filter is `hidden`. Under `lb-manual="filter"`, a row an answer changed stays
|
|
390
391
|
showing until the rows are placed again; see
|
|
391
|
-
[Placing by hand](#placing-by-hand).
|
|
392
|
+
[Placing by hand](#placing-by-hand). A group whose rows are all hidden is hidden too
|
|
393
|
+
([miswart](../miswarts.md#rows-hidden-by-a-filter)). An empty
|
|
392
394
|
choice filters nothing.
|
|
393
395
|
|
|
394
396
|
A filter is one or more terms, each an operator followed by a value:
|
|
@@ -421,6 +423,97 @@ column that is null or missing, pass only `!=`.
|
|
|
421
423
|
`parseFilter`, `passes` and `passesTerm` in `@loadbare/app/types` are the
|
|
422
424
|
rule the hub applies.
|
|
423
425
|
|
|
426
|
+
### Groups
|
|
427
|
+
|
|
428
|
+
A group is a run of rows sharing the order's leading term. Write a
|
|
429
|
+
`<template lb-group>` where the row template goes, holding the group's
|
|
430
|
+
heading and one nested `<template>`: the next group template, or the row
|
|
431
|
+
template. The nth group template breaks on the order's nth term.
|
|
432
|
+
|
|
433
|
+
```html
|
|
434
|
+
<ul lb-query="roster">
|
|
435
|
+
<template lb-group>
|
|
436
|
+
<li>
|
|
437
|
+
<h3 lb-column="team"></h3>
|
|
438
|
+
<ul>
|
|
439
|
+
<template><li lb-column="name"></li></template>
|
|
440
|
+
</ul>
|
|
441
|
+
</li>
|
|
442
|
+
</template>
|
|
443
|
+
</ul>
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
The hub clones the group template where the order breaks, and the group's
|
|
447
|
+
contents land immediately before the clone of its nested template, so the
|
|
448
|
+
markup's nesting decides the shape:
|
|
449
|
+
|
|
450
|
+
| The nested template is | The group's contents land | Example |
|
|
451
|
+
|------------------------------|------------------------------------|-----------------------------------|
|
|
452
|
+
| Inside the heading's element | Inside it | `<tbody>`, `<li>`, `<details>` |
|
|
453
|
+
| Beside the heading | After the heading, as its siblings | A heading `<tr>` in one `<tbody>` |
|
|
454
|
+
|
|
455
|
+
`<tbody>` and `<optgroup>` do not nest, so a table's levels below the first
|
|
456
|
+
are heading rows beside their rows:
|
|
457
|
+
|
|
458
|
+
```html
|
|
459
|
+
<table lb-query="accounts">
|
|
460
|
+
<thead><tr><th>Account</th></tr></thead>
|
|
461
|
+
<template lb-group>
|
|
462
|
+
<tbody>
|
|
463
|
+
<tr><th scope="rowgroup" lb-column="category"></th></tr>
|
|
464
|
+
<template><tr><td lb-column="account_name"></td></tr></template>
|
|
465
|
+
</tbody>
|
|
466
|
+
</template>
|
|
467
|
+
</table>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Content after the nested template lands after the group's rows, which is
|
|
471
|
+
where a group's footer goes.
|
|
472
|
+
|
|
473
|
+
A heading is filled from its group's first row as an element in a row is,
|
|
474
|
+
`href`s from `lb-url-parm` included, so it may show a column other than the
|
|
475
|
+
one the group breaks on. Under `lb-manual="order"`, a row an answer
|
|
476
|
+
moved to another group stays under its old heading, and the heading shows
|
|
477
|
+
the row as it stood, until the rows are placed again. The hub stamps each top-level
|
|
478
|
+
element of a group with `lb-group-live`, `lb-group-column` and
|
|
479
|
+
`lb-group-value`. A row creates its group, and a group leaves with its last
|
|
480
|
+
row. When the order changes, a group whose run goes on is kept and moved,
|
|
481
|
+
and a group whose run ended leaves.
|
|
482
|
+
|
|
483
|
+
A group template with no nested template is reported to the console. More
|
|
484
|
+
group templates than the order has terms show each extra level as one
|
|
485
|
+
group, and are reported once.
|
|
486
|
+
|
|
487
|
+
### Aggregates
|
|
488
|
+
|
|
489
|
+
`lb-aggregate` sets an element from the rows of the nearest group around
|
|
490
|
+
it, or of the whole list outside any group. It names the function, and
|
|
491
|
+
`lb-column` names the column:
|
|
492
|
+
|
|
493
|
+
```html
|
|
494
|
+
<tr><td><span lb-aggregate="count"></span> people</td><td lb-aggregate="sum" lb-column="salary"></td></tr>
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
| `lb-aggregate` | Sets the element to |
|
|
498
|
+
|----------------|-----------------------------------------------------------|
|
|
499
|
+
| `count` | The number of rows; with `lb-column`, the values in it that are not null |
|
|
500
|
+
| `sum` | The sum of the column |
|
|
501
|
+
| `avg` | The average of the column |
|
|
502
|
+
| `min` | The least value of the column, by the [order](#order)'s comparison |
|
|
503
|
+
| `max` | The greatest, likewise |
|
|
504
|
+
|
|
505
|
+
An aggregate lands as a column does, with `lb-column-value`; its
|
|
506
|
+
`lb-column` names the column it totals, and no row lands on it. A sum and an
|
|
507
|
+
average are exact decimals, read from JSON numbers and from strings holding
|
|
508
|
+
a plain decimal, as Postgres sends `numeric`. A sum has as many places as
|
|
509
|
+
the most precise value, and an average up to two more. `null` and empty
|
|
510
|
+
values are left out, as SQL leaves them out, and any other value is left
|
|
511
|
+
out and reported once. The result lands unformatted.
|
|
512
|
+
|
|
513
|
+
An aggregate covers the rows showing, so a row a filter hides is left out.
|
|
514
|
+
Where the true total matters beyond what the page shows, have the server
|
|
515
|
+
answer it as a row.
|
|
516
|
+
|
|
424
517
|
### What happened to a row
|
|
425
518
|
|
|
426
519
|
Every change to a list is one a stylesheet can see:
|
|
@@ -433,6 +526,7 @@ Every change to a list is one a stylesheet can see:
|
|
|
433
526
|
| `lb-row-requested` | `created`, `changed` or `moved` by this page's request |
|
|
434
527
|
| `lb-row-unplaced` | Stands where the order or the filter would not leave it |
|
|
435
528
|
| `lb-row-leaving` | A row on its way out |
|
|
529
|
+
| `lb-group-leaving` | A group on its way out |
|
|
436
530
|
|
|
437
531
|
The hub touches a row when an answer names it. `lb-row-created`,
|
|
438
532
|
`lb-row-changed` and `lb-row-moved` are cleared when it next does, and one
|
|
@@ -443,8 +537,8 @@ query, and set only by a landing that answers a request from the page.
|
|
|
443
537
|
placed again; see
|
|
444
538
|
[Placing by hand](#placing-by-hand).
|
|
445
539
|
|
|
446
|
-
A row that leaves loses `lb-row-live`, takes
|
|
447
|
-
`lb-row-leaving` and `inert`
|
|
540
|
+
A row or a group that leaves loses `lb-row-live` or `lb-group-live`, takes
|
|
541
|
+
`lb-row-leaving` or `lb-group-leaving` and `inert`
|
|
448
542
|
([miswart](../miswarts.md#leaving-rows-are-inert)), and is removed once its
|
|
449
543
|
animations finish, at once when there are none.
|
|
450
544
|
|
|
@@ -468,7 +562,7 @@ The hub keeps each query's last answer until the page changes, with any
|
|
|
468
562
|
patch since applied to it. An element that names a query and arrives after
|
|
469
563
|
that query's answer is filled from what was kept, at the end of the landing
|
|
470
564
|
that follows its arrival. Such an element is a picker in a new live row, or
|
|
471
|
-
scaffolding around rows, such as a ghost row. So
|
|
565
|
+
scaffolding around rows, such as a group's heading or a ghost row. So
|
|
472
566
|
a query nested in another query's rows need not land again, or land after
|
|
473
567
|
the outer query, for a new outer row to show its choices.
|
|
474
568
|
|
|
@@ -477,8 +571,8 @@ and its `lbRowsLanded` runs as its rows land. See
|
|
|
477
571
|
[Holding rows](./custom-elements.md#holding-rows).
|
|
478
572
|
|
|
479
573
|
A request always goes to the server, and a query re-runs only when a
|
|
480
|
-
response names it. A [
|
|
481
|
-
the hub kept. A patch that
|
|
574
|
+
response names it. A [sort or a filter](#sort-and-filters) is the one thing
|
|
575
|
+
landed from what the hub kept. A patch that
|
|
482
576
|
arrives before all of a query's rows is not kept, since it is not the whole
|
|
483
577
|
of anything.
|
|
484
578
|
|
|
@@ -536,8 +630,8 @@ answered side by side. A column never holds rows.
|
|
|
536
630
|
```
|
|
537
631
|
|
|
538
632
|
Many masters, each with its own detail, is one `rows` query of joined rows:
|
|
539
|
-
each detail row carries its master's columns
|
|
540
|
-
first.
|
|
633
|
+
each detail row carries its master's columns. A [group template](#groups)
|
|
634
|
+
shows each master as a group, ordered by the master's key first.
|
|
541
635
|
|
|
542
636
|
A query nested in another query's row template receives the same rows in
|
|
543
637
|
every live row. That serves a picker offering the same choices on every
|
|
@@ -827,7 +921,7 @@ it, and sends nothing:
|
|
|
827
921
|
Its controls start at their HTML defaults, and its `lb-show` branches are
|
|
828
922
|
as for a row whose every column is null.
|
|
829
923
|
- It stands after every row of the list, in the order added, and is not
|
|
830
|
-
ordered or
|
|
924
|
+
ordered, filtered or aggregated, since it holds no data. It counts in
|
|
831
925
|
`lb-query-row-count`.
|
|
832
926
|
- The form's submit carries it in `rows`, with `key: ""`, beside the rows on
|
|
833
927
|
record: an insert while the master is not on record, an update once it
|
|
@@ -907,10 +1001,10 @@ The hub sends one of these only when it has what the table lists, and
|
|
|
907
1001
|
otherwise reports to the console. An insert or an update that gathers
|
|
908
1002
|
nothing is not sent.
|
|
909
1003
|
|
|
910
|
-
For a query the hub serves, `lb-url` or `lb-
|
|
911
|
-
`lb-row-update` itself, with no round trip; see
|
|
912
|
-
[Query parms](./chrome.md#query-parms) and
|
|
913
|
-
`lb-hub-status
|
|
1004
|
+
For a query the hub serves, `lb-url`, `lb-sort` or `lb-filters`, the hub
|
|
1005
|
+
answers `lb-row-update` itself, with no round trip; see
|
|
1006
|
+
[Query parms](./chrome.md#query-parms) and
|
|
1007
|
+
[Sort and filters](#sort-and-filters). `lb-hub-status` takes no request.
|
|
914
1008
|
|
|
915
1009
|
A key comes from a live row, or from an element a `row` landed on, so all
|
|
916
1010
|
three work against either kind:
|
|
@@ -1225,28 +1319,28 @@ answers it with no round trip:
|
|
|
1225
1319
|
See [The URL](./chrome.md#the-url) for its columns, links, history, and the
|
|
1226
1320
|
unknown-page dialog.
|
|
1227
1321
|
|
|
1228
|
-
##
|
|
1322
|
+
## Sort and filters
|
|
1229
1323
|
|
|
1230
|
-
The hub serves
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
`lb-row-update`
|
|
1235
|
-
|
|
1236
|
-
|
|
1324
|
+
The hub serves two queries for how rows show: `lb-sort` and `lb-filters`,
|
|
1325
|
+
one row per `rows` query, keyed by the query's name. `lb-sort` holds each
|
|
1326
|
+
query's order as the server resolved it; `lb-filters` holds each query's
|
|
1327
|
+
filter values. An element makes a sort or a filter by dispatching
|
|
1328
|
+
`lb-request` with `lb-row-update` for `lb-sort` or `lb-filters`, keyed by
|
|
1329
|
+
the query's name; the `<lb-table>` widget's sortable headings and its
|
|
1330
|
+
selection do this; see
|
|
1237
1331
|
[Sending a request](./custom-elements.md#sending-a-request).
|
|
1238
1332
|
|
|
1239
|
-
A
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1333
|
+
A sort or a filter shows with no round trip: the hub places and filters the
|
|
1334
|
+
rows it already holds again, as a round trip carrying the choice would
|
|
1335
|
+
have. Then it sends the server the choice, in `lb-row-update` for `lb-sort`
|
|
1336
|
+
or `lb-filters`. No element waits on it, and the page's
|
|
1337
|
+
[`onChoices`](./page-files.md#onchoices) runs, when it has one, with the
|
|
1338
|
+
query and its new `sort` or `filters`.
|
|
1245
1339
|
|
|
1246
1340
|
Choices hold until the page changes, and a change of query parm keeps them.
|
|
1247
|
-
On entering a page,
|
|
1248
|
-
|
|
1249
|
-
parms, and the URL does not carry them.
|
|
1341
|
+
On entering a page, `lb-sort` and `lb-filters` land empty, unless the
|
|
1342
|
+
page's `onPageEnter` restores them with `sort()` and `filters()`. Choices
|
|
1343
|
+
are not query parms, and the URL does not carry them.
|
|
1250
1344
|
|
|
1251
1345
|
## The markup checks
|
|
1252
1346
|
|
|
@@ -1254,16 +1348,18 @@ The developer writes `lb-` attributes in markup, and script never assigns
|
|
|
1254
1348
|
them. The builder checks the markup of the chrome and of every page, after
|
|
1255
1349
|
expansion, and refuses to build:
|
|
1256
1350
|
|
|
1257
|
-
- an `lb-` attribute that is not one of the
|
|
1351
|
+
- an `lb-` attribute that is not one of the ten the developer writes;
|
|
1258
1352
|
`lb-exp-slot` and `lb-exp-template` are consumed by expansion and never
|
|
1259
1353
|
reach the check
|
|
1260
1354
|
- `lb-request` naming an `lb-` request other than the three Loadbare provides
|
|
1261
1355
|
- `lb-query` naming a query the page does not declare; every page and the
|
|
1262
|
-
chrome may name `lb-url` and `lb-
|
|
1356
|
+
chrome may name `lb-url`, `lb-sort`, `lb-filters` and `lb-hub-status`,
|
|
1357
|
+
and the chrome names no other
|
|
1263
1358
|
- `lb-request` naming a request the page does not declare under `handlers`;
|
|
1264
1359
|
the chrome sends none
|
|
1265
1360
|
- one of the three requests for a query whose `crud` entry does not declare
|
|
1266
|
-
it, or any but `lb-row-update` for `lb-url` or `lb-
|
|
1361
|
+
it, or any but `lb-row-update` for `lb-url`, `lb-sort` or `lb-filters`;
|
|
1362
|
+
the query is
|
|
1267
1363
|
a form's own when the form carries `lb-query`, and otherwise the nearest
|
|
1268
1364
|
`lb-query` around the element
|
|
1269
1365
|
- `lb-url-link` on anything but an `<a>`
|
|
@@ -1278,10 +1374,16 @@ expansion, and refuses to build:
|
|
|
1278
1374
|
- `lb-show` on a `<template>`, or on a row template's root
|
|
1279
1375
|
- `lb-show` with no `lb-query` around it
|
|
1280
1376
|
- `lb-show="!"` or `lb-show="!!column"`, which reverse no column
|
|
1281
|
-
- `lb-
|
|
1282
|
-
no column
|
|
1377
|
+
- `lb-filter` on an element not carrying `lb-query`, or naming no column
|
|
1283
1378
|
- `lb-manual` on an element not carrying `lb-query`, or naming anything but
|
|
1284
1379
|
`order`, `filter` or both
|
|
1380
|
+
- `lb-group` on anything but a `<template>`, or on one holding no
|
|
1381
|
+
`<template>` for its contents
|
|
1382
|
+
- `lb-aggregate` on a `<template>`, naming a function other than `count`,
|
|
1383
|
+
`sum`, `avg`, `min` or `max`, or, for any but `count`, beside no
|
|
1384
|
+
`lb-column`
|
|
1385
|
+
- `lb-count`, `lb-sum`, `lb-avg`, `lb-min` or `lb-max`, with what to write
|
|
1386
|
+
instead
|
|
1285
1387
|
- a `command` beginning `--lb-` that is not one of the four commands
|
|
1286
1388
|
- one of the four commands with no `commandfor`
|
|
1287
1389
|
- `--lb-new` aimed at an element the markup holds that is neither a
|
package/docs/reference/names.md
CHANGED
|
@@ -65,7 +65,7 @@ A widget package declares these. An application never does.
|
|
|
65
65
|
|
|
66
66
|
## Attributes
|
|
67
67
|
|
|
68
|
-
The developer writes
|
|
68
|
+
The developer writes ten attributes in pages and the chrome, and the
|
|
69
69
|
builder refuses any other `lb-` attribute there. `lb-exp-slot` and
|
|
70
70
|
`lb-exp-template` are written for expansion, which removes them before the
|
|
71
71
|
check. The hub and the builder write the rest, as stamps, and script never
|
|
@@ -76,9 +76,10 @@ assigns one.
|
|
|
76
76
|
| `lb-query` | Developer | [Landing](./data-binding.md#landing) |
|
|
77
77
|
| `lb-column` | Developer | [Landing](./data-binding.md#landing) |
|
|
78
78
|
| `lb-show` | Developer | [Conditional rendering](./data-binding.md#conditional-rendering) |
|
|
79
|
-
| `lb-order` | Developer | [Order](./data-binding.md#order) |
|
|
80
79
|
| `lb-filter` | Developer | [Filters](./data-binding.md#filters) |
|
|
81
80
|
| `lb-manual` | Developer | [Placing by hand](./data-binding.md#placing-by-hand) |
|
|
81
|
+
| `lb-group` | Developer | [Groups](./data-binding.md#groups) |
|
|
82
|
+
| `lb-aggregate` | Developer | [Aggregates](./data-binding.md#aggregates) |
|
|
82
83
|
| `lb-request` | Developer | [Requests](./data-binding.md#requests) |
|
|
83
84
|
| `lb-url-link` | Developer | [Links](./chrome.md#links) |
|
|
84
85
|
| `lb-url-parm` | Developer | [A link from a row](./chrome.md#a-link-from-a-row) |
|
|
@@ -92,8 +93,9 @@ assigns one.
|
|
|
92
93
|
| `lb-query-row-count` | Hub | [Counting rows](./data-binding.md#counting-rows) |
|
|
93
94
|
| `lb-query-unplaced-count`, `lb-row-unplaced` | Hub | [Placing by hand](./data-binding.md#placing-by-hand) |
|
|
94
95
|
| `lb-query-order` | Hub | [Order](./data-binding.md#order) |
|
|
96
|
+
| `lb-group-live`, `lb-group-column`, `lb-group-value` | Hub | [Groups](./data-binding.md#groups) |
|
|
95
97
|
| `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
|
|
96
|
-
| `lb-row-leaving` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
|
|
98
|
+
| `lb-row-leaving`, `lb-group-leaving` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
|
|
97
99
|
| `lb-row-editing` | Hub | [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
|
|
98
100
|
| `lb-request-pending` | Hub | [Request state](./data-binding.md#request-state) |
|
|
99
101
|
| `lb-request-error` | Hub | [Request state](./data-binding.md#request-state) |
|
|
@@ -111,7 +113,8 @@ them, and a page declares none.
|
|
|
111
113
|
| Query | Kind | Key | Columns | Defined in |
|
|
112
114
|
| ------------ | ----- | --------- | --------------------------------------------------------------- | ------------------------------------- |
|
|
113
115
|
| `lb-url` | `row` | `lb-path` | `lb-path`, `lb-page-label`, every query parm | [The URL](./chrome.md#the-url) |
|
|
114
|
-
| `lb-
|
|
116
|
+
| `lb-sort` | `rows` | `query` | `query`, `order` | [Sort and filters](./data-binding.md#sort-and-filters) |
|
|
117
|
+
| `lb-filters` | `rows` | `query` | `query`, every filter column | [Sort and filters](./data-binding.md#sort-and-filters) |
|
|
115
118
|
| `lb-hub-status` | `row` | `lb-path` | `lb-path`, `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` | [The hub's state](./chrome.md#the-hubs-state) |
|
|
116
119
|
|
|
117
120
|
No query parm is reserved: a column of `lb-url` whose name begins with
|
|
@@ -170,7 +173,7 @@ accessor or field named `lb` and a capital.
|
|
|
170
173
|
|
|
171
174
|
| Entry point | Exports | Defined in |
|
|
172
175
|
| -------------------------- | ---------------------------------------------------------------- | ---------------------------------------------- |
|
|
173
|
-
| `@loadbare/app/server` | `row`, `rows`, `patch`, `url`, `
|
|
176
|
+
| `@loadbare/app/server` | `row`, `rows`, `patch`, `url`, `sort`, `filters`, `refusal`, `createHub`, and the types `Queries`, `Requests`, `HubContext`, `Hub` | [Page Files](./page-files.md), [The data channel](./server.md#the-data-channel) |
|
|
174
177
|
| `@loadbare/app/express` | `hubRoutes` | [The Express Server](./server.md) |
|
|
175
178
|
| `@loadbare/app/dev` | `devServer`, `appServer`, `gate`, `devProxy`, `DOWN_MESSAGE` | [The Dev Server](./dev-server.md) |
|
|
176
179
|
| `@loadbare/app/build` | `buildApp`, `watchApp` | [Assembling your own](./dev-server.md#assembling-your-own) |
|
|
@@ -196,10 +199,21 @@ imports them rather than writing a string.
|
|
|
196
199
|
| `ATTR_QUERY_ROW_COUNT` | `lb-query-row-count` |
|
|
197
200
|
| `ATTR_QUERY_UNPLACED_COUNT` | `lb-query-unplaced-count` |
|
|
198
201
|
| `ATTR_QUERY_ORDER` | `lb-query-order` |
|
|
202
|
+
| `ATTR_GROUP` | `lb-group` |
|
|
203
|
+
| `ATTR_GROUP_LIVE` | `lb-group-live` |
|
|
204
|
+
| `ATTR_GROUP_COLUMN` | `lb-group-column` |
|
|
205
|
+
| `ATTR_GROUP_VALUE` | `lb-group-value` |
|
|
206
|
+
| `LIVE_GROUP` | `[lb-group-live]`, the selector for a group's element |
|
|
207
|
+
| `ATTR_AGGREGATE` | `lb-aggregate` |
|
|
208
|
+
| `AGGREGATE_COUNT`, `AGGREGATE_SUM`, `AGGREGATE_AVG`, `AGGREGATE_MIN`, `AGGREGATE_MAX` | `count`, `sum`, `avg`, `min`, `max` |
|
|
209
|
+
| `AGGREGATES` | All five aggregate functions |
|
|
199
210
|
| `ORDER_DESCENDING` | `-`, written before a column in an order |
|
|
200
211
|
| `COLUMN_TYPES` | `number`, `boolean`, `text` |
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
212
|
+
| `SORT_QUERY` | `lb-sort` |
|
|
213
|
+
| `SORT_COLUMN_QUERY` | `query` |
|
|
214
|
+
| `SORT_COLUMN_ORDER` | `order` |
|
|
215
|
+
| `FILTERS_QUERY` | `lb-filters` |
|
|
216
|
+
| `FILTERS_COLUMN_QUERY` | `query` |
|
|
203
217
|
| `ATTR_FILTER` | `lb-filter` |
|
|
204
218
|
| `ATTR_MANUAL` | `lb-manual` |
|
|
205
219
|
| `MANUAL_ORDER`, `MANUAL_FILTER` | `order`, `filter`: the sides `lb-manual` names |
|
|
@@ -211,6 +225,7 @@ imports them rather than writing a string.
|
|
|
211
225
|
| `REQUESTED_CREATED`, `REQUESTED_CHANGED`, `REQUESTED_MOVED` | `created`, `changed`, `moved` |
|
|
212
226
|
| `ATTR_ROW_UNPLACED` | `lb-row-unplaced` |
|
|
213
227
|
| `ATTR_ROW_LEAVING` | `lb-row-leaving` |
|
|
228
|
+
| `ATTR_GROUP_LEAVING` | `lb-group-leaving` |
|
|
214
229
|
| `ATTR_REQUEST` | `lb-request` |
|
|
215
230
|
| `LB_EVENT_NAME` | `lb-request`, the event every request travels as |
|
|
216
231
|
| `LB_DONE_EVENT_NAME` | `lb-request-done` |
|
|
@@ -252,7 +267,7 @@ imports them rather than writing a string.
|
|
|
252
267
|
| `ATTR_EXP_TEMPLATE` | `lb-exp-template` |
|
|
253
268
|
| `ATTR_PAGE` | `lb-page` |
|
|
254
269
|
| `ATTR_PAGE_TITLE` | `lb-page-title` |
|
|
255
|
-
| `DEVELOPER_ATTRIBUTES` | The
|
|
270
|
+
| `DEVELOPER_ATTRIBUTES` | The ten attributes a developer writes |
|
|
256
271
|
| `HUB_TAG_NAME` | `lb-hub` |
|
|
257
272
|
| `LB_ENDPOINT` | `/lb` |
|
|
258
273
|
| `LB_REQUEST_TIMEOUT_MS` | `10000` |
|
|
@@ -152,8 +152,8 @@ optional:
|
|
|
152
152
|
|
|
153
153
|
| Key | Runs |
|
|
154
154
|
|---------------|--------------------------------------------------------|
|
|
155
|
-
| `onPageEnter` | Before the page's queries, when the page loads; may move the URL or restore
|
|
156
|
-
| `onChoices` | Each time the user
|
|
155
|
+
| `onPageEnter` | Before the page's queries, when the page loads; may move the URL or restore the user's order and filters |
|
|
156
|
+
| `onChoices` | Each time the user changes the order or a filter |
|
|
157
157
|
| `handlers` | The page's declared requests, by request name |
|
|
158
158
|
| `crud` | The requests Loadbare provides, by query name |
|
|
159
159
|
|
|
@@ -190,34 +190,41 @@ loads there in the same round trip, and that load does not follow
|
|
|
190
190
|
`onPageEnter` again. A `url()` leading to the parms already in hand is
|
|
191
191
|
ignored. See [Moving the URL](#moving-the-url).
|
|
192
192
|
|
|
193
|
-
It may return `
|
|
194
|
-
[
|
|
193
|
+
It may return `sort()` and `filters()`, alone or beside `url()`, to restore
|
|
194
|
+
the user's [order and filters](./data-binding.md#sort-and-filters) for the
|
|
195
|
+
page:
|
|
195
196
|
|
|
196
197
|
```ts
|
|
197
198
|
// src/pages/directory.requests.ts
|
|
198
|
-
import {
|
|
199
|
+
import { sort, filters, url, type Requests } from "@loadbare/app/server";
|
|
199
200
|
|
|
200
201
|
export const requests: Requests = {
|
|
201
202
|
onPageEnter: async (ctx) => {
|
|
202
203
|
const saved = await ctx.db.savedView("directory");
|
|
203
|
-
if (saved)
|
|
204
|
+
if (saved) {
|
|
205
|
+
return {
|
|
206
|
+
...url(saved.parms),
|
|
207
|
+
...sort(saved.order),
|
|
208
|
+
...filters(saved.filters),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
204
211
|
},
|
|
205
|
-
onChoices: (ctx,
|
|
212
|
+
onChoices: (ctx, change) => ctx.db.saveChoices(change),
|
|
206
213
|
};
|
|
207
214
|
```
|
|
208
215
|
|
|
209
|
-
The page load answers `lb-
|
|
210
|
-
When `url()` moves the page, the choices arrive
|
|
211
|
-
URL. `
|
|
212
|
-
least one of them; anything else is
|
|
213
|
-
ignored.
|
|
216
|
+
The page load answers `lb-sort` and `lb-filters` first, so the rows land by
|
|
217
|
+
the order and the filters. When `url()` moves the page, the choices arrive
|
|
218
|
+
with the load at the new URL. `sort()` and `filters()`, like `url()`, take
|
|
219
|
+
columns whose values are strings, at least one of them; anything else is
|
|
220
|
+
reported on the server console and ignored.
|
|
214
221
|
|
|
215
222
|
### onChoices
|
|
216
223
|
|
|
217
|
-
`onChoices` runs each time the user
|
|
218
|
-
|
|
219
|
-
`onPageEnter` to restore, and answers nothing, by
|
|
220
|
-
returns lands. A page without it is not told.
|
|
224
|
+
`onChoices` runs each time the user changes the order or a filter, with the
|
|
225
|
+
query and its new `sort` or `filters`, as strings. It is how an application
|
|
226
|
+
keeps them for `onPageEnter` to restore, and answers nothing, by
|
|
227
|
+
convention. Whatever it returns lands. A page without it is not told.
|
|
221
228
|
|
|
222
229
|
### handlers
|
|
223
230
|
|
|
@@ -377,6 +384,8 @@ A change that seems to need a refresh usually has a patch:
|
|
|
377
384
|
[order](./data-binding.md#order), or leaves it where it stands under the
|
|
378
385
|
list's [`lb-manual`](./data-binding.md#placing-by-hand); a refresh would do
|
|
379
386
|
the same.
|
|
387
|
+
- A group that appears or goes: the hub makes a group with its first row
|
|
388
|
+
and removes it with its last, so no row stands in for an empty one.
|
|
380
389
|
- A row whose other columns change with the edit: re-read the row and patch
|
|
381
390
|
it.
|
|
382
391
|
- Rows the database removes with a deleted one: select their keys before the
|
package/docs/reference/server.md
CHANGED
|
@@ -228,9 +228,9 @@ in `drop` are removed, and every other row is left alone. A `rows` item on
|
|
|
228
228
|
the answer that loads the page also carries the query's declared `order`
|
|
229
229
|
and `types`, which the hub keeps for every answer after it.
|
|
230
230
|
|
|
231
|
-
A
|
|
232
|
-
|
|
233
|
-
[
|
|
231
|
+
A sort or a filter is sent as `lb-row-update` for `lb-sort` or `lb-filters`,
|
|
232
|
+
keyed by the query's name, with the new order or filter as `values`; see
|
|
233
|
+
[Sort and filters](./data-binding.md#sort-and-filters).
|
|
234
234
|
|
|
235
235
|
`createHub(pages)` builds the `Hub`, which has two calls, both answering
|
|
236
236
|
with response items: `dataForPage(page, ctx, options)` for a page load, and
|
package/docs/roadmap.md
CHANGED
|
@@ -148,8 +148,8 @@ breaks nothing.
|
|
|
148
148
|
|
|
149
149
|
The chrome belongs to no page, so the builder refuses an application query
|
|
150
150
|
named there, and a custom element in the chrome cannot show application
|
|
151
|
-
data. `lb-url` and `lb-
|
|
152
|
-
and an application has no equivalent.
|
|
151
|
+
data. `lb-url`, `lb-sort` and `lb-filters` show the pattern from the
|
|
152
|
+
framework side, and an application has no equivalent.
|
|
153
153
|
|
|
154
154
|
A chrome-level query set on `createHub` would close this, and it is additive.
|
|
155
155
|
It takes its place in the [options on `createHub`](#options-on-createhub).
|
package/docs/testing.md
CHANGED
|
@@ -172,8 +172,8 @@ watch, and surviving a failed build.
|
|
|
172
172
|
that refreshes its own `rows` query are refused
|
|
173
173
|
- an update or delete for several rows runs once per key, lays the patches
|
|
174
174
|
together, and refreshes once
|
|
175
|
-
- `onPageEnter` may return `url()` or `
|
|
176
|
-
every
|
|
175
|
+
- `onPageEnter` may return `url()`, `sort()` or `filters()`, and
|
|
176
|
+
`onChoices` hears every order and filter the user makes
|
|
177
177
|
- a refusal carries a message, columns or both, and passes through the
|
|
178
178
|
engine untouched
|
|
179
179
|
|
|
@@ -210,11 +210,12 @@ 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
|
|
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
|
|
214
215
|
leaves a stamp a stylesheet can see (`lb-order.test.ts`)
|
|
215
216
|
- a filter's text reads and passes values as documented, and a choice of
|
|
216
217
|
order or filter places the rows already landed again, hiding rows and
|
|
217
|
-
leaving them out of counts (`lb-choices.test.ts`)
|
|
218
|
+
groups and leaving them out of counts and aggregates (`lb-choices.test.ts`)
|
|
218
219
|
- `lb-show` moves an element into a template and back, and landing reaches
|
|
219
220
|
inside it
|
|
220
221
|
- a row whose values arrive as it already shows them is not filled again,
|
|
@@ -275,8 +276,9 @@ What the hub is tested for here:
|
|
|
275
276
|
deadline, under mocked timers, and fails the way any round trip fails
|
|
276
277
|
- a successful insert gathered from a form resets the form, unless the
|
|
277
278
|
answer landed the new row on it
|
|
278
|
-
- a path
|
|
279
|
-
`lb-url-unknown` dialog; two pages for one stub
|
|
279
|
+
- a path naming a page that does not exist reports, lands `lb-page-label`
|
|
280
|
+
as null, and opens the `lb-url-unknown` dialog; two pages for one stub
|
|
281
|
+
report and take the first
|
|
280
282
|
- `lb-url` lands with the path, the page's `lb-page-title` or stub as
|
|
281
283
|
`lb-page-label`, and a column per query parm, and sets the document title
|
|
282
284
|
- `lb-url-link` pushes state and swaps the page on a plain primary click,
|