@loadbare/app 0.7.4 → 0.8.1
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/skills-cli.d.ts +12 -0
- package/dist/build/skills-cli.d.ts.map +1 -0
- package/dist/build/skills-cli.js +81 -0
- package/dist/build/skills-cli.js.map +1 -0
- package/dist/build/skills.d.ts +47 -0
- package/dist/build/skills.d.ts.map +1 -0
- package/dist/build/skills.js +124 -0
- package/dist/build/skills.js.map +1 -0
- package/dist/core/lb-constants.d.ts +1 -2
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +13 -12
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +4 -10
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +47 -24
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +2 -7
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +8 -15
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +0 -3
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +21 -13
- package/docs/analysis-closed-set.md +16 -9
- package/docs/comparison.md +7 -6
- package/docs/reference/custom-elements.md +11 -6
- package/docs/reference/data-binding.md +36 -12
- package/docs/reference/page-files.md +13 -9
- package/docs/reference/widgets.md +4 -4
- package/docs/roadmap.md +1 -1
- package/docs/testing.md +5 -1
- package/docs/theory.md +1 -1
- package/docs/tutorials/080-widget-requests.md +9 -28
- package/package.json +8 -4
- package/skills/loadbare-app/SKILL.md +258 -0
- package/skills/loadbare-app/references/TECHREF-1.0.md +1189 -0
- package/skills/loadbare-app/references/builder.md +134 -0
- package/skills/loadbare-app/references/chrome.md +158 -0
- package/skills/loadbare-app/references/css.md +44 -0
- package/skills/loadbare-app/references/custom-elements.md +397 -0
- package/skills/loadbare-app/references/data-binding.md +457 -0
- package/skills/loadbare-app/references/overview.md +38 -0
- package/skills/loadbare-app/references/page-files.md +194 -0
- package/skills/loadbare-app/references/server.md +142 -0
- package/skills/loadbare-app/references/widgets.md +174 -0
package/docs/TECHREF-1.0.md
CHANGED
|
@@ -529,8 +529,7 @@ name, the same test that decides how a value lands — see
|
|
|
529
529
|
| -------------- | ------------------------------------------------- |
|
|
530
530
|
| lb-row-insert | a `<form>`, or a button in a `<tr>`, in a list |
|
|
531
531
|
| lb-row-delete | anything inside a live row |
|
|
532
|
-
| lb-row-update | a `<form>`,
|
|
533
|
-
| lb-cell-change | a widget wrapping one control |
|
|
532
|
+
| lb-row-update | a `<form>`, a button in a live row, or a widget cell |
|
|
534
533
|
| anything else | must be a named routine in the page's server code |
|
|
535
534
|
|
|
536
535
|
The wire format is not visible to the user, but uses the same lb-*
|
|
@@ -545,7 +544,6 @@ carries.
|
|
|
545
544
|
| `action` | Filled from scope | Required |
|
|
546
545
|
| ---------------- | ------------------------------ | ---------------------- |
|
|
547
546
|
| a declared name | `list` or `row`, `key`, `cell` | nothing |
|
|
548
|
-
| `lb-cell-change` | `list`, `key`, `cell` | all three, and `value` |
|
|
549
547
|
| `lb-row-insert` | `list` | `list`, and `values` |
|
|
550
548
|
| `lb-row-delete` | `list`, `key` | both |
|
|
551
549
|
| `lb-row-update` | `list`, `key` | both, and `values` |
|
|
@@ -556,7 +554,13 @@ way a control belongs to the form around it. `list` or `row` comes from the
|
|
|
556
554
|
nearest ancestor scope, `key` from the nearest live row inside that scope,
|
|
557
555
|
and `cell` from the dispatching element's own `lb-cell`.
|
|
558
556
|
A request missing a required field is not sent. The hub never fills
|
|
559
|
-
`value`. An `lb-row-insert` or `lb-row-update`
|
|
557
|
+
`value`. An `lb-row-insert` or `lb-row-update` from an element carrying
|
|
558
|
+
`lb-cell` is a record of one cell, the way a control has a value and a form
|
|
559
|
+
has values: `values` holds that cell alone, taken from the `value` the widget
|
|
560
|
+
sent or else read from the control it is or wraps, and `value` is not sent
|
|
561
|
+
beside it. A widget that sends a `value` from an element carrying no
|
|
562
|
+
`lb-cell` is refused, since nothing names the column. Any other
|
|
563
|
+
`lb-row-insert` or `lb-row-update` gathers the row it belongs
|
|
560
564
|
to: `values` holds every `lb-cell` with a control to read in the nearest
|
|
561
565
|
`<form>`, `<tr>` or live row around the dispatching element, itself
|
|
562
566
|
included, inside its scope. The cells are found the way a row lands, so a
|
|
@@ -569,10 +573,11 @@ own form; a live row counts because it is the row the key names. The scope
|
|
|
569
573
|
itself is never the row, since its cells belong to other rows. A request
|
|
570
574
|
from an element in no form or row is not sent, and the hub reports that its
|
|
571
575
|
cells belong in a `<form>`. A request that already carries `values` keeps
|
|
572
|
-
them, and one whose row has no cell to read is not sent. A click
|
|
573
|
-
native element that carries either operation and
|
|
574
|
-
holds cells
|
|
575
|
-
would send the row: put the action on a form or on a
|
|
576
|
+
them, and one whose row has no cell to read is not sent. A click on a
|
|
577
|
+
native element that carries either operation and is a cell or
|
|
578
|
+
holds cells is not sent, since clicking into one of its controls
|
|
579
|
+
would send the row: put the action on a form, on a button, or on a widget
|
|
580
|
+
that decides when its cell has changed.
|
|
576
581
|
|
|
577
582
|
A widget dispatches the action and, where it wraps a control, that control's
|
|
578
583
|
value.
|
|
@@ -581,7 +586,7 @@ value.
|
|
|
581
586
|
{ action: "lb-row-insert", list: "rosterList", values: {...} }
|
|
582
587
|
{ action: "lb-row-delete", list: "rosterList", key: "42" }
|
|
583
588
|
{ action: "lb-row-update", list: "rosterList", key: "42", values: {...} }
|
|
584
|
-
{ action: "lb-
|
|
589
|
+
{ action: "lb-row-update", list: "rosterList", key: "42", values: { name: "Ann" } }
|
|
585
590
|
{ action: "selectTab", row: "prefs", cell: "active_tab", value: "two" }
|
|
586
591
|
```
|
|
587
592
|
|
|
@@ -912,7 +917,7 @@ It has three optional keys.
|
|
|
912
917
|
| Key | Keyed by | Answers |
|
|
913
918
|
| ------------- | --------------------- | -------------------------------------------------- |
|
|
914
919
|
| `actions` | The `lb-action` value | Anything the page chooses to declare |
|
|
915
|
-
| `crud` | A query name | The
|
|
920
|
+
| `crud` | A query name | The three reserved `lb-action` values |
|
|
916
921
|
| `onPageEnter` | Nothing | Runs once on entering the page, before its queries |
|
|
917
922
|
|
|
918
923
|
|
|
@@ -963,16 +968,19 @@ export const requests: Requests = {
|
|
|
963
968
|
|
|
964
969
|
Each key under a `crud` entry is a reserved `lb-action` value with its prefix
|
|
965
970
|
stripped and the rest camel-cased, so the attribute, the wire and this key
|
|
966
|
-
are one vocabulary. All
|
|
971
|
+
are one vocabulary. All three operate on a list, because each needs a key and
|
|
967
972
|
a key exists only on a live row.
|
|
968
973
|
|
|
969
974
|
| `lb-action` | Key under `crud` | `where` carries |
|
|
970
975
|
| ---------------- | ---------------- | ---------------------- |
|
|
971
|
-
| `lb-cell-change` | `cellChange` | `key`, `cell`, `value` |
|
|
972
976
|
| `lb-row-delete` | `rowDelete` | `key` |
|
|
973
977
|
| `lb-row-insert` | `rowInsert` | `values` |
|
|
974
978
|
| `lb-row-update` | `rowUpdate` | `key`, `values` |
|
|
975
979
|
|
|
980
|
+
A `rowUpdate` sets the columns `values` names and leaves the rest as they
|
|
981
|
+
are, as an SQL `UPDATE` does. A form sends the cells it holds and a widget
|
|
982
|
+
cell sends itself, so one handler answers both.
|
|
983
|
+
|
|
976
984
|
## Widgets
|
|
977
985
|
|
|
978
986
|
---- UNEDITED ----
|
|
@@ -1124,7 +1132,7 @@ application writes the ones this table names and invents none of its own,
|
|
|
1124
1132
|
because a name Loadbare has not defined today it may define tomorrow.
|
|
1125
1133
|
|
|
1126
1134
|
The prefix reaches past HTML. A query name cannot begin with `lb-` either,
|
|
1127
|
-
which is what keeps the
|
|
1135
|
+
which is what keeps the three operations apart from an application's own
|
|
1128
1136
|
actions on the wire — see [Page Queries](#page-queries).
|
|
1129
1137
|
|
|
1130
1138
|
Each attribute is defined in one section, and this table says which.
|
|
@@ -71,17 +71,23 @@ closed.
|
|
|
71
71
|
| Operation | Takes from position | Carries | Answers |
|
|
72
72
|
| ---------------- | ------------------- | -------------------------------------------- | ------------ |
|
|
73
73
|
| `lb-row-insert` | list | values, gathered from the record | patch rows |
|
|
74
|
-
| `lb-row-update` | list, key | values, gathered or
|
|
74
|
+
| `lb-row-update` | list, key | values, gathered, or one cell from a widget | patch rows |
|
|
75
75
|
| `lb-row-delete` | list, key | nothing | patch drop |
|
|
76
76
|
| a declared name | list or row, key, cell | value | any names |
|
|
77
77
|
|
|
78
|
-
###
|
|
78
|
+
### Done: `lb-cell-change` folded into `lb-row-update`
|
|
79
79
|
|
|
80
|
-
A cell change is an update whose `values` holds one entry
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
A cell change is an update whose `values` holds one entry. SQL has one
|
|
81
|
+
UPDATE whether it sets one column or many. On the server, `cellChange` and
|
|
82
|
+
`rowUpdate` merged into `rowUpdate(key, values)`, where a column absent from
|
|
83
|
+
`values` is left as it is.
|
|
84
|
+
|
|
85
|
+
The fold needed one rule beyond this proposal. Without it, a widget sending
|
|
86
|
+
`lb-row-update` gathers its whole record, and every other editable cell in
|
|
87
|
+
the row goes with it. The rule: an element carrying `lb-cell` is a record
|
|
88
|
+
of one cell, the way a control has a value and a form has values. Its
|
|
89
|
+
`values` holds that cell alone, from the `value` the widget sent or else its
|
|
90
|
+
control, so a widget never writes its own column name into the request.
|
|
85
91
|
|
|
86
92
|
### Reordering is not an operation
|
|
87
93
|
|
|
@@ -177,8 +183,9 @@ overwrites that in 0.7.3, so the rule introduces nothing new.
|
|
|
177
183
|
|
|
178
184
|
1. The hub holds each name's current value and fills scopes that appear
|
|
179
185
|
late.
|
|
180
|
-
2. `lb-cell-change` folds into `lb-row-update`, with
|
|
181
|
-
`
|
|
186
|
+
2. `lb-cell-change` folds into `lb-row-update`, with an element carrying
|
|
187
|
+
`lb-cell` sending itself alone, and the server's `cellChange` and
|
|
188
|
+
`rowUpdate` merge. Done.
|
|
182
189
|
3. The reference states the patch row rule: upsert by key, unnamed columns
|
|
183
190
|
unchanged.
|
|
184
191
|
|
package/docs/comparison.md
CHANGED
|
@@ -411,25 +411,26 @@ Data types are an open blocker in TECHREF-1.0.
|
|
|
411
411
|
### Loadbare/app
|
|
412
412
|
|
|
413
413
|
`lb-action` names what an interaction asks for. A value beginning with `lb-`
|
|
414
|
-
is one of
|
|
414
|
+
is one of three reserved operations; any other value is an action the page
|
|
415
415
|
declares.
|
|
416
416
|
|
|
417
417
|
| `lb-action` | Written on | Carries | Server key under `crud` |
|
|
418
418
|
|------------------|---------------------------------------------|---------------------------------|-------------------------|
|
|
419
419
|
| `lb-row-insert` | A `<form>`, or a button in a `<tr>`, in a list | `list`, `values` | `rowInsert` |
|
|
420
|
-
| `lb-row-update` | A `<form
|
|
420
|
+
| `lb-row-update` | A `<form>`, a button in a live row, or a widget cell | `list`, `key`, `values` | `rowUpdate` |
|
|
421
421
|
| `lb-row-delete` | Anything inside a live row | `list`, `key` | `rowDelete` |
|
|
422
|
-
| `lb-cell-change` | A widget wrapping one control | `list`, `key`, `cell`, `value` | `cellChange` |
|
|
423
422
|
| Any other name | Any element | Scope in effect, and a widget's `value` | Under `actions` |
|
|
424
423
|
|
|
425
424
|
- Position comes from the document. `list` or `row` comes from the nearest
|
|
426
425
|
ancestor scope, `key` from the nearest live row, `cell` from the element's
|
|
427
426
|
own `lb-cell`. The author writes the action and not the position.
|
|
428
427
|
- Values are gathered from the nearest `<form>`, `<tr>` or live row around
|
|
429
|
-
the element, the way a button submits its form owner.
|
|
428
|
+
the element, the way a button submits its form owner. A widget carrying
|
|
429
|
+
`lb-cell` sends its own cell alone, so one `rowUpdate` answers a form and a
|
|
430
|
+
per-field edit.
|
|
430
431
|
- A native element sends on click, a form on submit. A widget sends its own.
|
|
431
432
|
- A declared action carries no argument list.
|
|
432
|
-
- A single-row scope is read-only for the
|
|
433
|
+
- A single-row scope is read-only for the three operations, because each needs
|
|
433
434
|
a key and a key exists only on a live row in a list.
|
|
434
435
|
|
|
435
436
|
On the server, each entry has `run` and `refresh`. `run` does the work and
|
|
@@ -728,7 +729,7 @@ TECHREF-1.0 lists every name Loadbare/app owns in one cross-reference.
|
|
|
728
729
|
| Owned | Count | Names |
|
|
729
730
|
|-------------------------------------|-------|---------------------------------------------------------------|
|
|
730
731
|
| `lb-*` HTML attributes | 16 | `lb-list`, `lb-row`, `lb-cell`, `lb-show`, `lb-key`, `lb-key-value`, `lb-value`, `lb-action`, `lb-nav-link`, `lb-pending`, `lb-error`, `lb-row-count`, `lb-unknown-page`, `lb-slot`, `lb-template`, `lb-page` |
|
|
731
|
-
| Reserved `lb-action` values |
|
|
732
|
+
| Reserved `lb-action` values | 3 | `lb-row-insert`, `lb-row-update`, `lb-row-delete` |
|
|
732
733
|
| `lb*` methods on custom elements | 2 | `lbPlaceRow`, `lbRowsLanded` |
|
|
733
734
|
| Attribute namespace for expansion | 1 | `exp-*` |
|
|
734
735
|
| Reserved tags | 1 | `<lb-hub>` |
|
|
@@ -229,8 +229,8 @@ as a string literal.
|
|
|
229
229
|
| `ATTR_KEY` | `lb-key` |
|
|
230
230
|
| `ATTR_KEY_VALUE` | `lb-key-value` |
|
|
231
231
|
| `ATTR_ACTION` | `lb-action`|
|
|
232
|
-
| `ACTION_ROW_INSERT`, `ACTION_ROW_DELETE`, `ACTION_ROW_UPDATE
|
|
233
|
-
| `LB_ACTIONS` | all
|
|
232
|
+
| `ACTION_ROW_INSERT`, `ACTION_ROW_DELETE`, `ACTION_ROW_UPDATE` | the reserved `lb-action` values |
|
|
233
|
+
| `LB_ACTIONS` | all three of them, in one array |
|
|
234
234
|
| `LB_RESERVED_PREFIX` | `lb-`, the prefix every reserved name begins with |
|
|
235
235
|
| `ATTR_ROW_COUNT` | `lb-row-count`|
|
|
236
236
|
| `LB_EVENT_NAME` | `lb-request` |
|
|
@@ -287,7 +287,7 @@ control's value as its `detail`:
|
|
|
287
287
|
import { LB_EVENT_NAME } from "@loadbare/app/constants";
|
|
288
288
|
import type { HubRequest } from "@loadbare/app/types";
|
|
289
289
|
|
|
290
|
-
const detail: HubRequest = { action: "lb-
|
|
290
|
+
const detail: HubRequest = { action: "lb-row-update", value: input.value };
|
|
291
291
|
this.dispatchEvent(new CustomEvent(LB_EVENT_NAME, { bubbles: true, detail }));
|
|
292
292
|
```
|
|
293
293
|
|
|
@@ -296,9 +296,14 @@ event, and does not send a request missing a field its operation requires.
|
|
|
296
296
|
See [TECHREF-1.0](../TECHREF-1.0.md#requests) for what each operation is
|
|
297
297
|
filled with.
|
|
298
298
|
|
|
299
|
-
A widget
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
A widget that carries `lb-cell` and sends `lb-row-insert` or `lb-row-update`
|
|
300
|
+
sends that one cell. The hub builds `values` from the cell's name and the
|
|
301
|
+
`value` the widget sent, or reads the control the widget wraps when it sent
|
|
302
|
+
none.
|
|
303
|
+
|
|
304
|
+
A widget that carries no `lb-cell` doesn't read its own controls. It
|
|
305
|
+
dispatches the bare action from the row, or from anything inside it, and the
|
|
306
|
+
hub gathers `values` from the row the event came from:
|
|
302
307
|
the nearest `<form>`, `<tr>` or live row around the dispatching element,
|
|
303
308
|
itself included, inside its scope. Every readable `lb-cell` in that row is
|
|
304
309
|
gathered, wherever in the row it sits, except the cells of a scope nested in
|
|
@@ -152,9 +152,9 @@ the prefix stripped and the rest camel-cased.
|
|
|
152
152
|
| `lb-action="lb-row-delete"` | `rowDelete` | `list`, `key` |
|
|
153
153
|
| `lb-action="lb-row-insert"` on a `<form>` | `rowInsert` | `list`, `values` |
|
|
154
154
|
| `lb-action="lb-row-update"` on a `<form>` | `rowUpdate` | `list`, `key`, `values` |
|
|
155
|
-
| `lb-action="lb-
|
|
155
|
+
| `lb-action="lb-row-update"` on a widget cell | `rowUpdate` | `list`, `key`, `values` of one cell |
|
|
156
156
|
|
|
157
|
-
All
|
|
157
|
+
All three operations are list operations. Each needs a key, and a key exists
|
|
158
158
|
only on a live row the hub stamped inside a list, so a single-row scope is
|
|
159
159
|
read-only and a declared action is the only thing it can send. An application
|
|
160
160
|
that wants a writable single row declares a list that answers with one row.
|
|
@@ -166,15 +166,11 @@ with one an application already uses. That reservation is also the whole of
|
|
|
166
166
|
the wire discriminant: a value beginning with `lb-` is an operation, and
|
|
167
167
|
anything else is a name the page declared.
|
|
168
168
|
|
|
169
|
-
The hub sends
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
cell
|
|
173
|
-
|
|
174
|
-
`<lb-input>` does when it carries `lb-action="lb-cell-change"`, and stays
|
|
175
|
-
quiet otherwise — an input inside an `lb-row-insert` or `lb-row-update` form is read
|
|
176
|
-
again by the form on submit, so a widget that sent on its own would write
|
|
177
|
-
the same edit twice.
|
|
169
|
+
The hub sends a request from a native element on the element's own event: a
|
|
170
|
+
form on submit, anything else on click. An insert or update clicked from a
|
|
171
|
+
button reads the form or row the button is in (see [Forms](#forms)). To
|
|
172
|
+
commit one cell as it changes, put `lb-row-update` on a widget cell instead
|
|
173
|
+
(see [Committing one cell](#committing-one-cell)).
|
|
178
174
|
|
|
179
175
|
Declare every action on the server, and permit every operation on its list. A
|
|
180
176
|
name the page has not declared, and an operation a list does not permit, are
|
|
@@ -184,7 +180,7 @@ refused; see
|
|
|
184
180
|
### Actions
|
|
185
181
|
|
|
186
182
|
Write `lb-action` on a button to ask the server to do something that is not
|
|
187
|
-
one of the
|
|
183
|
+
one of the three CRUD operations:
|
|
188
184
|
|
|
189
185
|
```html
|
|
190
186
|
<button lb-action="mailRoster">Mail the roster</button>
|
|
@@ -280,6 +276,34 @@ refuses it. A widget may dispatch either from any element, and the hub
|
|
|
280
276
|
gathers the same way; see
|
|
281
277
|
[Sending a request](./custom-elements.md#sending-a-request).
|
|
282
278
|
|
|
279
|
+
### Committing one cell
|
|
280
|
+
|
|
281
|
+
Put `lb-row-update` on a widget that carries `lb-cell` to save that one cell
|
|
282
|
+
whenever it changes. The shipped `<lb-input>` sends it on `change`:
|
|
283
|
+
|
|
284
|
+
```html
|
|
285
|
+
<template lb-key="id">
|
|
286
|
+
<tr>
|
|
287
|
+
<td><lb-input lb-cell="name" lb-action="lb-row-update"></lb-input></td>
|
|
288
|
+
<td><lb-input lb-cell="note" lb-action="lb-row-update"></lb-input></td>
|
|
289
|
+
</tr>
|
|
290
|
+
</template>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
An element carrying `lb-cell` is a record of one cell, the way a control has
|
|
294
|
+
a value and a form has values. Its update carries `values` holding that cell
|
|
295
|
+
alone, so an edit in one input never sends the other. It reaches the same
|
|
296
|
+
`rowUpdate` a form does. SQL has one UPDATE whether it sets one column or
|
|
297
|
+
many, and the application writes one handler for both.
|
|
298
|
+
|
|
299
|
+
The widget decides when the cell has changed. A native `<input>` carrying
|
|
300
|
+
`lb-cell` and `lb-row-update` has no such moment, since a click into it
|
|
301
|
+
would send it, so the hub refuses it and says so.
|
|
302
|
+
|
|
303
|
+
Leave `lb-action` off a widget inside an `lb-row-insert` or `lb-row-update`
|
|
304
|
+
form. The form reads every `lb-cell` in it on submit, so a widget that also
|
|
305
|
+
sent its own would write the same edit twice.
|
|
306
|
+
|
|
283
307
|
## Conditional rendering
|
|
284
308
|
|
|
285
309
|
Loadbare ships static HTML and hydrates elements that are already in the
|
|
@@ -86,7 +86,7 @@ Export `requests` from `<name>.requests.ts`. It holds three keys, each optional:
|
|
|
86
86
|
|---------------|------------------------------------------------------|
|
|
87
87
|
| `onPageEnter` | Before the page's queries, on entering the page |
|
|
88
88
|
| `actions` | What the page may be asked to do, by name |
|
|
89
|
-
| `crud` | The
|
|
89
|
+
| `crud` | The three operations a list permits on its rows |
|
|
90
90
|
|
|
91
91
|
### onPageEnter
|
|
92
92
|
|
|
@@ -127,17 +127,21 @@ carries `list` or `row`, whichever attribute scoped the element, plus `key`,
|
|
|
127
127
|
### crud
|
|
128
128
|
|
|
129
129
|
Declare CRUD operations under `crud`, keyed by the list they operate on. All
|
|
130
|
-
|
|
130
|
+
three are list operations: each needs a key, and a key exists only on a live
|
|
131
131
|
row inside a list, so a single-row scope is read-only and a declared action is
|
|
132
132
|
the only thing it can send. Each operation takes the binding its trigger
|
|
133
133
|
supplies:
|
|
134
134
|
|
|
135
|
-
| Operation
|
|
136
|
-
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
|
|
135
|
+
| Operation | The page writes | `run` receives |
|
|
136
|
+
|-------------|------------------------------------------------------------------------|-----------------|
|
|
137
|
+
| `rowDelete` | `lb-action="lb-row-delete"` | `key` |
|
|
138
|
+
| `rowInsert` | `<form lb-action="lb-row-insert">` | `values` |
|
|
139
|
+
| `rowUpdate` | `<form lb-action="lb-row-update">` or `<lb-input lb-action="lb-row-update">` | `key`, `values` |
|
|
140
|
+
|
|
141
|
+
Write `rowUpdate` to set the columns `values` names and leave every other
|
|
142
|
+
column as it is. A form sends the cells it holds, and a widget cell sends
|
|
143
|
+
itself alone. Check the names in `values` against the columns the list lets
|
|
144
|
+
the page edit.
|
|
141
145
|
|
|
142
146
|
The operation names are reserved: a name beginning with `lb-` cannot be
|
|
143
147
|
declared under `actions` or as a query, and `createHub` refuses a page that
|
|
@@ -179,7 +183,7 @@ would. What `run` returns is laid over the refreshed queries:
|
|
|
179
183
|
| `patch({ drop: [...] })` | These keys are gone; the rest stand |
|
|
180
184
|
|
|
181
185
|
Return a patch for a change the operation knows the extent of — one row added,
|
|
182
|
-
one row dropped, one
|
|
186
|
+
one row dropped, one row edited — and leave `refresh` empty. Re-run the query
|
|
183
187
|
instead when membership or order changed in a way the operation cannot name:
|
|
184
188
|
|
|
185
189
|
```ts
|
|
@@ -19,15 +19,15 @@ npm install @loadbare/widgets
|
|
|
19
19
|
export default ["@loadbare/widgets"];
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
See [
|
|
23
|
-
|
|
22
|
+
See [Widgets from packages](./builder.md#widgets-from-packages) for what
|
|
23
|
+
listing a package does, and [The Builder](./builder.md#where-the-builder-looks)
|
|
24
24
|
for where a listed package sits in the cascade.
|
|
25
25
|
|
|
26
26
|
## `lb-input`
|
|
27
27
|
|
|
28
28
|
Wraps an `<input>`. `lb-value` sets the input's `.value`. The widget sends
|
|
29
29
|
nothing on its own: `lb-action` names what the input's `change` sends. The
|
|
30
|
-
reserved `lb-
|
|
30
|
+
reserved `lb-row-update` saves the input's own cell; any other name sends that
|
|
31
31
|
action. Either carries the input's value, and the hub adds the scope the
|
|
32
32
|
input sits in.
|
|
33
33
|
|
|
@@ -42,7 +42,7 @@ of them, so an input that also sent its own would write the same edit twice.
|
|
|
42
42
|
|
|
43
43
|
| Attribute | Asks for |
|
|
44
44
|
| ---------- | ----- |
|
|
45
|
-
| `lb-action` | what to send on `change`; `lb-
|
|
45
|
+
| `lb-action` | what to send on `change`; `lb-row-update` to save the cell's own edit |
|
|
46
46
|
|
|
47
47
|
## `lb-select`
|
|
48
48
|
|
package/docs/roadmap.md
CHANGED
|
@@ -140,7 +140,7 @@ machinery would then also let `lb-list` and `lb-row` names be checked against
|
|
|
140
140
|
the declared queries.
|
|
141
141
|
|
|
142
142
|
One piece is separable and needs none of the above: an `lb-action` beginning
|
|
143
|
-
with `lb-` that names none of the
|
|
143
|
+
with `lb-` that names none of the three operations is a typo the builder can
|
|
144
144
|
refuse from markup alone. `LB_ACTIONS` in `core/lb-constants.ts` exists for
|
|
145
145
|
this, and the builder does not yet import it.
|
|
146
146
|
|
package/docs/testing.md
CHANGED
|
@@ -188,10 +188,14 @@ What the hub is tested for here:
|
|
|
188
188
|
its scope, whatever shares the button's cell: one ghost row among its
|
|
189
189
|
neighbours, a whole live row, a form nested in a row, a button's form
|
|
190
190
|
owner; and refuses a `<div>` holding cells, pointing to `<form>`
|
|
191
|
+
- an insert or update from an element carrying `lb-cell` sends that cell
|
|
192
|
+
alone, from the value a widget sent or else its control; refuses a value
|
|
193
|
+
with no `lb-cell` to name its column; and refuses a click on a native
|
|
194
|
+
element that is a cell
|
|
191
195
|
- gathering skips the cells of a nested scope, so a picker in a row sends
|
|
192
196
|
its own cell and nothing about its options
|
|
193
197
|
- a request arriving with no action, or with a reserved name that is not one
|
|
194
|
-
of the
|
|
198
|
+
of the three, is refused before it reaches the wire
|
|
195
199
|
- `lb-pending` lands on the element that dispatched, `lb-error` replaces it
|
|
196
200
|
on failure, and the next request clears it
|
|
197
201
|
- `aria-busy` comes and goes with `lb-pending`; a native button or form
|
package/docs/theory.md
CHANGED
|
@@ -460,7 +460,7 @@ that "knows what to do", assembling a request driven purely from
|
|
|
460
460
|
attributes.
|
|
461
461
|
|
|
462
462
|
This requirement is satisfied with a single new attribute, `lb-action`.
|
|
463
|
-
|
|
463
|
+
Three values are reserved, and any other value is interpreted as the
|
|
464
464
|
name of a routine on the server.
|
|
465
465
|
|
|
466
466
|
A request is an action and a position. The author writes the action,
|
|
@@ -37,7 +37,7 @@ class NoteInput extends HTMLElement {
|
|
|
37
37
|
this.dispatchEvent(
|
|
38
38
|
new CustomEvent(LB_EVENT_NAME, {
|
|
39
39
|
bubbles: true,
|
|
40
|
-
detail: { action: "lb-
|
|
40
|
+
detail: { action: "lb-row-update", value: input.value },
|
|
41
41
|
}),
|
|
42
42
|
);
|
|
43
43
|
});
|
|
@@ -49,9 +49,9 @@ customElements.define("note-input", NoteInput);
|
|
|
49
49
|
|
|
50
50
|
A widget with both a `.html` and a `.browser.ts` file shares one tag name; the
|
|
51
51
|
build finds each half independently. On change, it dispatches a
|
|
52
|
-
`lb-
|
|
53
|
-
of the row it is in and
|
|
54
|
-
`lb-
|
|
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`.
|
|
55
55
|
|
|
56
56
|
## Using it
|
|
57
57
|
|
|
@@ -72,30 +72,11 @@ every change, so there's nothing left to batch.
|
|
|
72
72
|
|
|
73
73
|
## Answering it server-side
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// ...onPageEnter and actions unchanged...
|
|
81
|
-
crud: {
|
|
82
|
-
notes: {
|
|
83
|
-
// ...rowInsert, rowDelete, rowUpdate unchanged...
|
|
84
|
-
cellChange: {
|
|
85
|
-
run: async (ctx, { key, value }) => {
|
|
86
|
-
const note = await ctx.db.updateNote(key, value);
|
|
87
|
-
return { notes: patch({ rows: [note] }) };
|
|
88
|
-
},
|
|
89
|
-
refresh: [],
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
`cellChange` reuses `updateNote` from [Updating a List Item](./076-updating-a-list-item.md)
|
|
97
|
-
— the database doesn't care whether the edit came from a form's values
|
|
98
|
-
map or one widget's value.
|
|
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.
|
|
99
80
|
|
|
100
81
|
## Run it
|
|
101
82
|
|
package/package.json
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loadbare/app",
|
|
3
3
|
"description": "High performance web app framework for server-bound applications",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
8
8
|
"docs",
|
|
9
|
+
"skills/loadbare-app/SKILL.md",
|
|
10
|
+
"skills/loadbare-app/references",
|
|
9
11
|
"README.md"
|
|
10
12
|
],
|
|
11
13
|
"publishConfig": {
|
|
12
14
|
"access": "public"
|
|
13
15
|
},
|
|
14
16
|
"bin": {
|
|
15
|
-
"loadbare-app-build": "dist/build/cli.js"
|
|
17
|
+
"loadbare-app-build": "dist/build/cli.js",
|
|
18
|
+
"loadbare-app": "dist/build/skills-cli.js"
|
|
16
19
|
},
|
|
17
20
|
"exports": {
|
|
18
21
|
".": "./dist/hub/lb-hub.browser.js",
|
|
@@ -31,8 +34,9 @@
|
|
|
31
34
|
"release:major": "node ../../scripts/bump-release.mjs major",
|
|
32
35
|
"prebuild": "node --eval \"fs.rmSync('dist',{recursive:true,force:true})\" --input-type=module",
|
|
33
36
|
"build:server": "tsc --project tsconfig.build.json",
|
|
34
|
-
"build": "
|
|
35
|
-
"
|
|
37
|
+
"build:skills": "node scripts/build-skills.mjs",
|
|
38
|
+
"build": "npm run build:server && npm run build:skills",
|
|
39
|
+
"postbuild": "node --eval \"for (const f of ['dist/build/cli.js','dist/build/skills-cli.js']) fs.chmodSync(f, 0o755)\" --input-type=module && node ../../scripts/check-dist-imports.mjs",
|
|
36
40
|
"test": "tsx --test \"tests/**/*.test.ts\"",
|
|
37
41
|
"typecheck": "tsc --noEmit",
|
|
38
42
|
"format": "prettier --write .",
|