@loadbare/app 0.9.0 → 0.10.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.
Files changed (80) hide show
  1. package/README.md +3 -3
  2. package/dist/build/assemble.d.ts.map +1 -1
  3. package/dist/build/assemble.js +74 -66
  4. package/dist/build/assemble.js.map +1 -1
  5. package/dist/build/expand.d.ts.map +1 -1
  6. package/dist/build/expand.js +20 -19
  7. package/dist/build/expand.js.map +1 -1
  8. package/dist/build/locations.d.ts +2 -3
  9. package/dist/build/locations.d.ts.map +1 -1
  10. package/dist/build/locations.js +2 -3
  11. package/dist/build/locations.js.map +1 -1
  12. package/dist/build/pages.d.ts +3 -4
  13. package/dist/build/pages.d.ts.map +1 -1
  14. package/dist/build/pages.js +3 -4
  15. package/dist/build/pages.js.map +1 -1
  16. package/dist/core/lb-constants.d.ts +25 -24
  17. package/dist/core/lb-constants.d.ts.map +1 -1
  18. package/dist/core/lb-constants.js +95 -168
  19. package/dist/core/lb-constants.js.map +1 -1
  20. package/dist/core/lb-types.d.ts +64 -77
  21. package/dist/core/lb-types.d.ts.map +1 -1
  22. package/dist/core/lb-types.js +40 -7
  23. package/dist/core/lb-types.js.map +1 -1
  24. package/dist/hub/lb-apply.d.ts +47 -37
  25. package/dist/hub/lb-apply.d.ts.map +1 -1
  26. package/dist/hub/lb-apply.js +174 -193
  27. package/dist/hub/lb-apply.js.map +1 -1
  28. package/dist/hub/lb-hub.browser.d.ts +1 -1
  29. package/dist/hub/lb-hub.browser.d.ts.map +1 -1
  30. package/dist/hub/lb-hub.browser.js +411 -449
  31. package/dist/hub/lb-hub.browser.js.map +1 -1
  32. package/dist/server/lb-express.d.ts +5 -5
  33. package/dist/server/lb-express.d.ts.map +1 -1
  34. package/dist/server/lb-express.js +35 -66
  35. package/dist/server/lb-express.js.map +1 -1
  36. package/dist/server/lb-server.d.ts +77 -135
  37. package/dist/server/lb-server.d.ts.map +1 -1
  38. package/dist/server/lb-server.js +132 -79
  39. package/dist/server/lb-server.js.map +1 -1
  40. package/docs/TECHREF-1.0.md +861 -587
  41. package/docs/comparison.md +222 -185
  42. package/docs/prior-art.md +15 -14
  43. package/docs/reference/builder.md +9 -3
  44. package/docs/reference/chrome.md +107 -56
  45. package/docs/reference/custom-elements.md +199 -173
  46. package/docs/reference/data-binding.md +374 -374
  47. package/docs/reference/overview.md +12 -10
  48. package/docs/reference/page-files.md +135 -99
  49. package/docs/reference/server.md +2 -2
  50. package/docs/reference/widgets.md +104 -110
  51. package/docs/roadmap.md +32 -39
  52. package/docs/terms-of-art.md +57 -0
  53. package/docs/testing.md +97 -68
  54. package/docs/theory.md +92 -58
  55. package/docs/tutorials/010-pages-and-navigation.md +20 -12
  56. package/docs/tutorials/020-css.md +6 -3
  57. package/docs/tutorials/030-html-decomposition.md +9 -7
  58. package/docs/tutorials/040-displaying-data.md +30 -13
  59. package/docs/tutorials/{050-actions.md → 050-requests.md} +25 -15
  60. package/docs/tutorials/060-custom-element-code.md +17 -16
  61. package/docs/tutorials/065-conditional-rendering.md +34 -23
  62. package/docs/tutorials/070-displaying-a-list.md +29 -21
  63. package/docs/tutorials/072-inserting-into-a-list.md +24 -16
  64. package/docs/tutorials/074-deleting-from-a-list.md +9 -7
  65. package/docs/tutorials/076-updating-a-list-item.md +11 -10
  66. package/docs/tutorials/080-widget-requests.md +71 -43
  67. package/docs/tutorials/090-using-widget-libraries.md +22 -22
  68. package/package.json +1 -1
  69. package/skills/loadbare-app/SKILL.md +178 -122
  70. package/skills/loadbare-app/references/TECHREF-1.0.md +861 -587
  71. package/skills/loadbare-app/references/builder.md +9 -3
  72. package/skills/loadbare-app/references/chrome.md +107 -56
  73. package/skills/loadbare-app/references/custom-elements.md +199 -173
  74. package/skills/loadbare-app/references/data-binding.md +374 -374
  75. package/skills/loadbare-app/references/overview.md +12 -10
  76. package/skills/loadbare-app/references/page-files.md +135 -99
  77. package/skills/loadbare-app/references/server.md +2 -2
  78. package/skills/loadbare-app/references/widgets.md +104 -110
  79. package/docs/analysis-accidental-complexity.md +0 -149
  80. package/docs/analysis-closed-set.md +0 -210
@@ -1,17 +1,41 @@
1
- # Widget Requests
1
+ # Committing a Control
2
2
 
3
- Our list example showed the use of forms and submit. The inputs
4
- were passive in the sense that they did not trigger any change on their
5
- own.
3
+ Our list example saved a note with a form and a Save button. A control can
4
+ also commit itself: an `<input>`, `<select>` or `<textarea>` carrying
5
+ `lb-request` commits on `change`, and sends its own value alone.
6
6
 
7
- Now we will see how to make a widget that fires events when its value
8
- changes.
7
+ Then we will write a custom element that works as a control, so it commits
8
+ the same way.
9
9
 
10
- ## Writing the widget
10
+ ## Committing an input
11
11
 
12
- Our new custom input will no longer rely on Loadbare's form handling. It
13
- says what happened and what its value is. Where it sits, the list, the row
14
- and the cell, is added by the hub.
12
+ ```html
13
+ <!-- src/pages/about.page.html -->
14
+ <ul lb-query="notes">
15
+ <template>
16
+ <li>
17
+ <input lb-column="text" lb-request="lb-row-update" />
18
+ <button lb-request="lb-row-delete">Delete</button>
19
+ </li>
20
+ </template>
21
+ </ul>
22
+ ```
23
+
24
+ The form and the Save button are gone. The input carries `lb-column`, so
25
+ the hub gathers its value alone, as `values` with one member, `text`. It
26
+ takes `key` from the live row the input is in. The request is the same
27
+ `lb-row-update` the form sent in
28
+ [Updating a List Item](./076-updating-a-list-item.md), so the `rowUpdate`
29
+ written there answers it unchanged. A `rowUpdate` sets the columns
30
+ `values` names and leaves the rest alone, as an SQL `UPDATE` does, so one
31
+ handler serves a form and a single control alike.
32
+
33
+ ## Writing a custom control
34
+
35
+ A custom element is a control when it is form-associated, has a `value`
36
+ property, and fires `change`. The hub then treats it exactly as it treats
37
+ an `<input>`: it sets its `value` when a row lands, gathers its `value`
38
+ when a request is issued, and commits it on `change`.
15
39
 
16
40
  ```html
17
41
  <!-- src/note-input.html -->
@@ -20,63 +44,67 @@ and the cell, is added by the hub.
20
44
 
21
45
  ```ts
22
46
  // src/note-input.browser.ts
23
- import { ATTR_VALUE, LB_EVENT_NAME } from "@loadbare/app/constants";
47
+ import { ATTR_COLUMN_VALUE } from "@loadbare/app/constants";
24
48
 
25
49
  class NoteInput extends HTMLElement {
26
- static observedAttributes = [ATTR_VALUE];
50
+ static formAssociated = true;
51
+ static observedAttributes = [ATTR_COLUMN_VALUE];
52
+
53
+ constructor() {
54
+ super();
55
+ this.addEventListener("change", (e) => {
56
+ if (e.target === this) return;
57
+ e.stopPropagation();
58
+ this.dispatchEvent(new Event("change", { bubbles: true }));
59
+ });
60
+ }
27
61
 
28
- attributeChangedCallback(_name: string, _old: string, value: string) {
62
+ get value(): string {
63
+ return this.querySelector("input")?.value ?? "";
64
+ }
65
+
66
+ set value(value: string) {
29
67
  const input = this.querySelector("input");
30
68
  if (input) input.value = value;
31
69
  }
32
70
 
33
- connectedCallback() {
34
- this.addEventListener("change", () => {
35
- const input = this.querySelector("input");
36
- if (!input) return;
37
- this.dispatchEvent(
38
- new CustomEvent(LB_EVENT_NAME, {
39
- bubbles: true,
40
- detail: { action: "lb-row-update", value: input.value },
41
- }),
42
- );
43
- });
71
+ attributeChangedCallback(_name: string, _old: string, value: string) {
72
+ this.value = value ?? "";
44
73
  }
45
74
  }
46
75
 
47
76
  customElements.define("note-input", NoteInput);
48
77
  ```
49
78
 
50
- A widget with both a `.html` and a `.browser.ts` file shares one tag name; the
51
- build finds each half independently. On change, it dispatches a
52
- `lb-row-update` carrying the input's value. The hub adds the list and the key
53
- of the row it is in, and turns the value into a `values` map holding only
54
- the widget's own `lb-cell`.
79
+ A custom element with both a `.html` and a `.browser.ts` file shares one
80
+ tag name; the build finds each half independently.
81
+
82
+ `static formAssociated = true` makes the element a form-associated custom
83
+ element, so a form it sits in is its form owner, and the form gathers it.
84
+ The inner `<input>`'s own `change` is stopped at the element, which fires
85
+ `change` from itself, so the element carrying `lb-request` is the one that
86
+ commits.
87
+
88
+ The hub stamps `lb-column-value` with every value it lands. Rendering from
89
+ that stamp covers a row the hub fills before the element is upgraded, when
90
+ the element is not yet a control and receives the stamp alone.
55
91
 
56
92
  ## Using it
57
93
 
58
94
  ```html
59
95
  <!-- src/pages/about.page.html -->
60
- <ul lb-list="notes">
61
- <template lb-key="id">
96
+ <ul lb-query="notes">
97
+ <template>
62
98
  <li>
63
- <note-input lb-cell="text"></note-input>
64
- <button lb-action="lb-row-delete">Delete</button>
99
+ <note-input lb-column="text" lb-request="lb-row-update"></note-input>
100
+ <button lb-request="lb-row-delete">Delete</button>
65
101
  </li>
66
102
  </template>
67
103
  </ul>
68
104
  ```
69
105
 
70
- The `lb-row-update` form and Save button are gone — `note-input` commits on
71
- every change, so there's nothing left to batch.
72
-
73
- ## Answering it server-side
74
-
75
- There is nothing to add. The request is the same `lb-row-update` the form
76
- sent in [Updating a List Item](./076-updating-a-list-item.md), with `values`
77
- holding only `text`, so the `rowUpdate` written there answers it unchanged.
78
- A `rowUpdate` sets the columns `values` names and leaves the rest alone, as
79
- an SQL `UPDATE` does, so one handler serves a form and a widget alike.
106
+ Inside a form, leave `lb-request` off the control. The form gathers it on
107
+ submit along with every other control it owns.
80
108
 
81
109
  ## Run it
82
110
 
@@ -1,12 +1,11 @@
1
1
  # Using Widget Libraries
2
2
 
3
- [Displaying a List](./070-displaying-a-list.md) already installed one widget
4
- library, `@loadbare/widgets`. This tutorial covers what that step actually
5
- did, and why it is the same step for a library from anywhere else.
3
+ This tutorial installs one widget library, `@loadbare/widgets`, and covers
4
+ why installing a library from anywhere else is the same step.
6
5
 
7
6
  [Custom Element Code](./060-custom-element-code.md) and
8
- [Widget Requests](./080-widget-requests.md) wrote widgets by hand, one
9
- file per tag, discovered because the tag turned up in a page. A widget
7
+ [Committing a Control](./080-widget-requests.md) wrote custom elements by
8
+ hand, one file per tag, discovered because the tag turned up in a page. A widget
10
9
  installed from a package works the same way once the package is listed —
11
10
  listing the package is the only new piece.
12
11
 
@@ -41,57 +40,58 @@ package says where to look; it does not import anything on its own.
41
40
  ## Using a tag
42
41
 
43
42
  Once the package is listed, a tag from the library is used exactly like a
44
- widget written by hand — the query scope and cell attributes work the same
45
- regardless of where the script came from:
43
+ custom element written by hand — `lb-query`, `lb-column` and `lb-request`
44
+ work the same regardless of where the script came from:
46
45
 
47
46
  ```html
48
47
  <!-- src/pages/index.page.html -->
49
- <div lb-row="status">
50
- <lb-select lb-cell="state">
48
+ <div lb-query="status">
49
+ <lb-select lb-column="state" lb-request="lb-row-update" exp-label="State">
51
50
  <option value="open">Open</option>
52
51
  <option value="closed">Closed</option>
53
52
  </lb-select>
54
53
  </div>
55
54
  ```
56
55
 
57
- `lb-select` follows the `lb-value` contract
58
- [Custom Element Code](./060-custom-element-code.md) described: the hub
59
- writes the query result to `lb-value`, and the widget's own class —
60
- imported from `@loadbare/widgets`, not written in this
61
- application — reacts to it.
56
+ `lb-select` is a form-associated control, like the `note-input`
57
+ [Committing a Control](./080-widget-requests.md) wrote: the hub sets its
58
+ `value` from the row, and it commits `lb-row-update` on `change`. Its
59
+ class is imported from `@loadbare/widgets`, not written in this
60
+ application. `exp-label` fills the widget's `<label>` at build time.
62
61
 
63
62
  ## The unknown-page dialog, as a widget
64
63
 
65
64
  [Pages and Navigation](./010-pages-and-navigation.md) wrote a
66
- `<dialog lb-unknown-page>` by hand. The library ships the same dialog as a
65
+ `<dialog lb-url-unknown>` by hand. The library ships the same dialog as a
67
66
  widget, so a chrome that lists the package can replace the dialog with one
68
67
  tag:
69
68
 
70
69
  ```html
71
70
  <lb-hub>
72
71
  <nav>
73
- <a href="/" lb-nav-link>Home</a>
74
- <a href="/about" lb-nav-link>About</a>
72
+ <a href="/" lb-url-link>Home</a>
73
+ <a href="/about" lb-url-link>About</a>
75
74
  </nav>
76
75
  <main></main>
77
76
  <lb-unknown-page></lb-unknown-page>
78
77
  </lb-hub>
79
78
  ```
80
79
 
81
- Its definition is the dialog, already scoped to the hub's `lb-navigation`
82
- query and carrying both of its cells. Nothing else changes: the hub still
83
- finds a `<dialog lb-unknown-page>` inside itself and opens it on a miss.
80
+ Its definition is the dialog, a `<dialog lb-url-unknown lb-query="lb-url">`
81
+ showing the `lb-path` column of the hub's own `lb-url` query. Nothing else
82
+ changes: the hub still finds a `<dialog lb-url-unknown>` inside itself and
83
+ opens it on a miss.
84
84
 
85
85
  ## Where this stops
86
86
 
87
87
  This only covers consuming a published widget, not writing one for
88
88
  publication — that's the same class shape
89
89
  [Custom Element Code](./060-custom-element-code.md) and
90
- [Widget Requests](./080-widget-requests.md) already wrote, packaged and
90
+ [Committing a Control](./080-widget-requests.md) already wrote, packaged and
91
91
  given an import specifier instead of living in an application's `src/`.
92
92
  It doesn't cover `lb-table`'s footer destination or `lb-picker`'s
93
93
  expansion parameters, which are in
94
94
  [The Basic Widget Library](../reference/widgets.md).
95
95
 
96
96
  ---
97
- Prev: [Widget Requests](./080-widget-requests.md)
97
+ Prev: [Committing a Control](./080-widget-requests.md)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loadbare/app",
3
3
  "description": "High performance web app framework for server-bound applications",
4
- "version": "0.9.0",
4
+ "version": "0.10.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",