@thi.ng/rdom 0.13.3 → 0.13.5
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/CHANGELOG.md +7 -1
- package/README.md +2 -1
- package/api.js +0 -1
- package/checks.js +8 -23
- package/compile.js +57 -87
- package/component.js +143 -133
- package/dom.js +197 -373
- package/event.js +14 -51
- package/idgen.js +4 -2
- package/klist.js +105 -161
- package/list.js +64 -108
- package/object.js +34 -97
- package/package.json +15 -12
- package/promise.js +24 -40
- package/replace.js +30 -58
- package/scheduler.js +36 -51
- package/sub.js +49 -47
- package/switch.js +66 -135
- package/wrap.js +31 -47
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-12-
|
|
3
|
+
- **Last updated**: 2023-12-18T13:41:19Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
### [0.13.4](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom@0.13.4) (2023-12-11)
|
|
13
|
+
|
|
14
|
+
#### ♻️ Refactoring
|
|
15
|
+
|
|
16
|
+
- update boolean attrib handling in setAttrib() ([96a21ab](https://github.com/thi-ng/umbrella/commit/96a21ab))
|
|
17
|
+
|
|
12
18
|
### [0.13.3](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom@0.13.3) (2023-12-09)
|
|
13
19
|
|
|
14
20
|
#### 🩹 Bug fixes
|
package/README.md
CHANGED
|
@@ -279,7 +279,7 @@ For Node.js REPL:
|
|
|
279
279
|
const rdom = await import("@thi.ng/rdom");
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 4.
|
|
282
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 4.06 KB
|
|
283
283
|
|
|
284
284
|
## Dependencies
|
|
285
285
|
|
|
@@ -309,6 +309,7 @@ directory are using this package:
|
|
|
309
309
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/layout-gridgen.png" width="240"/> | Randomized space-filling, nested grid layout generator | [Demo](https://demo.thi.ng/umbrella/layout-gridgen/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/layout-gridgen) |
|
|
310
310
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/lispy-repl.png" width="240"/> | Browser REPL for a Lispy S-expression based mini language | [Demo](https://demo.thi.ng/umbrella/lispy-repl/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/lispy-repl) |
|
|
311
311
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/mastodon-feed.jpg" width="240"/> | Mastodon API feed reader with support for different media types, fullscreen media modal, HTML rewriting | [Demo](https://demo.thi.ng/umbrella/mastodon-feed/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/mastodon-feed) |
|
|
312
|
+
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/meta-css-basics.png" width="240"/> | Basic thi.ng/meta-css usage & testbed | [Demo](https://demo.thi.ng/umbrella/meta-css-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/meta-css-basics) |
|
|
312
313
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/parse-playground.png" width="240"/> | Parser grammar livecoding editor/playground & codegen | [Demo](https://demo.thi.ng/umbrella/parse-playground/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/parse-playground) |
|
|
313
314
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pixel-colormatrix.jpg" width="240"/> | Matrix-based image color adjustments | [Demo](https://demo.thi.ng/umbrella/pixel-colormatrix/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-colormatrix) |
|
|
314
315
|
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pixel-gradients.jpg" width="240"/> | Randomized 4-point 2D color gradient image generator | [Demo](https://demo.thi.ng/umbrella/pixel-gradients/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-gradients) |
|
package/api.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/checks.js
CHANGED
|
@@ -1,25 +1,10 @@
|
|
|
1
1
|
import { implementsFunction } from "@thi.ng/checks/implements-function";
|
|
2
2
|
import { COMMENT } from "@thi.ng/hiccup/api";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @param tree
|
|
12
|
-
*/
|
|
13
|
-
export const isComment = (tree) => tree[0] === COMMENT;
|
|
14
|
-
/**
|
|
15
|
-
* Returns true if given value has a {@link IComponent.mount} function.
|
|
16
|
-
*
|
|
17
|
-
* @param x
|
|
18
|
-
*/
|
|
19
|
-
export const isComponent = (x) => implementsFunction(x, "mount");
|
|
20
|
-
/**
|
|
21
|
-
* Returns true if given value is a DOM element.
|
|
22
|
-
*
|
|
23
|
-
* @param x
|
|
24
|
-
*/
|
|
25
|
-
export const isElement = (x) => x instanceof Element;
|
|
3
|
+
const isComment = (tree) => tree[0] === COMMENT;
|
|
4
|
+
const isComponent = (x) => implementsFunction(x, "mount");
|
|
5
|
+
const isElement = (x) => x instanceof Element;
|
|
6
|
+
export {
|
|
7
|
+
isComment,
|
|
8
|
+
isComponent,
|
|
9
|
+
isElement
|
|
10
|
+
};
|
package/compile.js
CHANGED
|
@@ -6,101 +6,71 @@ import { $el, $remove, $tree } from "./dom.js";
|
|
|
6
6
|
import { SCHEDULER } from "./scheduler.js";
|
|
7
7
|
import { $SubA, $sub } from "./sub.js";
|
|
8
8
|
import { $wrapEl, $wrapText } from "./wrap.js";
|
|
9
|
-
|
|
10
|
-
* Compiles a tree of components given in any supported format incl. reactive
|
|
11
|
-
* state values into a single, nested {@link IComponent}.
|
|
12
|
-
*
|
|
13
|
-
* @remarks
|
|
14
|
-
* Supported formats/values:
|
|
15
|
-
*
|
|
16
|
-
* - hiccup component trees, i.e. `["tag#id.class", attribs, [...]]`
|
|
17
|
-
* - {@link IComponent} instances
|
|
18
|
-
* - pre-existing DOM elements
|
|
19
|
-
* - [`ISubscribable`](https://docs.thi.ng/umbrella/rstream/interfaces/ISubscribable.html)
|
|
20
|
-
* instances
|
|
21
|
-
* - [`IDeref`](https://docs.thi.ng/umbrella/api/interfaces/IDeref.html)
|
|
22
|
-
* instances
|
|
23
|
-
*
|
|
24
|
-
* Any other value type will be wrapped in a `<span>` element. Reactive
|
|
25
|
-
* `ISubscribable` values can be used as element attributes or element
|
|
26
|
-
* body/children. For the former, a subscription will be added to update the
|
|
27
|
-
* target attribute. If used as element body, the reactive value will be wrapped
|
|
28
|
-
* using a {@link $sub} `<span>` with the value as its reactive body.
|
|
29
|
-
*
|
|
30
|
-
* @param tree -
|
|
31
|
-
*/
|
|
32
|
-
export const $compile = (tree) => isArray(tree)
|
|
33
|
-
? isComplexComponent(tree)
|
|
34
|
-
? complexComponent(tree)
|
|
35
|
-
: basicComponent(tree)
|
|
36
|
-
: isComponent(tree)
|
|
37
|
-
? tree
|
|
38
|
-
: isSubscribable(tree)
|
|
39
|
-
? $sub(tree, "span")
|
|
40
|
-
: tree instanceof Element
|
|
41
|
-
? $wrapEl(tree)
|
|
42
|
-
: $wrapText("span", null, tree);
|
|
9
|
+
const $compile = (tree) => isArray(tree) ? isComplexComponent(tree) ? complexComponent(tree) : basicComponent(tree) : isComponent(tree) ? tree : isSubscribable(tree) ? $sub(tree, "span") : tree instanceof Element ? $wrapEl(tree) : $wrapText("span", null, tree);
|
|
43
10
|
const walk = (f, x, path = []) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
11
|
+
if (isPlainObject(x)) {
|
|
12
|
+
for (const k in x) {
|
|
13
|
+
walk(f, x[k], [...path, k]);
|
|
48
14
|
}
|
|
49
|
-
|
|
15
|
+
}
|
|
16
|
+
f(x, path);
|
|
50
17
|
};
|
|
51
18
|
const isComplexComponent = (x) => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
19
|
+
if (isPlainObject(x)) {
|
|
20
|
+
for (const k in x) {
|
|
21
|
+
if (isComplexComponent(x[k]))
|
|
22
|
+
return true;
|
|
57
23
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
24
|
+
} else if (isArray(x)) {
|
|
25
|
+
for (let i = 0, n = x.length; i < n; i++) {
|
|
26
|
+
if (isComplexComponent(x[i]))
|
|
27
|
+
return true;
|
|
63
28
|
}
|
|
64
|
-
|
|
29
|
+
}
|
|
30
|
+
return isSubscribable(x) || isComponent(x) || isElement(x);
|
|
65
31
|
};
|
|
66
32
|
const complexComponent = (tree) => ({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
33
|
+
async mount(parent, index = -1) {
|
|
34
|
+
this.subs = [];
|
|
35
|
+
walk((x, path) => {
|
|
36
|
+
isSubscribable(x) && this.subs.push(x.subscribe(new $SubA(this, path)));
|
|
37
|
+
}, tree[1]);
|
|
38
|
+
this.children = [];
|
|
39
|
+
this.el = $el(tree[0], tree[1], null, parent, index);
|
|
40
|
+
for (let i = 2; i < tree.length; i++) {
|
|
41
|
+
const child = $compile(tree[i]);
|
|
42
|
+
child.mount(this.el, i - 2);
|
|
43
|
+
this.children.push(child);
|
|
44
|
+
}
|
|
45
|
+
return this.el;
|
|
46
|
+
},
|
|
47
|
+
async unmount() {
|
|
48
|
+
SCHEDULER.cancel(this);
|
|
49
|
+
if (this.children) {
|
|
50
|
+
for (let c of this.children) {
|
|
51
|
+
await c.unmount();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
this.subs && this.subs.forEach((s) => s.unsubscribe());
|
|
55
|
+
$remove(this.el);
|
|
56
|
+
this.children = void 0;
|
|
57
|
+
this.subs = void 0;
|
|
58
|
+
this.el = void 0;
|
|
59
|
+
},
|
|
60
|
+
update() {
|
|
61
|
+
}
|
|
96
62
|
});
|
|
97
63
|
const basicComponent = (tree) => ({
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
64
|
+
async mount(parent, index = -1) {
|
|
65
|
+
return this.el = await $tree(tree, parent, index);
|
|
66
|
+
},
|
|
67
|
+
async unmount() {
|
|
68
|
+
$remove(this.el);
|
|
69
|
+
this.el = void 0;
|
|
70
|
+
},
|
|
71
|
+
update() {
|
|
72
|
+
}
|
|
106
73
|
});
|
|
74
|
+
export {
|
|
75
|
+
$compile
|
|
76
|
+
};
|
package/component.js
CHANGED
|
@@ -1,135 +1,145 @@
|
|
|
1
1
|
import { $compile } from "./compile.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
$
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
2
|
+
import {
|
|
3
|
+
$attribs,
|
|
4
|
+
$clear,
|
|
5
|
+
$comment,
|
|
6
|
+
$el,
|
|
7
|
+
$html,
|
|
8
|
+
$moveTo,
|
|
9
|
+
$remove,
|
|
10
|
+
$style,
|
|
11
|
+
$text,
|
|
12
|
+
$tree
|
|
13
|
+
} from "./dom.js";
|
|
14
|
+
class Component {
|
|
15
|
+
el;
|
|
16
|
+
async unmount() {
|
|
17
|
+
this.$remove();
|
|
18
|
+
this.el = void 0;
|
|
19
|
+
}
|
|
20
|
+
// @ts-ignore args
|
|
21
|
+
update(state) {
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Syntax sugar for {@link $el}, using this component's
|
|
25
|
+
* {@link IComponent.el} as default `parent`.
|
|
26
|
+
*
|
|
27
|
+
* @param tag
|
|
28
|
+
* @param attribs
|
|
29
|
+
* @param body
|
|
30
|
+
* @param parent
|
|
31
|
+
* @param idx
|
|
32
|
+
*/
|
|
33
|
+
$el(tag, attribs, body, parent = this.el, idx) {
|
|
34
|
+
return $el(tag, attribs, body, parent, idx);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Syntax sugar for {@link $comment}, creates a new comment DOM node using
|
|
38
|
+
* this component's {@link IComponent.el} as default `parent`.
|
|
39
|
+
*
|
|
40
|
+
* @param body
|
|
41
|
+
* @param parent
|
|
42
|
+
* @param idx
|
|
43
|
+
*/
|
|
44
|
+
$comment(body, parent = this.el, idx) {
|
|
45
|
+
return $comment(body, parent, idx);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Syntax sugar for {@link $clear}, using this component's
|
|
49
|
+
* {@link IComponent.el} as default element to clear.
|
|
50
|
+
*
|
|
51
|
+
* @param el
|
|
52
|
+
*/
|
|
53
|
+
$clear(el = this.el) {
|
|
54
|
+
return $clear(el);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Same as {@link $compile}.
|
|
58
|
+
*
|
|
59
|
+
* @param tree
|
|
60
|
+
*/
|
|
61
|
+
$compile(tree) {
|
|
62
|
+
return $compile(tree);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Same as {@link $tree}.
|
|
66
|
+
*
|
|
67
|
+
* @param tree
|
|
68
|
+
* @param root
|
|
69
|
+
* @param index
|
|
70
|
+
*/
|
|
71
|
+
$tree(tree, root = this.el, index) {
|
|
72
|
+
return $tree(tree, root, index);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Syntax sugar for {@link $text}, using this component's
|
|
76
|
+
* {@link IComponent.el} as default element to edit.
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* If using the default element, assumes `this.el` is an existing
|
|
80
|
+
* `HTMLElement`.
|
|
81
|
+
*
|
|
82
|
+
* @param body
|
|
83
|
+
* @param el
|
|
84
|
+
*/
|
|
85
|
+
$text(body, el = this.el) {
|
|
86
|
+
$text(el, body);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Syntax sugar for {@link $html}, using this component's
|
|
90
|
+
* {@link IComponent.el} as default element to edit.
|
|
91
|
+
*
|
|
92
|
+
* @remarks
|
|
93
|
+
* If using the default element, assumes `this.el` is an existing
|
|
94
|
+
* `HTMLElement` or `SVGElement`.
|
|
95
|
+
*
|
|
96
|
+
* @param body
|
|
97
|
+
* @param el
|
|
98
|
+
*/
|
|
99
|
+
$html(body, el = this.el) {
|
|
100
|
+
$html(el, body);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Syntax sugar for {@link $attribs}, using this component's
|
|
104
|
+
* {@link IComponent.el} as default element to edit.
|
|
105
|
+
*
|
|
106
|
+
* @param attribs
|
|
107
|
+
* @param el
|
|
108
|
+
*/
|
|
109
|
+
$attribs(attribs, el = this.el) {
|
|
110
|
+
$attribs(el, attribs);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Syntax sugar for {@link $style}, using this component's
|
|
114
|
+
* {@link IComponent.el} as default element to edit.
|
|
115
|
+
*
|
|
116
|
+
* @param rules
|
|
117
|
+
* @param el
|
|
118
|
+
*/
|
|
119
|
+
$style(rules, el = this.el) {
|
|
120
|
+
$style(el, rules);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Syntax sugar for {@link $remove}, using this component's
|
|
124
|
+
* {@link IComponent.el} as default element to remove.
|
|
125
|
+
*
|
|
126
|
+
* @param el
|
|
127
|
+
*/
|
|
128
|
+
$remove(el = this.el) {
|
|
129
|
+
$remove(el);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Syntax sugar for {@link $moveTo}, using this component's
|
|
133
|
+
* {@link IComponent.el} as default element to migrate.
|
|
134
|
+
*
|
|
135
|
+
* @param newParent
|
|
136
|
+
* @param el
|
|
137
|
+
* @param idx
|
|
138
|
+
*/
|
|
139
|
+
$moveTo(newParent, el = this.el, idx) {
|
|
140
|
+
$moveTo(newParent, el, idx);
|
|
141
|
+
}
|
|
135
142
|
}
|
|
143
|
+
export {
|
|
144
|
+
Component
|
|
145
|
+
};
|