@loadbare/app 0.18.0 → 0.18.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/hub/lb-apply.d.ts +12 -4
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +45 -5
- package/dist/hub/lb-apply.js.map +1 -1
- package/dist/hub/lb-hub.browser.js +3 -3
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/docs/TECHREF-1.0.md +50 -56
- package/docs/comparison.md +1 -2
- package/docs/reference/data-binding.md +23 -2
- package/docs/roadmap.md +17 -9
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +5 -2
- package/skills/loadbare-app/references/TECHREF-1.0.md +50 -56
- package/skills/loadbare-app/references/data-binding.md +23 -2
package/dist/hub/lb-apply.d.ts
CHANGED
|
@@ -3,23 +3,31 @@ import { type ColumnTypes, type ResponseItem, type Row, type RowsResult } from "
|
|
|
3
3
|
export interface Control extends Element {
|
|
4
4
|
value: string;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* A radio button, whose state is `checked` as well. It is checked when its
|
|
8
|
+
* own `value` is the value that landed, so a group of them naming one column
|
|
9
|
+
* shows that value, and gathers the one checked.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isRadio(el: Element): boolean;
|
|
6
12
|
/**
|
|
7
13
|
* A form-associated custom element with a `value` property. HTML marks one
|
|
8
14
|
* with `static formAssociated = true` on its class, and a control has a value.
|
|
9
15
|
*/
|
|
10
16
|
export declare function isFormAssociated(el: Element): boolean;
|
|
11
17
|
/**
|
|
12
|
-
* A control: an `<input>`, `<select>` or `<textarea>`, a checkbox,
|
|
18
|
+
* A control: an `<input>`, `<select>` or `<textarea>`, a checkbox, a radio
|
|
19
|
+
* button, or a
|
|
13
20
|
* form-associated custom element with a `value` property. Landing and
|
|
14
21
|
* gathering draw the same line, so a value read back is the one that landed
|
|
15
22
|
* there.
|
|
16
23
|
*/
|
|
17
24
|
export declare function isControl(el: Element): el is Control;
|
|
18
25
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
26
|
+
* Gather a control into `values` under its column. Of the radio buttons
|
|
27
|
+
* naming one column, the one checked gives the value, and `""` stands when
|
|
28
|
+
* none is.
|
|
21
29
|
*/
|
|
22
|
-
export declare function
|
|
30
|
+
export declare function gatherInto(values: Record<string, string>, column: string, el: Control): void;
|
|
23
31
|
/**
|
|
24
32
|
* Root if it matches, then every descendant in root's query that does.
|
|
25
33
|
* Gathering finds columns through here. It does not reach into an absent
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"AA+EA,OAAO,EASL,KAAK,WAAW,EAKhB,KAAK,YAAY,EACjB,KAAK,GAAG,EACR,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"AA+EA,OAAO,EASL,KAAK,WAAW,EAKhB,KAAK,YAAY,EACjB,KAAK,GAAG,EACR,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AA0B7B,mEAAmE;AACnE,MAAM,WAAW,OAAQ,SAAQ,OAAO;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AA4BD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAE5C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAGrD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,OAAO,CAIpD;AAUD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,OAAO,GACV,IAAI,CAMN;AA0FD;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAMjE;AA0CD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CAGtD;AA6LD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,GAAG,EACR,IAAI,UAAQ,EACZ,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG,CAU3C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAKlE;AAQD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAS3C;AAsnBD,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,mDAAmD;IACnD,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,OAAO,EACX,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,WAAgB,GACxB,IAAI,CAgIN;AAmFD,uDAAuD;AACvD,wBAAgB,UAAU,CACxB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,GACZ,YAAY,GAAG,SAAS,CAE1B;AAgBD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAE7C;AAoGD,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,GAAE,WAAgB,GACxB,IAAI,CA2BN"}
|
package/dist/hub/lb-apply.js
CHANGED
|
@@ -49,7 +49,8 @@ const ELEMENT_NODE = 1;
|
|
|
49
49
|
const TEXT_NODE = 3;
|
|
50
50
|
/**
|
|
51
51
|
* The input types whose state is not their `value`, or cannot be set. A
|
|
52
|
-
* checkbox's state is `checked`, and
|
|
52
|
+
* checkbox's and a radio button's state is `checked`, and each is a control
|
|
53
|
+
* by its own rule.
|
|
53
54
|
*/
|
|
54
55
|
const UNLANDED_INPUTS = ["checkbox", "radio", "file"];
|
|
55
56
|
/**
|
|
@@ -73,6 +74,14 @@ function isNativeControl(el) {
|
|
|
73
74
|
function isCheckbox(el) {
|
|
74
75
|
return (el.localName === "input" && el.type === "checkbox");
|
|
75
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* A radio button, whose state is `checked` as well. It is checked when its
|
|
79
|
+
* own `value` is the value that landed, so a group of them naming one column
|
|
80
|
+
* shows that value, and gathers the one checked.
|
|
81
|
+
*/
|
|
82
|
+
export function isRadio(el) {
|
|
83
|
+
return el.localName === "input" && el.type === "radio";
|
|
84
|
+
}
|
|
76
85
|
/**
|
|
77
86
|
* A form-associated custom element with a `value` property. HTML marks one
|
|
78
87
|
* with `static formAssociated = true` on its class, and a control has a value.
|
|
@@ -82,21 +91,34 @@ export function isFormAssociated(el) {
|
|
|
82
91
|
return ctor.formAssociated === true && "value" in el;
|
|
83
92
|
}
|
|
84
93
|
/**
|
|
85
|
-
* A control: an `<input>`, `<select>` or `<textarea>`, a checkbox,
|
|
94
|
+
* A control: an `<input>`, `<select>` or `<textarea>`, a checkbox, a radio
|
|
95
|
+
* button, or a
|
|
86
96
|
* form-associated custom element with a `value` property. Landing and
|
|
87
97
|
* gathering draw the same line, so a value read back is the one that landed
|
|
88
98
|
* there.
|
|
89
99
|
*/
|
|
90
100
|
export function isControl(el) {
|
|
91
|
-
return isNativeControl(el) || isCheckbox(el) || isFormAssociated(el);
|
|
101
|
+
return (isNativeControl(el) || isCheckbox(el) || isRadio(el) || isFormAssociated(el));
|
|
92
102
|
}
|
|
93
103
|
/**
|
|
94
104
|
* What a control gathers: a checkbox `"true"` or `"false"`, so unchecked
|
|
95
105
|
* still says so, and any other control its `value`.
|
|
96
106
|
*/
|
|
97
|
-
|
|
107
|
+
function controlValue(el) {
|
|
98
108
|
return isCheckbox(el) ? String(el.checked) : el.value;
|
|
99
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Gather a control into `values` under its column. Of the radio buttons
|
|
112
|
+
* naming one column, the one checked gives the value, and `""` stands when
|
|
113
|
+
* none is.
|
|
114
|
+
*/
|
|
115
|
+
export function gatherInto(values, column, el) {
|
|
116
|
+
if (isRadio(el) && !el.checked) {
|
|
117
|
+
values[column] ??= "";
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
values[column] = controlValue(el);
|
|
121
|
+
}
|
|
100
122
|
/**
|
|
101
123
|
* Set an element from a column. A control's `value` is set. A custom element
|
|
102
124
|
* that is not a control keeps its content, which the builder placed there
|
|
@@ -107,8 +129,9 @@ function land(el, value) {
|
|
|
107
129
|
// Untouched, whatever the server sent: the browser decides what a
|
|
108
130
|
// non-string looks like. See Row in core/lb-types.ts.
|
|
109
131
|
if (value === null || value === undefined) {
|
|
110
|
-
if (isCheckbox(el))
|
|
132
|
+
if (isCheckbox(el) || isRadio(el)) {
|
|
111
133
|
el.checked = false;
|
|
134
|
+
}
|
|
112
135
|
else if (isControl(el))
|
|
113
136
|
el.value = "";
|
|
114
137
|
else if (!el.localName.includes("-") && el.localName !== "input") {
|
|
@@ -122,6 +145,10 @@ function land(el, value) {
|
|
|
122
145
|
// and no string is read.
|
|
123
146
|
el.checked = value !== false;
|
|
124
147
|
}
|
|
148
|
+
else if (isRadio(el)) {
|
|
149
|
+
el.checked =
|
|
150
|
+
el.value === String(value);
|
|
151
|
+
}
|
|
125
152
|
else if (isControl(el)) {
|
|
126
153
|
el.value = value;
|
|
127
154
|
}
|
|
@@ -587,6 +614,7 @@ function create(list, doc, key) {
|
|
|
587
614
|
placed(el);
|
|
588
615
|
el.setAttribute(ATTR_ROW_LIVE, "");
|
|
589
616
|
el.setAttribute(ATTR_KEY_VALUE, key);
|
|
617
|
+
nameRadios(el, key);
|
|
590
618
|
const entry = {
|
|
591
619
|
key,
|
|
592
620
|
el,
|
|
@@ -597,6 +625,18 @@ function create(list, doc, key) {
|
|
|
597
625
|
list.byKey.set(key, entry);
|
|
598
626
|
return entry;
|
|
599
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* Give each radio button of a new live row a group of its own. The browser
|
|
630
|
+
* groups radio buttons by `name`, and a row template repeats one `name` in
|
|
631
|
+
* every live row, so the hub follows the `name` written, or the column when
|
|
632
|
+
* none is, with the row's key.
|
|
633
|
+
*/
|
|
634
|
+
function nameRadios(row, key) {
|
|
635
|
+
for (const el of below(row, `input[type=radio][${ATTR_COLUMN}]`)) {
|
|
636
|
+
const name = el.getAttribute("name") || el.getAttribute(ATTR_COLUMN);
|
|
637
|
+
el.setAttribute("name", `${name}-${key}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
600
640
|
/** A group's identity among its siblings: its column and its value there. */
|
|
601
641
|
function groupId(column, value) {
|
|
602
642
|
return `${column}\u0000${JSON.stringify(value ?? null)}`;
|