@loadbare/app 0.14.0 → 0.16.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/elements.d.ts +12 -2
- package/dist/build/elements.d.ts.map +1 -1
- package/dist/build/elements.js +44 -10
- package/dist/build/elements.js.map +1 -1
- package/dist/core/lb-constants.d.ts +2 -1
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +16 -3
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +25 -8
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +9 -0
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +118 -35
- 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 +41 -5
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/hub/lb-lifecycle.d.ts +40 -0
- package/dist/hub/lb-lifecycle.d.ts.map +1 -0
- package/dist/hub/lb-lifecycle.js +140 -0
- package/dist/hub/lb-lifecycle.js.map +1 -0
- package/docs/TECHREF-1.0.md +49 -47
- package/docs/comparison.md +7 -5
- package/docs/possible-ideas.md +6 -0
- package/docs/reference/custom-elements.md +110 -89
- package/docs/reference/data-binding.md +12 -7
- package/docs/reference/widgets.md +2 -2
- package/docs/testing.md +2 -2
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +20 -16
- package/skills/loadbare-app/references/TECHREF-1.0.md +49 -47
- package/skills/loadbare-app/references/custom-elements.md +110 -89
- package/skills/loadbare-app/references/data-binding.md +12 -7
- package/skills/loadbare-app/references/widgets.md +2 -2
|
@@ -238,7 +238,7 @@ and are not gathered.
|
|
|
238
238
|
row.** A form cannot sit inside another form or in a table row, so a dialog
|
|
239
239
|
that creates an account while a posting's picker is choosing one goes at the
|
|
240
240
|
end of the page, and each row opens it with `commandfor`. The dialog learns
|
|
241
|
-
the new key
|
|
241
|
+
the new key in `lbRequestDone`.
|
|
242
242
|
|
|
243
243
|
**A set the user edits has one form, pointed at a row.** Never put a form
|
|
244
244
|
in every row. Write one form naming the set's query, outside every row,
|
|
@@ -387,25 +387,29 @@ element (`static formAssociated = true`) with a `value` property that fires
|
|
|
387
387
|
on `change`. Any other custom element keeps its content and receives the
|
|
388
388
|
column as its `lb-column-value` attribute.
|
|
389
389
|
|
|
390
|
-
**A custom element
|
|
391
|
-
hub
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
390
|
+
**A custom element hears the hub's lifecycle, never the browser's.** The
|
|
391
|
+
hub calls `lbAttached()` once when it places the element, already filled,
|
|
392
|
+
and `lbDetached()` once when it removes it. Moving a row and turning
|
|
393
|
+
`lb-show` off and on call neither, and the instance is kept. Never write
|
|
394
|
+
`connectedCallback`, `disconnectedCallback`, `adoptedCallback` or
|
|
395
|
+
`connectedMoveCallback`; the build refuses them. Listen on the element
|
|
396
|
+
itself in the constructor, look a child up when it is needed, and put
|
|
397
|
+
once-per-instance setup in `lbAttached` with its undoing in `lbDetached`.
|
|
396
398
|
|
|
397
399
|
**The hub and a custom element talk in four ways, one per kind of
|
|
398
400
|
message.** State the hub gives an element is an attribute stamp, or `value`
|
|
399
|
-
on a control.
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
`lb-request
|
|
403
|
-
|
|
404
|
-
|
|
401
|
+
on a control. What the hub did to an element is an optional `lb` method:
|
|
402
|
+
`lbAttached`, `lbRowsLanded`, `lbRequestDone`, `lbDetached`, declared by
|
|
403
|
+
`HubLifecycle`. A moment is a bubbling event: an element sends
|
|
404
|
+
`lb-request`, and the hub answers by calling `lbRequestDone(detail,
|
|
405
|
+
origin)` on the custom elements from the committing element outward, then
|
|
406
|
+
dispatching `lb-request-done` from it, each carrying the request and the
|
|
407
|
+
response items that landed, or the error. A dialog choosing the row its
|
|
408
|
+
form just created implements `lbRequestDone`.
|
|
405
409
|
|
|
406
410
|
**A widget that holds rows may sit under `lb-show`.** Rows that land while
|
|
407
|
-
it is away are placed by the hub
|
|
408
|
-
|
|
411
|
+
it is away are placed by the hub and its `lbRowsLanded` runs, so hide a
|
|
412
|
+
table with `lb-show`, not with a stylesheet rule.
|
|
409
413
|
|
|
410
414
|
**Name a custom element script `<tag>.browser.ts`.** A plain `<tag>.ts`
|
|
411
415
|
stays on the server and the tag goes unregistered.
|
|
@@ -434,7 +438,7 @@ parser loses the tag before the build can report it.
|
|
|
434
438
|
Reach for one only when plain HTML cannot do the job. A set of rows, a form
|
|
435
439
|
and a condition need none. A custom element exists to be a control of its
|
|
436
440
|
own, or to act on rows once they land through the hook the hub calls,
|
|
437
|
-
`lbRowsLanded` (the `
|
|
441
|
+
`lbRowsLanded` (the `HubLifecycle` interface).
|
|
438
442
|
|
|
439
443
|
Before writing one, check `@loadbare/widgets`: `lb-input`, `lb-select`,
|
|
440
444
|
`lb-options`, `lb-picker`, `lb-table`, `lb-unknown-page`, `lb-confirm`,
|
|
@@ -715,10 +715,9 @@ standing where it stood, and moved back out when the column turns on. It is
|
|
|
715
715
|
not rendered, focused, clicked, announced or gathered. It is moved and
|
|
716
716
|
never rebuilt, so a custom element keeps its instance and a control keeps
|
|
717
717
|
what was typed into it. Landing reaches into that template, so the element
|
|
718
|
-
and everything inside it return current. A custom element
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
`lb-column-value` while it is away.
|
|
718
|
+
and everything inside it return current. A custom element hears nothing
|
|
719
|
+
going in or coming out, and still receives `lb-column-value` while it is
|
|
720
|
+
away.
|
|
722
721
|
|
|
723
722
|
The builder ships every `lb-show` element already inside its template, so
|
|
724
723
|
nothing conditional shows until its row lands. An absent element's template
|
|
@@ -1098,8 +1097,10 @@ makes a confirmation wrapper possible without the wrapped element knowing
|
|
|
1098
1097
|
about it.
|
|
1099
1098
|
|
|
1100
1099
|
Once what the request brought back has landed, or its round trip has failed,
|
|
1101
|
-
the hub
|
|
1102
|
-
element
|
|
1100
|
+
the hub calls `lbRequestDone(detail, origin)` on the committing element and
|
|
1101
|
+
every custom element around it, innermost first (see
|
|
1102
|
+
[Lifecycle](#lifecycle)), then dispatches the bubbling `lb-request-done`
|
|
1103
|
+
event from the same element. Its `detail`, `HubRequestDone` in `@loadbare/app/types`, holds
|
|
1103
1104
|
the request as the hub sent it and `items`, every response item that landed
|
|
1104
1105
|
because of it, in order. An answer that moved the URL contributes its
|
|
1105
1106
|
`lb-url` item and the page load. `error` is set instead when the round trip
|
|
@@ -1884,14 +1885,12 @@ Each direction has one mechanism for each kind of message:
|
|
|
1884
1885
|
| -------------- | ------------------------------------------- | ---------------------------- | ------------------------------------------------ |
|
|
1885
1886
|
| 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` |
|
|
1886
1887
|
| Hub to element | State the platform already names | A property | A control's `value` |
|
|
1887
|
-
| Hub to element |
|
|
1888
|
+
| Hub to element | What the hub did | An optional `lb` method | `lbAttached`, `lbRowsLanded`, `lbRequestDone`, `lbDetached` |
|
|
1888
1889
|
| Hub to element | A moment an element started | A bubbling event | `lb-request-done` |
|
|
1889
1890
|
| Element to hub | A moment | A bubbling event | `lb-request`, and `change`, `click` and `submit` |
|
|
1890
1891
|
|
|
1891
|
-
State is an attribute, because a stylesheet can select on it
|
|
1892
|
-
|
|
1893
|
-
on without, since it acts on one element at one point in landing and nothing
|
|
1894
|
-
else can do it. A moment is an event, because the element that cares is
|
|
1892
|
+
State is an attribute, because a stylesheet can select on it. A method is
|
|
1893
|
+
how the hub tells one element what it just did to that element. A moment is an event, because the element that cares is
|
|
1895
1894
|
often an ancestor of the one it concerns, and an event reaches it with no
|
|
1896
1895
|
knowledge of either.
|
|
1897
1896
|
|
|
@@ -1910,45 +1909,47 @@ class NoteField extends HTMLElement {
|
|
|
1910
1909
|
}
|
|
1911
1910
|
```
|
|
1912
1911
|
|
|
1913
|
-
A control that is not yet upgraded when its column lands receives
|
|
1914
|
-
`lb-column-value` alone, since the hub sets `value` only on a control. That
|
|
1915
|
-
happens to an element the builder shipped absent, and to one whose
|
|
1916
|
-
definition loads after the hub lands. A control takes the stamp up the
|
|
1917
|
-
first time it connects, and never again.
|
|
1918
|
-
|
|
1919
1912
|
A custom element that is not a control receives `lb-column-value` and
|
|
1920
1913
|
renders it; its content is never replaced.
|
|
1921
1914
|
|
|
1922
1915
|
### Lifecycle
|
|
1923
1916
|
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
|
1929
|
-
|
|
|
1930
|
-
|
|
|
1931
|
-
|
|
|
1932
|
-
|
|
|
1933
|
-
|
|
|
1934
|
-
|
|
|
1917
|
+
A custom element hears the hub's lifecycle, never the browser's. The hub
|
|
1918
|
+
calls four optional methods, which the `HubLifecycle` interface in
|
|
1919
|
+
`@loadbare/app/types` declares:
|
|
1920
|
+
|
|
1921
|
+
| The hub | A custom element hears |
|
|
1922
|
+
| ------------------------------------------------ | ------------------------------- |
|
|
1923
|
+
| Places it: chrome at startup, a page, a new live row, a new group | `lbAttached()`, once, after every column has landed on it |
|
|
1924
|
+
| Lands rows on it | `lbRowsLanded()` |
|
|
1925
|
+
| Finishes a request committed by it or inside it | `lbRequestDone(detail, origin)` |
|
|
1926
|
+
| Removes it: a row or group done leaving, the page replaced | `lbDetached()`, once |
|
|
1927
|
+
| Moves a live row the order put elsewhere | Nothing |
|
|
1928
|
+
| Turns `lb-show` off or on | Nothing |
|
|
1929
|
+
| Leaves a copy of a moved row behind | Nothing, on the copy |
|
|
1930
|
+
|
|
1931
|
+
The chrome and a page are placed as the page's first answer lands, or once
|
|
1932
|
+
that round trip fails. An element under an `lb-show` that is off is placed
|
|
1933
|
+
inside its template, so `lbAttached` runs whether it shows or not. `lbAttached` reaches an outer
|
|
1934
|
+
custom element before the ones inside it, and `lbDetached` the inner ones
|
|
1935
|
+
first. `lbRequestDone` reaches the committing element and every custom
|
|
1936
|
+
element around it, innermost first, before the `lb-request-done` event.
|
|
1937
|
+
An element a script creates hears none of them.
|
|
1935
1938
|
|
|
1936
1939
|
A listener on the element itself goes in the constructor, which reads no
|
|
1937
|
-
attribute and no child. A child is looked up when it is needed.
|
|
1938
|
-
|
|
1939
|
-
done once per instance goes behind a flag.
|
|
1940
|
+
attribute and no child. A child is looked up when it is needed. Work done
|
|
1941
|
+
once per instance goes in `lbAttached`, and its undoing in `lbDetached`.
|
|
1940
1942
|
|
|
1941
|
-
|
|
1943
|
+
The build refuses a script that declares `connectedCallback`,
|
|
1944
|
+
`disconnectedCallback`, `adoptedCallback` or `connectedMoveCallback`.
|
|
1942
1945
|
|
|
1943
|
-
|
|
1944
|
-
| ---------------- | -------------- | ------------------------------------------------------ |
|
|
1945
|
-
| `lbRowsLanded()` | Developer | After the rows land, with every row placed and stamped |
|
|
1946
|
+
### Row hooks
|
|
1946
1947
|
|
|
1947
|
-
The hub calls
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1948
|
+
The hub calls `lbRowsLanded()` on a custom element with `lb-query` and a row
|
|
1949
|
+
template, after the rows land, with every row placed and stamped. The hub
|
|
1950
|
+
places every row and builds every group itself, so a custom element reacts
|
|
1951
|
+
to rows and never places them. Scrolling to the row the page's request
|
|
1952
|
+
created is the case:
|
|
1952
1953
|
|
|
1953
1954
|
```ts
|
|
1954
1955
|
lbRowsLanded() {
|
|
@@ -1957,10 +1958,8 @@ lbRowsLanded() {
|
|
|
1957
1958
|
}
|
|
1958
1959
|
```
|
|
1959
1960
|
|
|
1960
|
-
A custom element
|
|
1961
|
-
|
|
1962
|
-
upgrades, the hub lands the query's last answer on it again, as all rows,
|
|
1963
|
-
so the hook runs.
|
|
1961
|
+
A custom element under an `lb-show` that is off holds its rows all the
|
|
1962
|
+
same, and the hook runs as they land.
|
|
1964
1963
|
|
|
1965
1964
|
`applyRow(root, row)`, exported by `@loadbare/app`, fills `root` from one
|
|
1966
1965
|
row, the same operation that fills a live row.
|
|
@@ -2136,9 +2135,12 @@ Loadbare/app owns every DOM event in this table, both the name and what its
|
|
|
2136
2135
|
|
|
2137
2136
|
### Reserved methods
|
|
2138
2137
|
|
|
2139
|
-
| Method
|
|
2140
|
-
|
|
|
2141
|
-
| `
|
|
2138
|
+
| Method | On | Defined in |
|
|
2139
|
+
| --------------- | --------------------------------------------------- | ----------------------- |
|
|
2140
|
+
| `lbAttached` | Any custom element the hub places | [Lifecycle](#lifecycle) |
|
|
2141
|
+
| `lbRowsLanded` | A custom element with `lb-query` and a row template | [Row hooks](#row-hooks) |
|
|
2142
|
+
| `lbRequestDone` | A custom element that committed, or holds one that did | [Lifecycle](#lifecycle) |
|
|
2143
|
+
| `lbDetached` | Any custom element the hub removes | [Lifecycle](#lifecycle) |
|
|
2142
2144
|
|
|
2143
2145
|
### Constants
|
|
2144
2146
|
|
|
@@ -278,10 +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 [
|
|
282
|
-
a script that declares a method, accessor or field whose name
|
|
283
|
-
capital, and anything else Loadbare does not call, so a
|
|
284
|
-
`lbRowLanded` fails the build rather than never being called.
|
|
281
|
+
the methods it calls; see [When its code runs](#when-its-code-runs). The
|
|
282
|
+
build refuses a script that declares a method, accessor or field whose name
|
|
283
|
+
is `lb`, a capital, and anything else Loadbare does not call, so a
|
|
284
|
+
misspelled `lbRowLanded` fails the build rather than never being called.
|
|
285
285
|
|
|
286
286
|
### What the hub and an element say to each other
|
|
287
287
|
|
|
@@ -291,39 +291,80 @@ Each direction has one mechanism for each kind of message:
|
|
|
291
291
|
|----------------|--------------------------------------------|-----------------------------|-------|
|
|
292
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` |
|
|
293
293
|
| Hub to element | State the platform already names | A property | A control's `value` |
|
|
294
|
-
| Hub to element |
|
|
294
|
+
| Hub to element | What the hub did | An optional `lb` method | `lbAttached`, `lbRowsLanded`, `lbRequestDone`, `lbDetached` |
|
|
295
295
|
| Hub to element | A moment an element started | A bubbling event | `lb-request-done` |
|
|
296
296
|
| Element to hub | A moment | A bubbling event | `lb-request`, and `change`, `click` and `submit` |
|
|
297
297
|
|
|
298
|
-
State is an attribute
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
and an event reaches it knowing neither.
|
|
298
|
+
State is an attribute, because a stylesheet can select on it. A method is
|
|
299
|
+
how the hub tells one element what it just did to that element. A moment is
|
|
300
|
+
an event, because the element that cares is often an ancestor of the one it
|
|
301
|
+
concerns, and an event reaches it knowing neither.
|
|
303
302
|
|
|
304
303
|
### When its code runs
|
|
305
304
|
|
|
306
|
-
The hub
|
|
307
|
-
|
|
308
|
-
|
|
305
|
+
The hub tells a custom element what it did through four optional methods,
|
|
306
|
+
named for the hub's own work. The `HubLifecycle` interface in
|
|
307
|
+
`@loadbare/app/types` declares them. Here is an element that closes its
|
|
308
|
+
popup on Escape, listening on `document` only while the hub has it on the
|
|
309
|
+
page:
|
|
309
310
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
| Turns `lb-show` on | `adoptedCallback`, `connectedCallback` |
|
|
319
|
-
| Turns on an element the builder shipped absent | `constructor`, `connectedCallback` |
|
|
311
|
+
```ts
|
|
312
|
+
// src/note-popup.browser.ts
|
|
313
|
+
import type { HubLifecycle } from "@loadbare/app/types";
|
|
314
|
+
|
|
315
|
+
class NotePopup extends HTMLElement implements HubLifecycle {
|
|
316
|
+
#onKey = (e: KeyboardEvent) => {
|
|
317
|
+
if (e.key === "Escape") this.querySelector("dialog")?.close();
|
|
318
|
+
};
|
|
320
319
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
[Conditional rendering](./data-binding.md#conditional-rendering).
|
|
320
|
+
lbAttached() {
|
|
321
|
+
document.addEventListener("keydown", this.#onKey);
|
|
322
|
+
}
|
|
325
323
|
|
|
326
|
-
|
|
324
|
+
lbDetached() {
|
|
325
|
+
document.removeEventListener("keydown", this.#onKey);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
customElements.define("note-popup", NotePopup);
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
| Method | The hub calls it |
|
|
333
|
+
|---------------------------------|-------------------------------------------------------------------|
|
|
334
|
+
| `lbAttached()` | Once, after it places the element and every column has landed on it |
|
|
335
|
+
| `lbRowsLanded()` | After rows land on the element, with every row placed and stamped |
|
|
336
|
+
| `lbRequestDone(detail, origin)` | After a request committed by the element, or inside it, has finished |
|
|
337
|
+
| `lbDetached()` | Once, after it removes the element |
|
|
338
|
+
|
|
339
|
+
The hub places an element when it starts up the chrome, shows a page,
|
|
340
|
+
creates a live row, or builds a group. It places the chrome and a page as
|
|
341
|
+
the page's first answer lands, or once that round trip fails, so an element
|
|
342
|
+
in either hears `lbAttached` with the page's data in place. It removes an
|
|
343
|
+
element when a live row or a group has finished leaving, and when it shows
|
|
344
|
+
another page in place of the one holding it. Write setup in `lbAttached` and its undoing in
|
|
345
|
+
`lbDetached`; the two pair exactly, so neither guards against running
|
|
346
|
+
twice.
|
|
347
|
+
|
|
348
|
+
Moving a row and turning `lb-show` off and on are neither placing nor
|
|
349
|
+
removing. The element keeps its instance and hears nothing. An element
|
|
350
|
+
under an `lb-show` that is off is placed inside its template, so its
|
|
351
|
+
`lbAttached` runs whether or not it shows. Measure and focus when the user
|
|
352
|
+
acts, never in `lbAttached`, where the element may not be rendered.
|
|
353
|
+
|
|
354
|
+
The hub calls `lbAttached` on an outer custom element before the ones
|
|
355
|
+
inside it, and `lbDetached` on the inner ones first. A table that sets the
|
|
356
|
+
`form` attribute on its controls in `lbAttached` does so before each control
|
|
357
|
+
hears its own.
|
|
358
|
+
|
|
359
|
+
An element a script creates hears none of the four, and neither does the
|
|
360
|
+
copy of a moved row the hub leaves behind while it fades. The hub calls
|
|
361
|
+
them only on what it places.
|
|
362
|
+
|
|
363
|
+
Never write `connectedCallback`, `disconnectedCallback`, `adoptedCallback`
|
|
364
|
+
or `connectedMoveCallback`. The browser calls those on every move, and the
|
|
365
|
+
build refuses a script that declares one.
|
|
366
|
+
|
|
367
|
+
Each kind of work then has one place:
|
|
327
368
|
|
|
328
369
|
1. **A listener on the element itself goes in the constructor.** It is
|
|
329
370
|
attached once and survives every move, and a live row gets its own
|
|
@@ -331,15 +372,11 @@ So each kind of work has one place:
|
|
|
331
372
|
element, so the listener needs no child to exist yet. The constructor
|
|
332
373
|
reads no attribute and no child: an element made with
|
|
333
374
|
`document.createElement` has neither when it runs.
|
|
334
|
-
2. **A child is looked up when it is needed**, in a handler, a getter,
|
|
335
|
-
|
|
336
|
-
3.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
`disconnectedCallback` removes. Work done once per instance that needs
|
|
340
|
-
the element's attributes, such as a control taking up a value that landed
|
|
341
|
-
before it upgraded, goes behind a flag there; see
|
|
342
|
-
[Being a control](#being-a-control).
|
|
375
|
+
2. **A child is looked up when it is needed**, in a handler, a getter, or
|
|
376
|
+
one of the four methods, and never held from setup.
|
|
377
|
+
3. **Work done once per instance goes in `lbAttached`**, with its undoing
|
|
378
|
+
in `lbDetached`: rearranging the element's own children, or a listener on
|
|
379
|
+
`document` or `window`.
|
|
343
380
|
|
|
344
381
|
### Being a control
|
|
345
382
|
|
|
@@ -350,20 +387,10 @@ and commits its `lb-request` on `change`:
|
|
|
350
387
|
|
|
351
388
|
```ts
|
|
352
389
|
// src/star-rating.browser.ts
|
|
353
|
-
import { ATTR_COLUMN_VALUE } from "@loadbare/app/constants";
|
|
354
|
-
|
|
355
390
|
class StarRating extends HTMLElement {
|
|
356
391
|
static formAssociated = true;
|
|
357
392
|
#internals = this.attachInternals();
|
|
358
393
|
#value = "";
|
|
359
|
-
#connected = false;
|
|
360
|
-
|
|
361
|
-
connectedCallback() {
|
|
362
|
-
if (this.#connected) return;
|
|
363
|
-
this.#connected = true;
|
|
364
|
-
const stamped = this.getAttribute(ATTR_COLUMN_VALUE);
|
|
365
|
-
if (stamped !== null) this.value = stamped;
|
|
366
|
-
}
|
|
367
394
|
|
|
368
395
|
get value(): string {
|
|
369
396
|
return this.#value;
|
|
@@ -399,14 +426,6 @@ customElements.define("star-rating", StarRating);
|
|
|
399
426
|
Dispatch `change` with `bubbles: true`, as a native control's does, when the
|
|
400
427
|
user commits an edit. Setting `value` from the hub fires nothing.
|
|
401
428
|
|
|
402
|
-
A control can receive its value before it is a control. An element the
|
|
403
|
-
builder shipped absent, or one whose definition loads after the hub has
|
|
404
|
-
landed, is not upgraded when its column lands, so the hub cannot set its
|
|
405
|
-
`value` and the value arrives as `lb-column-value` alone. Take the stamp up
|
|
406
|
-
the first time the control connects, as `connectedCallback` does above, and
|
|
407
|
-
never again: after that the hub sets `value` itself, and a later move must
|
|
408
|
-
not undo an edit.
|
|
409
|
-
|
|
410
429
|
A form owns a form-associated custom element the way it owns an `<input>`,
|
|
411
430
|
including through the HTML `form` attribute, so a form gathers it on submit.
|
|
412
431
|
Write `formResetCallback` to restore the default value: the hub resets a form
|
|
@@ -538,7 +557,9 @@ customElements.define("visit-count", VisitCount);
|
|
|
538
557
|
List `ATTR_COLUMN_VALUE` in `observedAttributes`. The browser calls
|
|
539
558
|
`attributeChangedCallback` for an attribute already present when an element
|
|
540
559
|
upgrades, as well as for one that changes afterward, so the first render and
|
|
541
|
-
every later one go through the one callback.
|
|
560
|
+
every later one go through the one callback. A landing that brings the value
|
|
561
|
+
the element already carries leaves the attribute alone, and the callback does
|
|
562
|
+
not run.
|
|
542
563
|
|
|
543
564
|
A custom element carrying `lb-show`, or inside an element that does, still
|
|
544
565
|
receives its column while it is away, so it returns current; see
|
|
@@ -571,23 +592,28 @@ Let the event bubble, so an ancestor can stop it before the hub sends it.
|
|
|
571
592
|
### Hearing how it turned out
|
|
572
593
|
|
|
573
594
|
Once what a request brought back has landed, or its round trip has failed,
|
|
574
|
-
the hub
|
|
575
|
-
|
|
576
|
-
|
|
595
|
+
the hub calls `lbRequestDone(detail, origin)` on the custom element that
|
|
596
|
+
committed and on every custom element around it, innermost first. `origin`
|
|
597
|
+
is the element that committed, so the element that cares need not be the
|
|
598
|
+
one that committed: a dialog hears it from the form inside it.
|
|
577
599
|
|
|
578
600
|
```ts
|
|
579
|
-
import {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
}
|
|
601
|
+
import type { HubLifecycle, HubRequestDone } from "@loadbare/app/types";
|
|
602
|
+
|
|
603
|
+
class NewRowDialog extends HTMLElement implements HubLifecycle {
|
|
604
|
+
lbRequestDone({ request, items, error }: HubRequestDone) {
|
|
605
|
+
if (error) return;
|
|
606
|
+
const item = items.find((i) => i.query === request.query);
|
|
607
|
+
const created = item?.patch?.rows?.[0];
|
|
608
|
+
if (created) this.choose(String(created[item!.key]));
|
|
609
|
+
}
|
|
610
|
+
}
|
|
589
611
|
```
|
|
590
612
|
|
|
613
|
+
The hub then dispatches `lb-request-done` from the element that committed,
|
|
614
|
+
carrying the same `detail` as a bubbling `CustomEvent`, for any other
|
|
615
|
+
listener. Import its name as `LB_DONE_EVENT_NAME`.
|
|
616
|
+
|
|
591
617
|
`items` is every response item that landed because of the request, in
|
|
592
618
|
order. `refusal` is set beside `error` when the handler refused the
|
|
593
619
|
request, holding its `message` and `columns`. An answer that moved the URL contributes its `lb-url` item, which
|
|
@@ -596,11 +622,12 @@ the round trip failed, and then nothing landed. A new row's key is in the
|
|
|
596
622
|
answer only when the handler returned it in a patch: a refresh sends all
|
|
597
623
|
rows, and nothing marks which one is new.
|
|
598
624
|
|
|
599
|
-
By the time
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
625
|
+
By the time either is called, `lb-request-pending` is gone and the page is
|
|
626
|
+
as the answer left it. A request that was never sent, because the hub or an
|
|
627
|
+
ancestor stopped it, gets neither. An element the answer removed, such as
|
|
628
|
+
the row a delete took away, is outside the document by then: no ancestor it
|
|
629
|
+
had there hears the event, and no custom element the hub has removed hears
|
|
630
|
+
`lbRequestDone`.
|
|
604
631
|
|
|
605
632
|
### Holding rows
|
|
606
633
|
|
|
@@ -611,32 +638,28 @@ plain element carrying `lb-query` with a row template inside it needs no
|
|
|
611
638
|
code, so a custom element holds rows only to do something with them once
|
|
612
639
|
they land.
|
|
613
640
|
|
|
614
|
-
A custom element carrying `lb-query` and a row template
|
|
615
|
-
|
|
641
|
+
A custom element carrying `lb-query` and a row template implements
|
|
642
|
+
`lbRowsLanded`, which the hub calls once the rows have landed, with every
|
|
643
|
+
row placed and stamped:
|
|
616
644
|
|
|
617
645
|
```ts
|
|
618
|
-
import type {
|
|
646
|
+
import type { HubLifecycle } from "@loadbare/app/types";
|
|
619
647
|
import { ATTR_ROW_REQUESTED, REQUESTED_CREATED } from "@loadbare/app/constants";
|
|
620
648
|
|
|
621
|
-
class ScrollingList extends HTMLElement implements
|
|
649
|
+
class ScrollingList extends HTMLElement implements HubLifecycle {
|
|
622
650
|
lbRowsLanded() {
|
|
623
|
-
// Once, after the rows have landed, every row placed and stamped.
|
|
624
651
|
this.querySelector(`[${ATTR_ROW_REQUESTED}="${REQUESTED_CREATED}"]`)
|
|
625
652
|
?.scrollIntoView({ block: "nearest" });
|
|
626
653
|
}
|
|
627
654
|
}
|
|
628
655
|
```
|
|
629
656
|
|
|
630
|
-
| Method | The hub calls it |
|
|
631
|
-
|----------------|-------------------------------------------------------|
|
|
632
|
-
| `lbRowsLanded` | After the rows land, with every row placed and stamped |
|
|
633
|
-
|
|
634
657
|
Everything else is the hub's:
|
|
635
658
|
|
|
636
659
|
| Concern | The hub |
|
|
637
660
|
|-------------|----------------------------------------------------------|
|
|
638
661
|
| Cloning | Clones the row template once per new key |
|
|
639
|
-
| Matching | Fills the live row already showing that key
|
|
662
|
+
| Matching | Fills the live row already showing that key, when its values changed |
|
|
640
663
|
| Placing | Places every live row by the query's order |
|
|
641
664
|
| Grouping | Builds a group where the order breaks, and removes it with its last row |
|
|
642
665
|
| Removing | Marks the live rows the response says are gone as leaving, and removes them |
|
|
@@ -649,11 +672,9 @@ gives each option and `<optgroup>` what landing does not, a value and a
|
|
|
649
672
|
label, and the other scrolls to the row the page's request created or
|
|
650
673
|
moved.
|
|
651
674
|
|
|
652
|
-
A custom element
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
upgrades, the hub lands the query's last answer on it again, as all rows,
|
|
656
|
-
so `lbRowsLanded` runs.
|
|
675
|
+
A custom element under an `lb-show` that is off still holds its rows. The
|
|
676
|
+
hub places the rows that land on it then as it places any, and calls its
|
|
677
|
+
`lbRowsLanded`, so it returns current.
|
|
657
678
|
|
|
658
679
|
A custom element that walks its own rows finds them with `LIVE_ROW` from
|
|
659
680
|
`@loadbare/app/constants`, never by `lb-key-value`: an element a `row` lands
|
|
@@ -172,6 +172,11 @@ membership: a live row whose key did not arrive leaves. A patch changes only
|
|
|
172
172
|
the rows it names, and every other live row keeps its content. The hub
|
|
173
173
|
places every live row by the query's order; see [Order](#order).
|
|
174
174
|
|
|
175
|
+
A live row whose values arrive as it already shows them is not filled
|
|
176
|
+
again. A control in it that the user has typed into and not committed keeps
|
|
177
|
+
what was typed, through a refresh and through a change of order. A row
|
|
178
|
+
whose values changed is filled whole, and its controls show what arrived.
|
|
179
|
+
|
|
175
180
|
A key is unique within a query. Two rows with one key in the same answer,
|
|
176
181
|
or two live rows showing one key, are reported on the console.
|
|
177
182
|
|
|
@@ -284,10 +289,9 @@ scaffolding around rows, such as a group's heading or a ghost row. So
|
|
|
284
289
|
a query nested in another query's rows need not land again, or land after
|
|
285
290
|
the outer query, for a new outer row to show its choices.
|
|
286
291
|
|
|
287
|
-
A custom element
|
|
288
|
-
`
|
|
289
|
-
|
|
290
|
-
runs. See [Holding rows](./custom-elements.md#holding-rows).
|
|
292
|
+
A custom element under an `lb-show` that is off is filled like any other,
|
|
293
|
+
and its `lbRowsLanded` runs as its rows land. See
|
|
294
|
+
[Holding rows](./custom-elements.md#holding-rows).
|
|
291
295
|
|
|
292
296
|
Nothing is answered from what the hub kept: a request always goes to the
|
|
293
297
|
server, and a query re-runs only when a response names it. A patch that
|
|
@@ -877,9 +881,10 @@ An ancestor may stop the event, and the request is not sent. A custom
|
|
|
877
881
|
element may dispatch the event itself; see
|
|
878
882
|
[Sending a request](./custom-elements.md#sending-a-request).
|
|
879
883
|
|
|
880
|
-
Once the answer has landed, or the round trip has failed, the hub
|
|
881
|
-
|
|
882
|
-
|
|
884
|
+
Once the answer has landed, or the round trip has failed, the hub calls
|
|
885
|
+
`lbRequestDone` on the custom elements from the committing element outward,
|
|
886
|
+
then dispatches a bubbling `lb-request-done` event from the same element.
|
|
887
|
+
Both carry the request and what landed because of it, or the error; see
|
|
883
888
|
[Hearing how it turned out](./custom-elements.md#hearing-how-it-turned-out).
|
|
884
889
|
|
|
885
890
|
## The URL
|
|
@@ -182,8 +182,8 @@ the hub until the user says yes:
|
|
|
182
182
|
| `exp-request` | The confirm button's `lb-request` |
|
|
183
183
|
| `exp-confirm` | The confirm button's text, `Confirm` when absent |
|
|
184
184
|
|
|
185
|
-
The widget closes the dialog once
|
|
186
|
-
|
|
185
|
+
The widget closes the dialog once the request succeeds, and leaves it open
|
|
186
|
+
on a refusal.
|
|
187
187
|
|
|
188
188
|
## `lb-form`
|
|
189
189
|
|