@loadbare/app 0.12.0 → 0.14.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 +87 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/cli.js +2 -1
- package/dist/build/cli.js.map +1 -1
- package/dist/build/elements.d.ts +9 -1
- package/dist/build/elements.d.ts.map +1 -1
- package/dist/build/elements.js +50 -0
- package/dist/build/elements.js.map +1 -1
- package/dist/build/origins.d.ts +2 -0
- package/dist/build/origins.d.ts.map +1 -1
- package/dist/build/origins.js +1 -1
- package/dist/build/origins.js.map +1 -1
- package/dist/core/lb-constants.d.ts +34 -1
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +105 -0
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +74 -18
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +74 -11
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +57 -18
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +661 -63
- 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 +400 -33
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts +19 -7
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +62 -26
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +80 -11
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +185 -33
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +584 -111
- package/docs/comparison.md +17 -13
- package/docs/possible-ideas.md +308 -0
- package/docs/reference/chrome.md +7 -1
- package/docs/reference/custom-elements.md +134 -39
- package/docs/reference/data-binding.md +405 -17
- package/docs/reference/page-files.md +101 -19
- package/docs/reference/server.md +24 -0
- package/docs/reference/widgets.md +118 -25
- package/docs/roadmap.md +17 -6
- package/docs/testing.md +21 -10
- package/package.json +2 -3
- package/skills/loadbare-app/SKILL.md +92 -30
- package/skills/loadbare-app/references/TECHREF-1.0.md +584 -111
- package/skills/loadbare-app/references/chrome.md +7 -1
- package/skills/loadbare-app/references/custom-elements.md +134 -39
- package/skills/loadbare-app/references/data-binding.md +405 -17
- package/skills/loadbare-app/references/page-files.md +101 -19
- package/skills/loadbare-app/references/server.md +24 -0
- package/skills/loadbare-app/references/widgets.md +118 -25
|
@@ -72,6 +72,10 @@ Put everything the user interacts with inside `<lb-hub>`. The hub normally
|
|
|
72
72
|
sits directly inside `<body>`, with banner, nav, footer and `<main>` inside
|
|
73
73
|
it, so Loadbare can act on all of them.
|
|
74
74
|
|
|
75
|
+
Write exactly one `<lb-hub>` and exactly one `<main>`, with the `<main>`
|
|
76
|
+
inside the hub and empty but for whitespace. The builder rejects a chrome
|
|
77
|
+
that does otherwise.
|
|
78
|
+
|
|
75
79
|
The chrome's `<title>` is the document title until the first page shows.
|
|
76
80
|
From then on the hub sets the document title to the page's label; see
|
|
77
81
|
[The URL](#the-url).
|
|
@@ -165,7 +169,9 @@ pushes one instead when the element carrying `lb-request` also carries
|
|
|
165
169
|
|
|
166
170
|
The hub answers the request itself, with no round trip, then reloads the
|
|
167
171
|
page's queries at the new URL. The page stays in place, and rows that come
|
|
168
|
-
back keep their place.
|
|
172
|
+
back keep their place. A request that changes only `lb-order-<query>`, the
|
|
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.
|
|
169
175
|
|
|
170
176
|
A control whose column the URL does not carry lands empty, so every control
|
|
171
177
|
inside `lb-query="lb-url"` shows what the address bar says, after a reload
|
|
@@ -278,7 +278,10 @@ A custom element reads `lb-` attributes and never assigns one. The developer
|
|
|
278
278
|
writes them in markup, and the hub and the builder write their stamps.
|
|
279
279
|
|
|
280
280
|
Loadbare reserves method names beginning with `lb` on a custom element, for
|
|
281
|
-
the methods it calls; see [Holding rows](#holding-rows).
|
|
281
|
+
the methods it calls; see [Holding rows](#holding-rows). The build refuses
|
|
282
|
+
a script that declares a method, accessor or field whose name is `lb`, a
|
|
283
|
+
capital, and anything else Loadbare does not call, so a misspelled
|
|
284
|
+
`lbRowLanded` fails the build rather than never being called.
|
|
282
285
|
|
|
283
286
|
### What the hub and an element say to each other
|
|
284
287
|
|
|
@@ -286,9 +289,9 @@ Each direction has one mechanism for each kind of message:
|
|
|
286
289
|
|
|
287
290
|
| Direction | What | How | Today |
|
|
288
291
|
|----------------|--------------------------------------------|-----------------------------|-------|
|
|
289
|
-
| Hub to element | State that lasts | An attribute the hub stamps | `lb-column-value`, `lb-key-value`, `lb-query-row-count`, `lb-request-pending`, `lb-request-error` |
|
|
292
|
+
| Hub to element | State that lasts | An attribute the hub stamps | `lb-column-value`, `lb-key-value`, `lb-query-row-count`, `lb-group-*`, `lb-row-*`, `lb-request-pending`, `lb-request-error` |
|
|
290
293
|
| Hub to element | State the platform already names | A property | A control's `value` |
|
|
291
|
-
| Hub to element | Work the hub needs done now, while landing | An optional `lb` method | `
|
|
294
|
+
| Hub to element | Work the hub needs done now, while landing | An optional `lb` method | `lbRowsLanded` |
|
|
292
295
|
| Hub to element | A moment an element started | A bubbling event | `lb-request-done` |
|
|
293
296
|
| Element to hub | A moment | A bubbling event | `lb-request`, and `change`, `click` and `submit` |
|
|
294
297
|
|
|
@@ -329,7 +332,7 @@ So each kind of work has one place:
|
|
|
329
332
|
reads no attribute and no child: an element made with
|
|
330
333
|
`document.createElement` has neither when it runs.
|
|
331
334
|
2. **A child is looked up when it is needed**, in a handler, a getter,
|
|
332
|
-
|
|
335
|
+
or `lbRowsLanded`, and never held from setup.
|
|
333
336
|
3. **`connectedCallback` runs on every move**, so it is written to run
|
|
334
337
|
again. It rearranges the element's own children into a state it checks
|
|
335
338
|
for first, or adds a listener to `document` or `window`, which
|
|
@@ -409,9 +412,104 @@ including through the HTML `form` attribute, so a form gathers it on submit.
|
|
|
409
412
|
Write `formResetCallback` to restore the default value: the hub resets a form
|
|
410
413
|
after a successful insert.
|
|
411
414
|
|
|
415
|
+
A control takes the message of a refusal naming its column when it has
|
|
416
|
+
`setCustomValidity` and `reportValidity`, as a native control does; see
|
|
417
|
+
[Refusals](./data-binding.md#refusals). A control wrapping a native one
|
|
418
|
+
passes both to it, so the browser shows the message there and focus lands
|
|
419
|
+
there.
|
|
420
|
+
|
|
412
421
|
The `<lb-input>`, `<lb-select>`, `<lb-options>` and `<lb-picker>` widgets
|
|
413
422
|
are controls; see [The Basic Widget Library](./widgets.md).
|
|
414
423
|
|
|
424
|
+
### Example: a file's text as a value
|
|
425
|
+
|
|
426
|
+
The hub takes no file input as a control. A custom element wraps one and is
|
|
427
|
+
the control in its place. This one reads the chosen file as text, which
|
|
428
|
+
suits a CSV or a bank statement, and sends the file's name under a second
|
|
429
|
+
column:
|
|
430
|
+
|
|
431
|
+
```html
|
|
432
|
+
<!-- src/file-text.html -->
|
|
433
|
+
<label>{{label}} <input type="file" accept="{{accept}}" /></label>
|
|
434
|
+
<input type="hidden" lb-column="{{name-column}}" />
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
```ts
|
|
438
|
+
// src/file-text.browser.ts
|
|
439
|
+
class FileText extends HTMLElement {
|
|
440
|
+
static formAssociated = true;
|
|
441
|
+
#internals = this.attachInternals();
|
|
442
|
+
#value = "";
|
|
443
|
+
|
|
444
|
+
constructor() {
|
|
445
|
+
super();
|
|
446
|
+
this.addEventListener("change", (e) => {
|
|
447
|
+
const input = e.target as HTMLInputElement;
|
|
448
|
+
if (e.target === this || input.type !== "file") return;
|
|
449
|
+
e.stopPropagation();
|
|
450
|
+
void this.read(input);
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
get value(): string {
|
|
455
|
+
return this.#value;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
set value(value: string) {
|
|
459
|
+
this.#value = value ?? "";
|
|
460
|
+
this.#internals.setFormValue(this.#value);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
formResetCallback() {
|
|
464
|
+
this.value = "";
|
|
465
|
+
this.setName("");
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async read(input: HTMLInputElement) {
|
|
469
|
+
const file = input.files?.[0] ?? null;
|
|
470
|
+
this.value = file ? await file.text() : "";
|
|
471
|
+
this.setName(file?.name ?? "");
|
|
472
|
+
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
setName(name: string) {
|
|
476
|
+
const hidden = this.querySelector<HTMLInputElement>('input[type="hidden"]');
|
|
477
|
+
if (hidden) hidden.value = name;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
customElements.define("file-text", FileText);
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
```html
|
|
485
|
+
<!-- src/uploads.page.html -->
|
|
486
|
+
<form lb-query="uploads" lb-request="lb-row-insert">
|
|
487
|
+
<file-text
|
|
488
|
+
lb-column="filetext"
|
|
489
|
+
exp-name-column="filename"
|
|
490
|
+
exp-label="Statement file"
|
|
491
|
+
exp-accept=".csv,.ofx"
|
|
492
|
+
></file-text>
|
|
493
|
+
<button type="submit">Upload</button>
|
|
494
|
+
</form>
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Reading a file is asynchronous, so the element stops the file input's own
|
|
498
|
+
`change` and fires its own once the text is in hand. A form submitted before
|
|
499
|
+
then gathers the empty value, and the handler refuses it as no file.
|
|
500
|
+
|
|
501
|
+
A control gathers one column, so the name rides in a hidden input that the
|
|
502
|
+
hub gathers as a control of its own. The form gathers both on submit. Its
|
|
503
|
+
reset after the insert clears the file input but not the hidden one, whose
|
|
504
|
+
`value` is its default, so `formResetCallback` clears the name itself.
|
|
505
|
+
|
|
506
|
+
The text travels in the request's JSON body, which `hubRoutes` limits to
|
|
507
|
+
100 KB unless the server raises it; see [Options](./server.md#options).
|
|
508
|
+
|
|
509
|
+
The choices here are this application's: text rather than binary, the whole
|
|
510
|
+
file in the request, the name in a second column. A different application
|
|
511
|
+
writes its own element, under its own name, to make different ones.
|
|
512
|
+
|
|
415
513
|
### Receiving a value
|
|
416
514
|
|
|
417
515
|
A custom element that is not a control keeps the content the builder placed
|
|
@@ -491,7 +589,8 @@ this.addEventListener(LB_DONE_EVENT_NAME, (e) => {
|
|
|
491
589
|
```
|
|
492
590
|
|
|
493
591
|
`items` is every response item that landed because of the request, in
|
|
494
|
-
order.
|
|
592
|
+
order. `refusal` is set beside `error` when the handler refused the
|
|
593
|
+
request, holding its `message` and `columns`. An answer that moved the URL contributes its `lb-url` item, which
|
|
495
594
|
carries a key only the server knew, and the page load. `error` is set when
|
|
496
595
|
the round trip failed, and then nothing landed. A new row's key is in the
|
|
497
596
|
answer only when the handler returned it in a patch: a refresh sends all
|
|
@@ -505,34 +604,32 @@ outside the document, and no ancestor it had there hears it.
|
|
|
505
604
|
|
|
506
605
|
### Holding rows
|
|
507
606
|
|
|
508
|
-
The hub lands every row template itself
|
|
509
|
-
|
|
510
|
-
|
|
607
|
+
The hub lands every row template itself, places every row by the query's
|
|
608
|
+
order, and builds every group the markup's group templates describe; see
|
|
609
|
+
[Order](./data-binding.md#order) and [Groups](./data-binding.md#groups). A
|
|
610
|
+
plain element carrying `lb-query` with a row template inside it needs no
|
|
611
|
+
code, so a custom element holds rows only to do something with them once
|
|
612
|
+
they land.
|
|
511
613
|
|
|
512
|
-
A custom element carrying `lb-query` and a row template may implement
|
|
513
|
-
optional
|
|
614
|
+
A custom element carrying `lb-query` and a row template may implement one
|
|
615
|
+
optional method, which the hub calls:
|
|
514
616
|
|
|
515
617
|
```ts
|
|
516
|
-
import type { RowsHost
|
|
517
|
-
|
|
518
|
-
class SortedList extends HTMLElement implements RowsHost {
|
|
519
|
-
lbPlaceRow(el: Element, row: Row, template: HTMLTemplateElement) {
|
|
520
|
-
// Where this live row goes. Called with the live row detached, on its
|
|
521
|
-
// first appearance and again whenever all rows decide the order.
|
|
522
|
-
}
|
|
618
|
+
import type { RowsHost } from "@loadbare/app/types";
|
|
619
|
+
import { ATTR_ROW_REQUESTED, REQUESTED_CREATED } from "@loadbare/app/constants";
|
|
523
620
|
|
|
621
|
+
class ScrollingList extends HTMLElement implements RowsHost {
|
|
524
622
|
lbRowsLanded() {
|
|
525
|
-
// Once, after the rows have landed
|
|
526
|
-
|
|
527
|
-
|
|
623
|
+
// Once, after the rows have landed, every row placed and stamped.
|
|
624
|
+
this.querySelector(`[${ATTR_ROW_REQUESTED}="${REQUESTED_CREATED}"]`)
|
|
625
|
+
?.scrollIntoView({ block: "nearest" });
|
|
528
626
|
}
|
|
529
627
|
}
|
|
530
628
|
```
|
|
531
629
|
|
|
532
|
-
| Method | The hub calls it
|
|
533
|
-
|
|
534
|
-
| `
|
|
535
|
-
| `lbRowsLanded` | After the rows land |
|
|
630
|
+
| Method | The hub calls it |
|
|
631
|
+
|----------------|-------------------------------------------------------|
|
|
632
|
+
| `lbRowsLanded` | After the rows land, with every row placed and stamped |
|
|
536
633
|
|
|
537
634
|
Everything else is the hub's:
|
|
538
635
|
|
|
@@ -540,25 +637,23 @@ Everything else is the hub's:
|
|
|
540
637
|
|-------------|----------------------------------------------------------|
|
|
541
638
|
| Cloning | Clones the row template once per new key |
|
|
542
639
|
| Matching | Fills the live row already showing that key |
|
|
543
|
-
|
|
|
544
|
-
|
|
|
640
|
+
| Placing | Places every live row by the query's order |
|
|
641
|
+
| Grouping | Builds a group where the order breaks, and removes it with its last row |
|
|
642
|
+
| Removing | Marks the live rows the response says are gone as leaving, and removes them |
|
|
643
|
+
| Stamping | Stamps each live row with `lb-row-live`, `lb-key-value`, and what happened to it |
|
|
545
644
|
| Counting | Stamps `lb-query-row-count` with the number of live rows |
|
|
546
645
|
|
|
547
|
-
`
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
different placements over the same landing.
|
|
646
|
+
`lb-options.browser.ts` and `lb-table.browser.ts` in
|
|
647
|
+
[`@loadbare/widgets`](./widgets.md) are two uses of `lbRowsLanded`: one
|
|
648
|
+
gives each option and `<optgroup>` what landing does not, a value and a
|
|
649
|
+
label, and the other scrolls to the row the page's request created or
|
|
650
|
+
moved.
|
|
553
651
|
|
|
554
652
|
A custom element the builder shipped absent under `lb-show` has not
|
|
555
|
-
upgraded while its column is off,
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
`lbRowsLanded` runs. Once upgraded it stays so: when its branch goes away and
|
|
560
|
-
comes back, it has placed every row that landed meanwhile, and nothing is
|
|
561
|
-
landed again.
|
|
653
|
+
upgraded while its column is off, and the hub places the rows that land on
|
|
654
|
+
it then as it places any. When the column first turns on and the element
|
|
655
|
+
upgrades, the hub lands the query's last answer on it again, as all rows,
|
|
656
|
+
so `lbRowsLanded` runs.
|
|
562
657
|
|
|
563
658
|
A custom element that walks its own rows finds them with `LIVE_ROW` from
|
|
564
659
|
`@loadbare/app/constants`, never by `lb-key-value`: an element a `row` lands
|