@loadbare/app 0.16.0 → 0.17.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/README.md +10 -14
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +15 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/core/lb-constants.d.ts +6 -2
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +38 -8
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +57 -20
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +122 -11
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +38 -26
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +655 -471
- 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 +77 -59
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/hub/lb-lifecycle.d.ts +1 -2
- package/dist/hub/lb-lifecycle.d.ts.map +1 -1
- package/dist/hub/lb-lifecycle.js +9 -3
- package/dist/hub/lb-lifecycle.js.map +1 -1
- package/dist/server/lb-server.d.ts +29 -12
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +72 -11
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +162 -48
- package/docs/comparison.md +9 -8
- package/docs/reference/chrome.md +8 -5
- package/docs/reference/custom-elements.md +25 -7
- package/docs/reference/data-binding.md +125 -22
- package/docs/reference/page-files.md +51 -7
- package/docs/reference/widgets.md +5 -1
- package/docs/roadmap.md +8 -0
- package/docs/testing.md +6 -2
- package/docs/theory-old.md +839 -0
- package/docs/theory.md +113 -839
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +28 -15
- package/skills/loadbare-app/references/TECHREF-1.0.md +162 -48
- package/skills/loadbare-app/references/chrome.md +8 -5
- package/skills/loadbare-app/references/custom-elements.md +25 -7
- package/skills/loadbare-app/references/data-binding.md +125 -22
- package/skills/loadbare-app/references/page-files.md +51 -7
- package/skills/loadbare-app/references/widgets.md +5 -1
package/package.json
CHANGED
|
@@ -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-push` and `lb-url-unknown`; one form pointed at a row by the `--lb-edit`, `--lb-new` and `--lb-release` commands; build-time expansion with `exp-*` parameters, `lb-exp-slot` and `lb-exp-template`; custom elements as form-associated controls and row hosts; the Express wiring with `hubRoutes`; and the `@loadbare/widgets` library. Use whenever a task involves `@loadbare/app`, `@loadbare/widgets`, `loadbare-app-build`, an `lb-` attribute, or a page, query, request or custom element file in a Loadbare application. The model is not React, htmx or REST, and cannot be inferred from them.
|
|
3
|
+
description: Build server-bound web applications with Loadbare/app. Covers the file conventions the builder finds by name (`chrome.html`, `*.page.html`, `*.queries.ts`, `*.requests.ts`, `imports.ts`, `<tag>.html`, `<tag>.browser.ts`); the `lb-*` attribute vocabulary that lands query rows on HTML and issues requests (`lb-query`, `lb-column`, `lb-show`, `lb-request`); queries declared with `row(key, run)` and `rows(key, run)`; the URL as the hub's own query `lb-url`, with `lb-url-link`, `lb-url-push` and `lb-url-unknown`; the user's order and filters as the hub's query `lb-choices`, read by `lb-order` and `lb-filter`; one form pointed at a row by the `--lb-edit`, `--lb-new` and `--lb-release` commands; 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"
|
|
@@ -189,11 +189,23 @@ in.
|
|
|
189
189
|
**A `rows` query declares its order, and the hub places every row by it.**
|
|
190
190
|
`rows("id", run, { order: "category_order,name" })`; a column after `-` sorts
|
|
191
191
|
descending, and values compare by JSON type, so a numeric sort column is a
|
|
192
|
-
JSON number
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
JSON number or is declared one: `types: { amount: "number" }` beside
|
|
193
|
+
`order`. Never sort in a widget, and never send a placeholder row to
|
|
194
|
+
hold a place.
|
|
195
|
+
|
|
196
|
+
**The user's order and filters are choices, not query parms.** The hub
|
|
197
|
+
serves a second query, `lb-choices`, keyed by `lb-path`, one column per
|
|
198
|
+
choice, named by the application. A control inside
|
|
199
|
+
`lb-query="lb-choices"` with `lb-request="lb-row-update"` makes a choice.
|
|
200
|
+
`lb-order="<choice>"` on the element carrying `lb-query` places its rows by
|
|
201
|
+
the order that choice holds, in place of the server's while it is not
|
|
202
|
+
empty. `lb-filter="col, col"` there hides each row that does not pass the
|
|
203
|
+
choice of the same name: `^=Amazon`, `>=2026-01-01 <=2026-03-31`, or plain
|
|
204
|
+
text for contains. A choice shows with no round trip, then the server's
|
|
205
|
+
`onChoices(ctx, choices)` hears every choice, to keep them;
|
|
206
|
+
`onPageEnter` returns `choices()` to restore them. Choices hold until the
|
|
207
|
+
page changes. A filter that decides which rows the server sends is a query
|
|
208
|
+
parm.
|
|
197
209
|
|
|
198
210
|
**Groups are templates.** A `<template lb-group>` holds a heading and one
|
|
199
211
|
nested `<template>`, the next level or the row template; the nth breaks on
|
|
@@ -201,11 +213,12 @@ the order's nth term, to any depth. Contents land before the nested
|
|
|
201
213
|
template, so put it inside the heading's element for a container and beside
|
|
202
214
|
the heading for a heading row. `<tbody>` and `<optgroup>` do not nest. The
|
|
203
215
|
heading is filled from the group's first row. `lb-count`, `lb-sum="col"`,
|
|
204
|
-
`lb-avg`, `lb-min` and `lb-max` total the
|
|
205
|
-
outside any.
|
|
216
|
+
`lb-avg`, `lb-min` and `lb-max` total the rows showing in the nearest group,
|
|
217
|
+
or in the whole list outside any.
|
|
206
218
|
|
|
207
219
|
**Animate with CSS.** The hub stamps `lb-row-created`, `lb-row-changed`,
|
|
208
|
-
`lb-row-moved
|
|
220
|
+
`lb-row-moved` (its values changed and it now stands elsewhere), and
|
|
221
|
+
`lb-row-requested` for this page's request, and marks a
|
|
209
222
|
leaving row or group `lb-row-leaving` or `lb-group-leaving`, removing it once
|
|
210
223
|
its animations end. Scrolling to a row is script, in `lbRowsLanded`.
|
|
211
224
|
|
|
@@ -329,7 +342,7 @@ layer between the page and its queries.
|
|
|
329
342
|
the element sits.
|
|
330
343
|
|
|
331
344
|
**The query string is what the page has on screen.** Which record a page
|
|
332
|
-
shows, a filter, a date range: each is a query parm,
|
|
345
|
+
shows, a filter the server applies, a date range: each is a query parm,
|
|
333
346
|
`/accounts?acct=23&from=2026-09-09`, so a reload, a bookmark or a mailed link
|
|
334
347
|
shows the same thing. The hub serves the query `lb-url`, of kind `row`,
|
|
335
348
|
keyed by `lb-path`, with `lb-page-label`, `lb-page-unknown`, and one column
|
|
@@ -371,9 +384,9 @@ whole data channel.
|
|
|
371
384
|
|
|
372
385
|
**The developer writes `lb-*` attributes in markup, and script never
|
|
373
386
|
assigns them.** The builder refuses any `lb-` attribute other than
|
|
374
|
-
`lb-query`, `lb-column`, `lb-show`, `lb-
|
|
375
|
-
`lb-url-push` and `lb-url-unknown`. Everything else with the
|
|
376
|
-
stamp the hub or the builder writes.
|
|
387
|
+
`lb-query`, `lb-column`, `lb-show`, `lb-order`, `lb-filter`, `lb-request`,
|
|
388
|
+
`lb-url-link`, `lb-url-push` and `lb-url-unknown`. Everything else with the
|
|
389
|
+
prefix is a stamp the hub or the builder writes.
|
|
377
390
|
|
|
378
391
|
**`lb-` belongs to Loadbare.** The application should never name anything
|
|
379
392
|
with the `lb-` prefix anywhere: no attribute, query, column, request, custom
|
|
@@ -463,8 +476,8 @@ with the package, so no network is needed.
|
|
|
463
476
|
gathering, requests, conditions and request state. Start here for
|
|
464
477
|
anything in a page.
|
|
465
478
|
- [`references/page-files.md`](references/page-files.md) — what page
|
|
466
|
-
files are, queries, `onPageEnter`, handlers, `crud`, refresh
|
|
467
|
-
and `url()`.
|
|
479
|
+
files are, queries, `onPageEnter`, `onChoices`, handlers, `crud`, refresh
|
|
480
|
+
and patch, `url()` and `choices()`.
|
|
468
481
|
- [`references/custom-elements.md`](references/custom-elements.md) —
|
|
469
482
|
expansion, parameters, slots, destinations, and custom element code and
|
|
470
483
|
when it runs.
|
|
@@ -22,9 +22,13 @@ a value is rendered by browser coercion when it lands on an HTML text
|
|
|
22
22
|
element or a control, and by whatever the custom element does with
|
|
23
23
|
`lb-column-value` when it lands on one that is not a control.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
by their JSON type,
|
|
27
|
-
|
|
25
|
+
Three places read a value's type today. The [order](#order) compares
|
|
26
|
+
values by their JSON type, a [filter](#filters) reads its value as the
|
|
27
|
+
column's type, and an [aggregate](#aggregates) reads a sum or an average
|
|
28
|
+
from a JSON number or a string holding a plain decimal. A `rows` query may
|
|
29
|
+
declare a column's type, which the order, a filter, `lb-min` and `lb-max`
|
|
30
|
+
read the column as in place of its JSON type. No declared type changes how
|
|
31
|
+
a value renders.
|
|
28
32
|
|
|
29
33
|
We will then see if a useful solution emerges that Loadbare/app should
|
|
30
34
|
handle.
|
|
@@ -404,7 +408,7 @@ query.
|
|
|
404
408
|
| `lb-column-value` | The value it set |
|
|
405
409
|
| `lb-key-value` | The row's key |
|
|
406
410
|
| `lb-row-live` | Nothing; it marks a live row |
|
|
407
|
-
| `lb-query-row-count` | The number of live rows it
|
|
411
|
+
| `lb-query-row-count` | The number of live rows it shows |
|
|
408
412
|
|
|
409
413
|
The markup names a query and the columns it shows. The kind and the key are
|
|
410
414
|
the server's, and the markup states neither.
|
|
@@ -441,7 +445,8 @@ element is a control.
|
|
|
441
445
|
Name one query on more than one element to show it in more than one place.
|
|
442
446
|
Every one of them receives it.
|
|
443
447
|
|
|
444
|
-
A query that arrives with nowhere to land is reported to the console
|
|
448
|
+
A query that arrives with nowhere to land is reported to the console,
|
|
449
|
+
unless its name begins with `lb-`.
|
|
445
450
|
|
|
446
451
|
#### How a column lands
|
|
447
452
|
|
|
@@ -518,7 +523,8 @@ so all rows landing again unchanged move nothing. A live row already in the
|
|
|
518
523
|
markup when the first answer lands is one of the query's rows.
|
|
519
524
|
|
|
520
525
|
After every landing the hub stamps the element with `lb-query-row-count`,
|
|
521
|
-
the number of live rows it
|
|
526
|
+
the number of live rows it shows. A row a [filter](#filters) hides is not
|
|
527
|
+
counted. The server answers with rows and says
|
|
522
528
|
nothing about how many survived, so this is the one fact a page cannot be
|
|
523
529
|
sent. It makes an empty query a stylesheet rule:
|
|
524
530
|
|
|
@@ -530,10 +536,15 @@ sent. It makes an empty query a stylesheet rule:
|
|
|
530
536
|
|
|
531
537
|
A row missing its key column is reported to the console and not landed.
|
|
532
538
|
|
|
539
|
+
When the focus is in a live row that placing moves, the hub puts it back on
|
|
540
|
+
the same element and scrolls it into view. When that row leaves, or a
|
|
541
|
+
filter hides it, the focus goes to the first element the user can operate
|
|
542
|
+
in the first row showing.
|
|
543
|
+
|
|
533
544
|
#### Order
|
|
534
545
|
|
|
535
546
|
A `rows` query's order is a rule over its columns. The server declares it
|
|
536
|
-
with the query, and the
|
|
547
|
+
with the query, and the user may choose another:
|
|
537
548
|
|
|
538
549
|
```ts
|
|
539
550
|
accounts: rows("id", (ctx) => ctx.db.accounts(), {
|
|
@@ -542,9 +553,10 @@ accounts: rows("id", (ctx) => ctx.db.accounts(), {
|
|
|
542
553
|
```
|
|
543
554
|
|
|
544
555
|
An order is columns separated by commas. A column written after `-` sorts
|
|
545
|
-
descending.
|
|
546
|
-
|
|
547
|
-
|
|
556
|
+
descending. `lb-order`, on the element carrying `lb-query`, names a column
|
|
557
|
+
of [`lb-choices`](#choices) holding the user's order, and while that column
|
|
558
|
+
is not empty it replaces the declared order. With neither, rows show in the
|
|
559
|
+
order the server sent them, and a patch's new rows go last.
|
|
548
560
|
|
|
549
561
|
| Values | Compare |
|
|
550
562
|
| -------------------- | ------------------------------------------ |
|
|
@@ -555,27 +567,75 @@ show in the order the server sent them, and a patch's new rows go last.
|
|
|
555
567
|
| `null` or missing | After everything ascending, first descending |
|
|
556
568
|
|
|
557
569
|
A number sent as a string sorts as a string, so a column the order reads
|
|
558
|
-
numerically arrives as a JSON number
|
|
559
|
-
|
|
560
|
-
|
|
570
|
+
numerically arrives as a JSON number, or its query declares its type.
|
|
571
|
+
`types` names a type for any of a `rows` query's columns, one of `number`,
|
|
572
|
+
`boolean` and `text`, and the column compares read as that type whatever
|
|
573
|
+
JSON type its values arrive as:
|
|
574
|
+
|
|
575
|
+
```ts
|
|
576
|
+
accounts: rows("id", (ctx) => ctx.db.accounts(), {
|
|
577
|
+
order: "-balance",
|
|
578
|
+
types: { balance: "number" },
|
|
579
|
+
}),
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
A value that is no value of its declared type compares as `null` does.
|
|
583
|
+
`createHub` refuses at startup a type it does not know.
|
|
584
|
+
|
|
585
|
+
The declared order and types travel once, on the answer that loads the
|
|
586
|
+
page, and the hub keeps them with the query's answer for every answer after
|
|
587
|
+
it, all rows or a patch. `readAs` in
|
|
588
|
+
`@loadbare/app/types` is the rule the hub applies.
|
|
589
|
+
|
|
590
|
+
Rows that compare equal keep the order they arrived in, and a patch's new
|
|
591
|
+
rows come after the rows already showing.
|
|
561
592
|
|
|
562
|
-
The hub sorts the rows it has, so a
|
|
563
|
-
|
|
593
|
+
The hub sorts the rows it has, so a choice of order places them again with
|
|
594
|
+
no round trip:
|
|
564
595
|
|
|
565
596
|
```html
|
|
566
|
-
<div lb-query="lb-
|
|
567
|
-
<select lb-column="
|
|
597
|
+
<div lb-query="lb-choices">
|
|
598
|
+
<select lb-column="accounts_order" lb-request="lb-row-update">
|
|
568
599
|
<option value="">By category</option>
|
|
569
600
|
<option value="account_name">By name</option>
|
|
570
601
|
</select>
|
|
571
602
|
</div>
|
|
603
|
+
|
|
604
|
+
<table lb-query="accounts" lb-order="accounts_order">
|
|
605
|
+
...
|
|
606
|
+
</table>
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### Filters
|
|
610
|
+
|
|
611
|
+
`lb-filter`, on the element carrying `lb-query`, names the columns of its
|
|
612
|
+
rows a choice may filter, separated by commas. The column of
|
|
613
|
+
[`lb-choices`](#choices) of the same name holds the filter. A row that does
|
|
614
|
+
not pass every filter is `hidden`, and a ticked `lb-select` in it is
|
|
615
|
+
cleared. A group whose rows are all hidden is hidden. An empty choice
|
|
616
|
+
filters nothing.
|
|
617
|
+
|
|
618
|
+
```html
|
|
619
|
+
<table lb-query="accounts" lb-filter="account_name, balance">
|
|
572
620
|
```
|
|
573
621
|
|
|
574
|
-
A
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
622
|
+
A filter is terms, each an operator and a value. A term begins wherever
|
|
623
|
+
whitespace comes before an operator, so a value may hold spaces. Text with
|
|
624
|
+
no operator is `*=`. A term with no value is left out. Every term must
|
|
625
|
+
pass: `>=2026-01-01 <=2026-03-31`.
|
|
626
|
+
|
|
627
|
+
| Operator | Compares |
|
|
628
|
+
| -------------------------- | ------------------------------------------------- |
|
|
629
|
+
| `^=`, `$=`, `*=` | As text, ignoring case: begins with, ends with, contains |
|
|
630
|
+
| `=`, `!=`, `<`, `<=`, `>`, `>=` | As the [order](#order) compares, with the value read as the column's type |
|
|
631
|
+
|
|
632
|
+
The column's type is its declared [type](#order), if its query declares
|
|
633
|
+
one. Otherwise it is a number for a JSON number, `true` or `false` for a
|
|
634
|
+
boolean, and text otherwise. A value that is not of the column's type, and
|
|
635
|
+
a column that is null or missing, pass only `!=`.
|
|
636
|
+
|
|
637
|
+
`parseFilter`, `passes` and `passesTerm` in `@loadbare/app/types` are the
|
|
638
|
+
rule the hub applies.
|
|
579
639
|
|
|
580
640
|
#### Groups
|
|
581
641
|
|
|
@@ -617,8 +677,8 @@ filled, so it shows any column of the row. The example breaks on
|
|
|
617
677
|
The hub stamps each top-level element of a group's clone with
|
|
618
678
|
`lb-group-live`, `lb-group-column`, the column it breaks on, and
|
|
619
679
|
`lb-group-value`, its value there. A row creates its group, and a group
|
|
620
|
-
leaves with its last row.
|
|
621
|
-
|
|
680
|
+
leaves with its last row. When the order changes, a group whose run goes
|
|
681
|
+
on is kept and moved, and a group whose run ended leaves.
|
|
622
682
|
|
|
623
683
|
A group template with no nested template is reported to the console. More
|
|
624
684
|
group templates than the order has terms show each extra level as one
|
|
@@ -648,7 +708,8 @@ precise value, and an average up to two more. `null` and empty values are
|
|
|
648
708
|
left out, as SQL leaves them out. Any other value is left out and reported
|
|
649
709
|
once. The hub does not format the result.
|
|
650
710
|
|
|
651
|
-
An aggregate covers the rows
|
|
711
|
+
An aggregate covers the rows showing, so a row a [filter](#filters) hides
|
|
712
|
+
is left out. Where the true total
|
|
652
713
|
matters beyond what the page shows, it is a row the server answers.
|
|
653
714
|
|
|
654
715
|
#### What happened to a row
|
|
@@ -660,7 +721,7 @@ application animates with CSS alone and the hub starts no animation.
|
|
|
660
721
|
| ------------------ | -------------------- | -------------------------------------------------- |
|
|
661
722
|
| `lb-row-created` | A live row | Created when the hub last touched it |
|
|
662
723
|
| `lb-row-changed` | A live row | Its values changed when the hub last touched it |
|
|
663
|
-
| `lb-row-moved` | A live row |
|
|
724
|
+
| `lb-row-moved` | A live row | Its values changed, and it now stands elsewhere |
|
|
664
725
|
| `lb-row-requested` | A live row | `created`, `changed` or `moved` by this page's request |
|
|
665
726
|
| `lb-row-leaving` | A row on its way out | No longer live |
|
|
666
727
|
| `lb-group-leaving` | A group on its way out | No longer live |
|
|
@@ -674,8 +735,12 @@ row's query, and set only by a landing that answers a request from the page.
|
|
|
674
735
|
A row or a group that leaves loses `lb-row-live` or `lb-group-live`, takes
|
|
675
736
|
`lb-row-leaving` or `lb-group-leaving` and `inert`, and is removed once the
|
|
676
737
|
animations running on it have finished, at once when there are none. A
|
|
677
|
-
|
|
678
|
-
|
|
738
|
+
row leaves when all rows arrive without its key, or a patch drops it.
|
|
739
|
+
|
|
740
|
+
A row is moved when its values changed and the nearest rows whose values did
|
|
741
|
+
not change, before and after it, are not the ones it stood between. A row
|
|
742
|
+
it passed is not stamped, and a change of the user's order, which changes no
|
|
743
|
+
values, stamps none. A moved row stays live and moves.
|
|
679
744
|
|
|
680
745
|
```css
|
|
681
746
|
[lb-row-created] { animation: arrive 200ms; }
|
|
@@ -1341,10 +1406,10 @@ names each one in the row it lands.
|
|
|
1341
1406
|
|
|
1342
1407
|
The hub sends the query parms with every round trip, a page load and a
|
|
1343
1408
|
request alike. The server passes them to `contextFor` — see
|
|
1344
|
-
[The Express server](#the-express-server). Loadbare assigns
|
|
1345
|
-
meaning
|
|
1346
|
-
|
|
1347
|
-
|
|
1409
|
+
[The Express server](#the-express-server). Loadbare assigns no parm a
|
|
1410
|
+
meaning: a column of `lb-url` whose name begins with `lb-` is never a query
|
|
1411
|
+
parm. An order or a filter the hub applies to rows already on the page is
|
|
1412
|
+
a [choice](#choices), not a parm.
|
|
1348
1413
|
|
|
1349
1414
|
#### An unknown page
|
|
1350
1415
|
|
|
@@ -1409,8 +1474,8 @@ rowInsert: {
|
|
|
1409
1474
|
to other query parms, keeps the URL they are on.
|
|
1410
1475
|
|
|
1411
1476
|
`onPageEnter` may return `url()` the same way, to move the page before
|
|
1412
|
-
anything shows, as an application restoring the
|
|
1413
|
-
|
|
1477
|
+
anything shows, as an application restoring the parms the user last had
|
|
1478
|
+
does. The page loads at the new URL in the same round trip, and
|
|
1414
1479
|
that load does not follow `onPageEnter` again. A `url()` leading to the
|
|
1415
1480
|
page and parms already in hand is ignored, so the page loads once. When to
|
|
1416
1481
|
restore is the application's rule, such as only when the URL carries no
|
|
@@ -1428,12 +1493,51 @@ onPageEnter: async (ctx) => {
|
|
|
1428
1493
|
Saving what the user has on screen is a declared request with
|
|
1429
1494
|
`refresh: []`, whose handler each page passes to a routine the
|
|
1430
1495
|
application's pages share. A custom element naming `lb-url` sees every
|
|
1431
|
-
change of the URL and issues it
|
|
1432
|
-
included.
|
|
1496
|
+
change of the URL and issues it.
|
|
1433
1497
|
|
|
1434
1498
|
The page is loaded with a second context, built by `contextFor` from the new
|
|
1435
1499
|
parms — see [The Express server](#the-express-server).
|
|
1436
1500
|
|
|
1501
|
+
### Choices
|
|
1502
|
+
|
|
1503
|
+
The hub serves the query `lb-choices`, of kind `row`, keyed by `lb-path`,
|
|
1504
|
+
with a column for each choice the user made for how rows show: an
|
|
1505
|
+
[order](#order) or a [filter](#filters). The application names the
|
|
1506
|
+
columns. It lands wherever an element names it, like any server query.
|
|
1507
|
+
|
|
1508
|
+
A control inside `lb-query="lb-choices"` that sends `lb-row-update` makes a
|
|
1509
|
+
choice. A request with `lb-row-update` for `lb-choices` or `lb-url` from
|
|
1510
|
+
anywhere on the page is keyed by the path, so a custom element may
|
|
1511
|
+
dispatch one without sitting inside the query.
|
|
1512
|
+
|
|
1513
|
+
A choice joins the ones already made, and needs no round trip to show:
|
|
1514
|
+
every element whose `lb-order` or `lb-filter` reads a column that changed
|
|
1515
|
+
lands its query's last answer again, so it shows what a round trip carrying
|
|
1516
|
+
the choice would. Then the hub sends `lb-row-update` for `lb-choices`,
|
|
1517
|
+
keyed by the path, with every choice made on the page as `values`, and no
|
|
1518
|
+
element pending. The server runs the page's `onChoices` with them, when it
|
|
1519
|
+
has one, and otherwise answers nothing. Whatever `onChoices` returns lands,
|
|
1520
|
+
and by convention it returns nothing.
|
|
1521
|
+
|
|
1522
|
+
Choices hold until the page changes, and a change of query parm keeps them.
|
|
1523
|
+
On entering a page, every column named under `lb-query="lb-choices"` lands
|
|
1524
|
+
empty. `onPageEnter` restores them by returning `choices()`, alone or
|
|
1525
|
+
spread beside `url()`:
|
|
1526
|
+
|
|
1527
|
+
```ts
|
|
1528
|
+
onPageEnter: async (ctx) => {
|
|
1529
|
+
const saved = await ctx.db.savedChoices("accounts");
|
|
1530
|
+
if (saved) return choices(saved);
|
|
1531
|
+
},
|
|
1532
|
+
onChoices: (ctx, chosen) => ctx.db.saveChoices("accounts", chosen),
|
|
1533
|
+
```
|
|
1534
|
+
|
|
1535
|
+
The page load then answers the `lb-choices` item first, then the queries.
|
|
1536
|
+
When `url()` moves the page, the choices arrive with the load at the new
|
|
1537
|
+
URL. A
|
|
1538
|
+
`choices()` naming no column, or holding a value that is not a string, is
|
|
1539
|
+
reported on the server console and ignored, as for `url()`.
|
|
1540
|
+
|
|
1437
1541
|
### The markup checks
|
|
1438
1542
|
|
|
1439
1543
|
The builder checks the chrome and every page, after expansion, and refuses
|
|
@@ -1441,8 +1545,8 @@ to build on any of these:
|
|
|
1441
1545
|
|
|
1442
1546
|
- An `lb-` attribute that is not a developer attribute: `lb-query`,
|
|
1443
1547
|
`lb-column`, `lb-show`, `lb-group`, `lb-count`, `lb-sum`, `lb-avg`,
|
|
1444
|
-
`lb-min`, `lb-max`, `lb-
|
|
1445
|
-
`lb-url-push`, `lb-url-unknown`. Every other `lb-` attribute is a stamp.
|
|
1548
|
+
`lb-min`, `lb-max`, `lb-order`, `lb-filter`, `lb-request`, `lb-select`,
|
|
1549
|
+
`lb-url-link`, `lb-url-push`, `lb-url-unknown`. Every other `lb-` attribute is a stamp.
|
|
1446
1550
|
`lb-exp-slot` and `lb-exp-template` are consumed by expansion and never
|
|
1447
1551
|
reach the check.
|
|
1448
1552
|
- `lb-request` naming a value that begins with `lb-` and is not one of the
|
|
@@ -1454,6 +1558,8 @@ to build on any of these:
|
|
|
1454
1558
|
- `lb-show` on a `<template>`, on a row template's root, or with no
|
|
1455
1559
|
`lb-query` around it.
|
|
1456
1560
|
- `lb-show="!"` or `lb-show="!!column"`, which reverse no column.
|
|
1561
|
+
- `lb-order` or `lb-filter` on an element not carrying `lb-query`, or naming
|
|
1562
|
+
no column.
|
|
1457
1563
|
- `lb-select` on anything but an `<input type="checkbox">`, outside a row
|
|
1458
1564
|
template, or beside `lb-column` or `lb-request`.
|
|
1459
1565
|
- A `command` beginning `--lb-` that is not one of the three
|
|
@@ -1718,13 +1824,14 @@ as explained in the next section.
|
|
|
1718
1824
|
### Page Requests
|
|
1719
1825
|
|
|
1720
1826
|
`<stub>.requests.ts` exports one object named `requests`, typed `Requests`.
|
|
1721
|
-
It has
|
|
1827
|
+
It has four optional keys.
|
|
1722
1828
|
|
|
1723
1829
|
| Key | Keyed by | Answers |
|
|
1724
1830
|
| ------------- | --------------------- | -------------------------------------------------- |
|
|
1725
1831
|
| `handlers` | The request name | The page's declared requests |
|
|
1726
1832
|
| `crud` | A query name | The three requests Loadbare provides |
|
|
1727
|
-
| `onPageEnter` | Nothing | Runs once on entering the page, before its queries, and may move the URL |
|
|
1833
|
+
| `onPageEnter` | Nothing | Runs once on entering the page, before its queries, and may move the URL or restore [choices](#choices) |
|
|
1834
|
+
| `onChoices` | Nothing | Runs with every choice made on the page, each time the user makes one |
|
|
1728
1835
|
|
|
1729
1836
|
The server resolves a declared request against `handlers`, and a request
|
|
1730
1837
|
Loadbare provides against `crud` under the request's query. A name with no
|
|
@@ -1840,8 +1947,10 @@ A response item carries exactly one of `row`, `rows` or `patch`. A patch
|
|
|
1840
1947
|
answers a `rows` query only: rows named in `rows` are added or updated, keys
|
|
1841
1948
|
in `drop` are removed, and every other row is left alone.
|
|
1842
1949
|
|
|
1843
|
-
A `rows` item also carries `order`
|
|
1844
|
-
|
|
1950
|
+
A `rows` item also carries `order` when the query declares one.
|
|
1951
|
+
|
|
1952
|
+
A choice is sent as `lb-row-update` for `lb-choices`, keyed by the path,
|
|
1953
|
+
with every choice made on the page as `values`; see [Choices](#choices).
|
|
1845
1954
|
|
|
1846
1955
|
`createHub(pages)` builds the `Hub`, which has two calls, both answering
|
|
1847
1956
|
with response items: `dataForPage(page, ctx, options)` for a page load, and
|
|
@@ -1926,7 +2035,7 @@ calls four optional methods, which the `HubLifecycle` interface in
|
|
|
1926
2035
|
| Removes it: a row or group done leaving, the page replaced | `lbDetached()`, once |
|
|
1927
2036
|
| Moves a live row the order put elsewhere | Nothing |
|
|
1928
2037
|
| Turns `lb-show` off or on | Nothing |
|
|
1929
|
-
|
|
|
2038
|
+
| Hides a row or a group for a filter | Nothing |
|
|
1930
2039
|
|
|
1931
2040
|
The chrome and a page are placed as the page's first answer lands, or once
|
|
1932
2041
|
that round trip fails. An element under an `lb-show` that is off is placed
|
|
@@ -2062,6 +2171,8 @@ it may define tomorrow.
|
|
|
2062
2171
|
| `lb-url-unknown` | Developer | A `<dialog>` inside `<lb-hub>` | [An unknown page](#an-unknown-page) |
|
|
2063
2172
|
| `lb-group` | Developer | A `<template>` holding a `<template>` | [Groups](#groups) |
|
|
2064
2173
|
| `lb-count`, `lb-sum`, `lb-avg`, `lb-min`, `lb-max` | Developer | Any element but a `<template>` | [Aggregates](#aggregates) |
|
|
2174
|
+
| `lb-order` | Developer | An element with `lb-query` | [Order](#order) |
|
|
2175
|
+
| `lb-filter` | Developer | An element with `lb-query` | [Filters](#filters) |
|
|
2065
2176
|
| `lb-exp-slot` | Developer | One element in an element file | [Slots and templates](#slots-and-templates) |
|
|
2066
2177
|
| `lb-exp-template` | Developer | An element file, and a `<template>` | [Slots and templates](#slots-and-templates) |
|
|
2067
2178
|
| `lb-column-value` | Hub | Every element set from a column | [How a column lands](#how-a-column-lands) |
|
|
@@ -2088,12 +2199,12 @@ The builder refuses any other `lb-` attribute in markup — see
|
|
|
2088
2199
|
| Query | Kind | Key | Columns | Defined in |
|
|
2089
2200
|
| -------- | ----- | --------- | --------------------------------------------------------------- | ------------------- |
|
|
2090
2201
|
| `lb-url` | `row` | `lb-path` | `lb-path`, `lb-page-label`, `lb-page-unknown`, every query parm | [The URL](#the-url) |
|
|
2202
|
+
| `lb-choices` | `row` | `lb-path` | `lb-path`, every choice | [Choices](#choices) |
|
|
2091
2203
|
|
|
2092
2204
|
### Reserved query parms
|
|
2093
2205
|
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
| `lb-order-<query>` | The user's order for a query | [Order](#order) |
|
|
2206
|
+
None. A column of `lb-url` whose name begins with `lb-` is never a query
|
|
2207
|
+
parm — see [Query parms](#query-parms).
|
|
2097
2208
|
|
|
2098
2209
|
### Reserved request names
|
|
2099
2210
|
|
|
@@ -2164,8 +2275,11 @@ imports them rather than writing a string.
|
|
|
2164
2275
|
| `LIVE_GROUP` | `[lb-group-live]`, the selector for a group's element |
|
|
2165
2276
|
| `ATTR_COUNT`, `ATTR_SUM`, `ATTR_AVG`, `ATTR_MIN`, `ATTR_MAX` | `lb-count`, `lb-sum`, `lb-avg`, `lb-min`, `lb-max` |
|
|
2166
2277
|
| `AGGREGATES` | All five aggregate attributes |
|
|
2167
|
-
| `ORDER_PARM_PREFIX` | `lb-order-` |
|
|
2168
2278
|
| `ORDER_DESCENDING` | `-`, written before a column in an order |
|
|
2279
|
+
| `CHOICES_QUERY` | `lb-choices` |
|
|
2280
|
+
| `ATTR_ORDER` | `lb-order` |
|
|
2281
|
+
| `ATTR_FILTER` | `lb-filter` |
|
|
2282
|
+
| `FILTER_OPERATORS` | Every filter operator, the longer first |
|
|
2169
2283
|
| `ATTR_ROW_CREATED` | `lb-row-created` |
|
|
2170
2284
|
| `ATTR_ROW_CHANGED` | `lb-row-changed` |
|
|
2171
2285
|
| `ATTR_ROW_MOVED` | `lb-row-moved` |
|
|
@@ -2191,7 +2305,7 @@ imports them rather than writing a string.
|
|
|
2191
2305
|
| `ATTR_EXP_TEMPLATE` | `lb-exp-template` |
|
|
2192
2306
|
| `ATTR_PAGE` | `lb-page` |
|
|
2193
2307
|
| `ATTR_PAGE_TITLE` | `lb-page-title` |
|
|
2194
|
-
| `DEVELOPER_ATTRIBUTES` | The
|
|
2308
|
+
| `DEVELOPER_ATTRIBUTES` | The sixteen attributes a developer writes |
|
|
2195
2309
|
| `LB_EVENT_NAME` | `lb-request` |
|
|
2196
2310
|
| `LB_DONE_EVENT_NAME` | `lb-request-done` |
|
|
2197
2311
|
| `SHOW_NOT` | `!`, written before a column in `lb-show` |
|
|
@@ -109,8 +109,9 @@ page file carries; see [page files](./page-files.md#the-page-title). The hub
|
|
|
109
109
|
sets the document title to `lb-page-label` whenever it is not null, so the
|
|
110
110
|
tab and the browser history show the page.
|
|
111
111
|
|
|
112
|
-
`lb-url` is
|
|
113
|
-
|
|
112
|
+
`lb-url` is one of two queries a page may use that the server does not
|
|
113
|
+
declare. The other is [`lb-choices`](./data-binding.md#choices). A page
|
|
114
|
+
names either the same way, anywhere inside the hub.
|
|
114
115
|
|
|
115
116
|
### Where focus starts
|
|
116
117
|
|
|
@@ -169,14 +170,16 @@ pushes one instead when the element carrying `lb-request` also carries
|
|
|
169
170
|
|
|
170
171
|
The hub answers the request itself, with no round trip, then reloads the
|
|
171
172
|
page's queries at the new URL. The page stays in place, and rows that come
|
|
172
|
-
back keep their place.
|
|
173
|
-
user's [order](./data-binding.md#order) for a query the hub sorts itself,
|
|
174
|
-
re-sorts the rows already on the page and loads nothing.
|
|
173
|
+
back keep their place.
|
|
175
174
|
|
|
176
175
|
A control whose column the URL does not carry lands empty, so every control
|
|
177
176
|
inside `lb-query="lb-url"` shows what the address bar says, after a reload
|
|
178
177
|
and after Back alike.
|
|
179
178
|
|
|
179
|
+
An order or a filter the hub applies to rows the page already holds is not
|
|
180
|
+
a query parm. It is a [choice](./data-binding.md#choices), which holds until
|
|
181
|
+
the page changes.
|
|
182
|
+
|
|
180
183
|
The hub sends the query parms with every round trip, and the server hands
|
|
181
184
|
them to `contextFor`; see [the Express server](./server.md#database-layer).
|
|
182
185
|
A handler moves the URL by returning `url()`, when only the server knows the
|
|
@@ -271,6 +271,7 @@ one as a string literal:
|
|
|
271
271
|
| `LB_DONE_EVENT_NAME` | `lb-request-done`, the event that says how it turned out |
|
|
272
272
|
| `SHOW_NOT` | `!`, written before a column in `lb-show` |
|
|
273
273
|
| `URL_QUERY` | `lb-url` |
|
|
274
|
+
| `CHOICES_QUERY` | `lb-choices` |
|
|
274
275
|
| `URL_COLUMN_PATH`, `URL_COLUMN_PAGE_LABEL`, `URL_COLUMN_PAGE_UNKNOWN` | `lb-path`, `lb-page-label`, `lb-page-unknown` |
|
|
275
276
|
| `LB_RESERVED_PREFIX` | `lb-` |
|
|
276
277
|
|
|
@@ -356,9 +357,8 @@ inside it, and `lbDetached` on the inner ones first. A table that sets the
|
|
|
356
357
|
`form` attribute on its controls in `lbAttached` does so before each control
|
|
357
358
|
hears its own.
|
|
358
359
|
|
|
359
|
-
An element a script creates hears none of the four
|
|
360
|
-
|
|
361
|
-
them only on what it places.
|
|
360
|
+
An element a script creates hears none of the four. The hub calls them only
|
|
361
|
+
on what it places.
|
|
362
362
|
|
|
363
363
|
Never write `connectedCallback`, `disconnectedCallback`, `adoptedCallback`
|
|
364
364
|
or `connectedMoveCallback`. The browser calls those on every move, and the
|
|
@@ -589,6 +589,22 @@ missing a field its name needs, and stamps the dispatching element with
|
|
|
589
589
|
|
|
590
590
|
Let the event bubble, so an ancestor can stop it before the hub sends it.
|
|
591
591
|
|
|
592
|
+
A request with `lb-row-update` for `lb-url` or `lb-choices` is keyed by the
|
|
593
|
+
path, so an element anywhere on the page may set a query parm or make a
|
|
594
|
+
[choice](./data-binding.md#choices) without sitting inside the query:
|
|
595
|
+
|
|
596
|
+
```ts
|
|
597
|
+
import { CHOICES_QUERY, LB_EVENT_NAME, REQUEST_ROW_UPDATE } from "@loadbare/app/constants";
|
|
598
|
+
import type { HubRequest } from "@loadbare/app/types";
|
|
599
|
+
|
|
600
|
+
const detail: HubRequest = {
|
|
601
|
+
name: REQUEST_ROW_UPDATE,
|
|
602
|
+
query: CHOICES_QUERY,
|
|
603
|
+
values: { ledger_order: "-amount" },
|
|
604
|
+
};
|
|
605
|
+
this.dispatchEvent(new CustomEvent(LB_EVENT_NAME, { bubbles: true, detail }));
|
|
606
|
+
```
|
|
607
|
+
|
|
592
608
|
### Hearing how it turned out
|
|
593
609
|
|
|
594
610
|
Once what a request brought back has landed, or its round trip has failed,
|
|
@@ -617,7 +633,8 @@ listener. Import its name as `LB_DONE_EVENT_NAME`.
|
|
|
617
633
|
`items` is every response item that landed because of the request, in
|
|
618
634
|
order. `refusal` is set beside `error` when the handler refused the
|
|
619
635
|
request, holding its `message` and `columns`. An answer that moved the URL contributes its `lb-url` item, which
|
|
620
|
-
carries a key only the server knew, and the page load.
|
|
636
|
+
carries a key only the server knew, and the page load. A choice contributes
|
|
637
|
+
the row of `lb-choices` it made. `error` is set when
|
|
621
638
|
the round trip failed, and then nothing landed. A new row's key is in the
|
|
622
639
|
answer only when the handler returned it in a patch: a refresh sends all
|
|
623
640
|
rows, and nothing marks which one is new.
|
|
@@ -660,11 +677,12 @@ Everything else is the hub's:
|
|
|
660
677
|
|-------------|----------------------------------------------------------|
|
|
661
678
|
| Cloning | Clones the row template once per new key |
|
|
662
679
|
| Matching | Fills the live row already showing that key, when its values changed |
|
|
663
|
-
| Placing | Places every live row by the query's
|
|
664
|
-
|
|
|
680
|
+
| Placing | Places every live row by the user's order or the query's |
|
|
681
|
+
| Filtering | Hides a row the user's filter does not pass, and a group whose rows are all hidden |
|
|
682
|
+
| Grouping | Builds a group where the order breaks, keeps it while its run goes on, and removes it with its last row |
|
|
665
683
|
| Removing | Marks the live rows the response says are gone as leaving, and removes them |
|
|
666
684
|
| Stamping | Stamps each live row with `lb-row-live`, `lb-key-value`, and what happened to it |
|
|
667
|
-
| Counting | Stamps `lb-query-row-count` with the number of live rows |
|
|
685
|
+
| Counting | Stamps `lb-query-row-count` with the number of live rows showing |
|
|
668
686
|
|
|
669
687
|
`lb-options.browser.ts` and `lb-table.browser.ts` in
|
|
670
688
|
[`@loadbare/widgets`](./widgets.md) are two uses of `lbRowsLanded`: one
|