@thi.ng/rdom 1.1.22 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-04-08T14:59:30Z
3
+ - **Last updated**: 2024-04-20T14:42:45Z
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,29 @@ 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
+ ## [1.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom@1.3.0) (2024-04-20)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add support for async iterables ([742e0db](https://github.com/thi-ng/umbrella/commit/742e0db))
17
+ - add $async() component wrapper
18
+ - add $asyncA() attribute wrapper
19
+ - update $compile() to support embedded `AsyncIterable` values
20
+ - update wrapper() to support reactive/async attribs ([96ea779](https://github.com/thi-ng/umbrella/commit/96ea779))
21
+ - internally switch from `$el()` => `$compile()`
22
+
23
+ #### ♻️ Refactoring
24
+
25
+ - update type usage ([56d5747](https://github.com/thi-ng/umbrella/commit/56d5747))
26
+
27
+ ## [1.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom@1.2.0) (2024-04-11)
28
+
29
+ #### 🚀 Features
30
+
31
+ - update setAttrib() property vs. attrib handling ([52cfe72](https://github.com/thi-ng/umbrella/commit/52cfe72))
32
+ - add/build cache of property setters
33
+ - update setAttrib() to prioritize setters and only fallback to attributes
34
+
12
35
  ## [1.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/rdom@1.1.0) (2024-02-10)
13
36
 
14
37
  #### 🚀 Features
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Mastodon Follow](https://img.shields.io/mastodon/follow/109331703950160316?domain=https%3A%2F%2Fmastodon.thi.ng&style=social)](https://mastodon.thi.ng/@toxi)
8
8
 
9
9
  > [!NOTE]
10
- > This is one of 191 standalone projects, maintained as part
10
+ > This is one of 192 standalone projects, maintained as part
11
11
  > of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
12
12
  > and anti-framework.
13
13
  >
@@ -22,6 +22,7 @@
22
22
  - [DOM creation & mutation](#dom-creation--mutation)
23
23
  - [Control structures](#control-structures)
24
24
  - [Event handlers for reactive streams](#event-handlers-for-reactive-streams)
25
+ - [Embedding async iterables](#embedding-async-iterables)
25
26
  - [Status](#status)
26
27
  - [Support packages](#support-packages)
27
28
  - [Related packages](#related-packages)
@@ -110,14 +111,16 @@ reasons.
110
111
 
111
112
  Because _rdom_ itself relies for most reactive features, stream composition and
112
113
  reactive value transformations on other packages, i.e.
113
- [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream)
114
+ [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream),
115
+ [@thi.ng/transducers-async](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers-async)
114
116
  and
115
117
  [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers),
116
118
  please consult the docs for these packages to learn more about the available
117
119
  constructs and patterns. Most of _rdom_ only deals with either subscribing to
118
- reactive values and/or wrapping/transforming existing subscriptions, either
119
- explicitly using the provided control components (e.g.
120
- [`$sub()`](https://docs.thi.ng/umbrella/rdom/functions/_sub.html)) or using
120
+ reactive values, async iterables and/or wrapping/transforming existing
121
+ subscriptions, either explicitly using the provided control components (e.g.
122
+ [`$async()`](https://docs.thi.ng/umbrella/rdom/functions/_async.html)),
123
+ [`$sub()`](https://docs.thi.ng/umbrella/rdom/functions/_sub.html), or using
121
124
  [`$compile()`](https://docs.thi.ng/umbrella/rdom/functions/_compile.html) to
122
125
  auto-wrap such values embedded in an hiccup tree.
123
126
 
@@ -144,8 +147,8 @@ as a facade for many of these other functions and creates an actual DOM from a
144
147
  given hiccup component tree. It also automatically wraps any reactive values
145
148
  contained therein.
146
149
 
147
- **All of these functions are also usable, even if you don't intend to use any
148
- other package features!**
150
+ **All of the following functions are also usable, even if you don't intend to
151
+ use any other package features!**
149
152
 
150
153
  - [$addChild](https://docs.thi.ng/umbrella/rdom/functions/_addChild.html)
151
154
  - [$attribs](https://docs.thi.ng/umbrella/rdom/functions/_attribs.html)
@@ -168,6 +171,7 @@ for the implementation of common UI structures (e.g. item lists of any kind).
168
171
  The following links lead to the documentation of these wrappers, incl. small
169
172
  code examples:
170
173
 
174
+ - [$async](https://docs.thi.ng/umbrella/rdom/functions/_async.html)
171
175
  - [$klist](https://docs.thi.ng/umbrella/rdom/functions/_klist.html)
172
176
  - [$list](https://docs.thi.ng/umbrella/rdom/functions/_list.html)
173
177
  - [$lazy](https://docs.thi.ng/umbrella/rdom/functions/_lazy.html)
@@ -184,12 +188,12 @@ code examples:
184
188
 
185
189
  ### Event handlers for reactive streams
186
190
 
187
- Reactive rdom component are based on
191
+ Currently, reactive rdom components are based on
188
192
  [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream)
189
- subscriptions. In order to create a feedback loop between those reactive state
190
- values and their subscribed UI components, input event handlers need to feed any
191
- user changes back to those reactive state(s). To reduce boilerplate for these
192
- tasks, the following higher order input event handlers are provided:
193
+ subscriptions. To create a feedback loop between those reactive state values and
194
+ their subscribed UI components, input event handlers need to feed any user
195
+ changes back to those reactive state(s). To reduce boilerplate for these tasks,
196
+ the following higher order input event handlers are provided:
193
197
 
194
198
  - [$input](https://docs.thi.ng/umbrella/rdom/functions/_input.html)
195
199
  - [$inputCheckbox](https://docs.thi.ng/umbrella/rdom/functions/_inputCheckbox.html)
@@ -218,7 +222,8 @@ $compile(["input", {
218
222
  name.subscribe(trace("name:"));
219
223
  ```
220
224
 
221
- Click counter:
225
+ Click counter using [thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/develop/packages/rstream) and
226
+ [thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers):
222
227
 
223
228
  ```ts
224
229
  import { $compile, $inputTrigger } from "@thi.ng/rdom";
@@ -239,6 +244,34 @@ $compile([
239
244
  ]).mount(document.body);
240
245
  ```
241
246
 
247
+ ### Embedding async iterables
248
+
249
+ Work is underway to better support [built-in
250
+ AsyncIterables](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols)
251
+ (possibly entirely in-lieu of rstream constructs). Currently, they can only be directly used for simple text or attribute values (also see the [rdom-async example](https://github.com/thi-ng/umbrella/blob/develop/examples/rdom-async)):
252
+
253
+ ```ts
254
+ import { $compile } from "@thi.ng/rdom";
255
+ import { range, source } from "@thi.ng/transducers-async";
256
+
257
+ // infinite 1Hz counter
258
+ const counter = range(1000);
259
+
260
+ // manually updated click counter (also an async iterable)
261
+ const clicks = source(0);
262
+
263
+ // event handler to update click count
264
+ const updateClicks = () => clicks.update((x)=> x + 1);
265
+
266
+ // compile DOM with embedded async iterables
267
+ $compile(
268
+ ["div", {},
269
+ ["div", {}, "counter: ", counter],
270
+ ["button", { onclick: updateClicks }, "clicks: ", clicks]
271
+ ]
272
+ ).mount(document.body)
273
+ ```
274
+
242
275
  ## Status
243
276
 
244
277
  **STABLE** - used in production
@@ -274,12 +307,12 @@ import * as rdom from "@thi.ng/rdom";
274
307
  Browser ESM import:
275
308
 
276
309
  ```html
277
- <script type="module" src="https://cdn.skypack.dev/@thi.ng/rdom"></script>
310
+ <script type="module" src="https://esm.run/@thi.ng/rdom"></script>
278
311
  ```
279
312
 
280
- [Skypack documentation](https://docs.skypack.dev/)
313
+ [JSDelivr documentation](https://www.jsdelivr.com/)
281
314
 
282
- Package sizes (brotli'd, pre-treeshake): ESM: 4.02 KB
315
+ Package sizes (brotli'd, pre-treeshake): ESM: 4.21 KB
283
316
 
284
317
  ## Dependencies
285
318
 
@@ -319,6 +352,7 @@ directory are using this package:
319
352
  | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pointfree-geom.jpg" width="240"/> | Live coding playground for 2D geometry generation using @thi.ng/pointfree-lang | [Demo](https://demo.thi.ng/umbrella/pointfree-geom/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pointfree-geom) |
320
353
  | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/procedural-text.jpg" width="240"/> | Procedural stochastic text generation via custom DSL, parse grammar & AST transformation | [Demo](https://demo.thi.ng/umbrella/procedural-text/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/procedural-text) |
321
354
  | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/ramp-scroll-anim.png" width="240"/> | Scroll-based, reactive, multi-param CSS animation basics | [Demo](https://demo.thi.ng/umbrella/ramp-scroll-anim/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/ramp-scroll-anim) |
355
+ | | Basic & barebones usage of async iterables in thi.ng/rdom | [Demo](https://demo.thi.ng/umbrella/rdom-async/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-async) |
322
356
  | | Demonstates various rdom usage patterns | [Demo](https://demo.thi.ng/umbrella/rdom-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-basics) |
323
357
  | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rdom-delayed-update.jpg" width="240"/> | Dynamically loaded images w/ preloader state | [Demo](https://demo.thi.ng/umbrella/rdom-delayed-update/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-delayed-update) |
324
358
  | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/rdom-dnd.png" width="240"/> | rdom drag & drop example | [Demo](https://demo.thi.ng/umbrella/rdom-dnd/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-dnd) |
package/async.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ import type { Maybe, Path } from "@thi.ng/api";
2
+ import type { IComponent, IMountWithState, NumOrElement } from "./api.js";
3
+ /**
4
+ * Takes an ES `AsyncIterable` and creates a simple component wrapper for its
5
+ * asynchronously produced values.
6
+ *
7
+ * @remarks
8
+ * If given an {@link IMountWithState} component, new values are applied via the
9
+ * `.update()` life cycle value. If given a `tag` and `attribs`, a corresponding
10
+ * element wrapper component will be created automatically (using
11
+ * {@link $wrapText} and incoming values will be applied using {@link $text}
12
+ * (aka setting `el.innerText`).
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { $async } from "@thi.ng/rdom";
17
+ * import { range } from "@thi.ng/transducers-async";
18
+ *
19
+ * // infinite 1Hz counter
20
+ * const counter = range(1000);
21
+ *
22
+ * // wrapper component which updates whenever counter produces new values
23
+ * $async(counter, "div", { class: "red" }).mount(document.body);
24
+ * ```
25
+ *
26
+ * @param src -
27
+ * @param inner -
28
+ */
29
+ export declare function $async<T>(src: AsyncIterable<T>, inner: IMountWithState<T>): IComponent<T>;
30
+ export declare function $async(src: AsyncIterable<any>, tag: string, attribs?: any): IComponent;
31
+ export declare class $Async<T = any> {
32
+ protected src: AsyncIterable<T>;
33
+ protected inner: IMountWithState<Maybe<T>>;
34
+ el?: Element;
35
+ constructor(src: AsyncIterable<T>, inner: IMountWithState<Maybe<T>>);
36
+ mount(parent: ParentNode, index?: NumOrElement): Promise<Element>;
37
+ unmount(): Promise<void>;
38
+ update(x: T): void;
39
+ }
40
+ export declare const $asyncA: (src: AsyncIterable<any>, comp: IComponent, path: Path) => Promise<void>;
41
+ //# sourceMappingURL=async.d.ts.map
package/async.js ADDED
@@ -0,0 +1,46 @@
1
+ import { isString } from "@thi.ng/checks/is-string";
2
+ import { defSetterUnsafe } from "@thi.ng/paths/setter";
3
+ import { $attribs } from "./dom.js";
4
+ import { $wrapText } from "./wrap.js";
5
+ function $async(src, tag, attribs) {
6
+ return new $Async(src, isString(tag) ? $wrapText(tag, attribs) : tag);
7
+ }
8
+ class $Async {
9
+ constructor(src, inner) {
10
+ this.src = src;
11
+ this.inner = inner;
12
+ }
13
+ el;
14
+ async mount(parent, index = -1) {
15
+ this.el = await this.inner.mount(parent, index, void 0);
16
+ (async () => {
17
+ for await (let x of this.src) {
18
+ if (!this.el)
19
+ return;
20
+ this.update(x);
21
+ }
22
+ })();
23
+ return this.el;
24
+ }
25
+ async unmount() {
26
+ this.el = void 0;
27
+ await this.inner.unmount();
28
+ }
29
+ update(x) {
30
+ if (this.el)
31
+ this.inner.update(x);
32
+ }
33
+ }
34
+ const $asyncA = async (src, comp, path) => {
35
+ const attribs = {};
36
+ const setter = defSetterUnsafe(path);
37
+ for await (let x of src) {
38
+ if (comp.el)
39
+ $attribs(comp.el, setter(attribs, x));
40
+ }
41
+ };
42
+ export {
43
+ $Async,
44
+ $async,
45
+ $asyncA
46
+ };
package/compile.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { isArray } from "@thi.ng/checks/is-array";
2
+ import { isAsyncIterable } from "@thi.ng/checks/is-async-iterable";
2
3
  import { isPlainObject } from "@thi.ng/checks/is-plain-object";
3
4
  import { isSubscribable } from "@thi.ng/rstream/checks";
5
+ import { $async, $asyncA } from "./async.js";
4
6
  import { isComponent, isElement } from "./checks.js";
5
7
  import { $el, $remove, $tree } from "./dom.js";
6
8
  import { $SubA, $sub } from "./sub.js";
7
9
  import { $wrapEl, $wrapText } from "./wrap.js";
8
- 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);
10
+ const $compile = (tree) => isArray(tree) ? isComplexComponent(tree) ? complexComponent(tree) : basicComponent(tree) : isComponent(tree) ? tree : isSubscribable(tree) ? $sub(tree, "span") : isAsyncIterable(tree) ? $async(tree, "span") : tree instanceof Element ? $wrapEl(tree) : $wrapText("span", null, tree);
9
11
  const walk = (f, x, path = []) => {
10
12
  if (isPlainObject(x)) {
11
13
  for (const k in x) {
@@ -26,13 +28,17 @@ const isComplexComponent = (x) => {
26
28
  return true;
27
29
  }
28
30
  }
29
- return isSubscribable(x) || isComponent(x) || isElement(x);
31
+ return isSubscribable(x) || isAsyncIterable(x) || isComponent(x) || isElement(x);
30
32
  };
31
33
  const complexComponent = (tree) => ({
32
34
  async mount(parent, index = -1) {
33
35
  this.subs = [];
34
36
  walk((x, path) => {
35
- isSubscribable(x) && this.subs.push(x.subscribe(new $SubA(this, path)));
37
+ if (isSubscribable(x)) {
38
+ this.subs.push(x.subscribe(new $SubA(this, path)));
39
+ } else if (isAsyncIterable(x)) {
40
+ $asyncA(x, this, path);
41
+ }
36
42
  }, tree[1]);
37
43
  this.children = [];
38
44
  this.el = $el(tree[0], tree[1], null, parent, index);
package/component.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { MaybeDeref } from "@thi.ng/api";
1
+ import type { Maybe, MaybeDeref } from "@thi.ng/api";
2
2
  import type { IComponent, NumOrElement } from "./api.js";
3
3
  /**
4
4
  * Abstract base class / {@link IComponent} implementation. Provides
@@ -20,7 +20,7 @@ export declare abstract class Component<T = any> implements IComponent<T> {
20
20
  * @param parent
21
21
  * @param idx
22
22
  */
23
- $el(tag: string, attribs?: any, body?: any, parent?: ParentNode | undefined, idx?: NumOrElement): Element;
23
+ $el(tag: string, attribs?: any, body?: any, parent?: Maybe<ParentNode>, idx?: NumOrElement): Element;
24
24
  /**
25
25
  * Syntax sugar for {@link $comment}, creates a new comment DOM node using
26
26
  * this component's {@link IComponent.el} as default `parent`.
@@ -29,7 +29,7 @@ export declare abstract class Component<T = any> implements IComponent<T> {
29
29
  * @param parent
30
30
  * @param idx
31
31
  */
32
- $comment(body: string | string[], parent?: ParentNode | undefined, idx?: NumOrElement): Comment;
32
+ $comment(body: string | string[], parent?: Maybe<ParentNode>, idx?: NumOrElement): Comment;
33
33
  /**
34
34
  * Syntax sugar for {@link $clear}, using this component's
35
35
  * {@link IComponent.el} as default element to clear.
package/dom.js CHANGED
@@ -100,10 +100,17 @@ const $attribs = (el, attribs) => {
100
100
  }
101
101
  return el;
102
102
  };
103
+ const __setterCache = {};
104
+ const getproto = Object.getPrototypeOf;
105
+ const getdesc = Object.getOwnPropertyDescriptor;
106
+ const __desc = (proto, prop) => proto ? getdesc(proto, prop) ?? __desc(getproto(proto), prop) : void 0;
107
+ const __setter = (el, prop) => {
108
+ const key = `${el.namespaceURI}/${el.tagName}#${prop}`;
109
+ return __setterCache[key] ?? (__setterCache[key] = __desc(getproto(el), prop)?.set ?? false);
110
+ };
103
111
  const setAttrib = (el, id, val, attribs) => {
104
112
  implementsFunction(val, "deref") && (val = val.deref());
105
- const isListener = id.startsWith("on");
106
- if (isListener) {
113
+ if (id.startsWith("on")) {
107
114
  if (isString(val)) {
108
115
  el.setAttribute(id, val);
109
116
  } else {
@@ -130,27 +137,11 @@ const setAttrib = (el, id, val, attribs) => {
130
137
  case "prefix":
131
138
  el.setAttribute(id, isString(val) ? val : formatPrefixes(val));
132
139
  break;
133
- case "accessKey":
134
- case "autocapitalize":
135
- case "checked":
136
- case "contentEditable":
137
- case "dir":
138
- case "draggable":
139
- case "hidden":
140
- case "id":
141
- case "indeterminate":
142
- case "lang":
143
- case "scrollLeft":
144
- case "scrollTop":
145
- case "selectionEnd":
146
- case "selectionStart":
147
- case "slot":
148
- case "spellcheck":
149
- case "tabIndex":
150
- case "title":
151
- el[id] = val;
152
- break;
153
140
  default: {
141
+ const setter = __setter(el, id);
142
+ if (setter && val != null) {
143
+ return setter.call(el, val);
144
+ }
154
145
  const idx = id.indexOf(":");
155
146
  if (idx < 0) {
156
147
  val === false || val == null ? el.removeAttribute(id) : el.setAttribute(id, val === true ? id : val);
package/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./api.js";
2
+ export * from "./async.js";
2
3
  export * from "./checks.js";
3
4
  export * from "./compile.js";
4
5
  export * from "./component.js";
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./api.js";
2
+ export * from "./async.js";
2
3
  export * from "./checks.js";
3
4
  export * from "./compile.js";
4
5
  export * from "./component.js";
package/lazy.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Fn0 } from "@thi.ng/api";
1
+ import type { Fn0, Maybe } from "@thi.ng/api";
2
2
  import type { ComponentLike, IComponent, NumOrElement } from "./api.js";
3
3
  import { Component } from "./component.js";
4
4
  /**
@@ -22,10 +22,10 @@ export declare class $Lazy extends Component {
22
22
  protected attribs: any;
23
23
  protected ctor: Fn0<Promise<ComponentLike>>;
24
24
  protected opts?: IntersectionObserverInit | undefined;
25
- protected observer: IntersectionObserver | undefined;
26
- protected inner: IComponent | undefined;
25
+ protected observer: Maybe<IntersectionObserver>;
26
+ protected inner: Maybe<IComponent>;
27
27
  constructor(tag: string, attribs: any, ctor: Fn0<Promise<ComponentLike>>, opts?: IntersectionObserverInit | undefined);
28
- mount(parent: ParentNode, index?: NumOrElement | undefined): Promise<Element>;
28
+ mount(parent: ParentNode, index?: NumOrElement): Promise<Element>;
29
29
  unmount(): Promise<void>;
30
30
  }
31
31
  //# sourceMappingURL=lazy.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/rdom",
3
- "version": "1.1.22",
3
+ "version": "1.3.0",
4
4
  "description": "Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -37,14 +37,14 @@
37
37
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@thi.ng/api": "^8.10.0",
41
- "@thi.ng/checks": "^3.6.0",
42
- "@thi.ng/errors": "^2.5.3",
43
- "@thi.ng/hiccup": "^5.1.27",
44
- "@thi.ng/paths": "^5.1.77",
45
- "@thi.ng/prefixes": "^2.3.15",
46
- "@thi.ng/rstream": "^8.3.20",
47
- "@thi.ng/strings": "^3.7.29"
40
+ "@thi.ng/api": "^8.11.0",
41
+ "@thi.ng/checks": "^3.6.2",
42
+ "@thi.ng/errors": "^2.5.5",
43
+ "@thi.ng/hiccup": "^5.1.29",
44
+ "@thi.ng/paths": "^5.1.79",
45
+ "@thi.ng/prefixes": "^2.3.17",
46
+ "@thi.ng/rstream": "^8.4.1",
47
+ "@thi.ng/strings": "^3.7.31"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@microsoft/api-extractor": "^7.43.0",
@@ -87,6 +87,9 @@
87
87
  "./api": {
88
88
  "default": "./api.js"
89
89
  },
90
+ "./async": {
91
+ "default": "./async.js"
92
+ },
90
93
  "./checks": {
91
94
  "default": "./checks.js"
92
95
  },
@@ -143,5 +146,5 @@
143
146
  ],
144
147
  "year": 2020
145
148
  },
146
- "gitHead": "85ac4bd4d6d89f8e3689e2863d5bea0cecdb371c\n"
149
+ "gitHead": "8339d05ecc857e529c7325a9839c0063b89e728d\n"
147
150
  }
package/sub.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Fn2, Path } from "@thi.ng/api";
1
+ import type { Fn2, Maybe, Path } from "@thi.ng/api";
2
2
  import type { ISubscribable } from "@thi.ng/rstream";
3
3
  import { Subscription } from "@thi.ng/rstream/subscription";
4
4
  import type { IComponent, IMountWithState, NumOrElement } from "./api.js";
@@ -42,9 +42,9 @@ export declare function $sub(src: ISubscribable<any>, tag: string, attribs?: any
42
42
  */
43
43
  export declare const $subWithID: <T>(src: ISubscribable<T>, inner: IMountWithState<T>, id: string) => IComponent<T>;
44
44
  export declare class $Sub<T = any> extends Subscription<T, T> {
45
- protected inner: IMountWithState<T | undefined>;
45
+ protected inner: IMountWithState<Maybe<T>>;
46
46
  el?: Element;
47
- constructor(inner: IMountWithState<T | undefined>, id?: string);
47
+ constructor(inner: IMountWithState<Maybe<T>>, id?: string);
48
48
  mount(parent: ParentNode, index?: NumOrElement): Promise<Element>;
49
49
  unmount(): Promise<void>;
50
50
  update(x: T): void;
package/wrap.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import type { IComponent, IMountWithState } from "./api.js";
2
+ export interface WrappedComponent<T> extends IMountWithState<T> {
3
+ inner: IComponent<any>;
4
+ }
2
5
  /**
3
6
  * Returns a component wrapper for a single DOM element whose TEXT body can be
4
7
  * later updated/replaced via `.update()`, similarly to setting `.innerText`.
@@ -7,7 +10,7 @@ import type { IComponent, IMountWithState } from "./api.js";
7
10
  * @param attribs - element attribs
8
11
  * @param body - optional initial body
9
12
  */
10
- export declare const $wrapText: (tag: string, attribs?: any, body?: any) => IMountWithState<any>;
13
+ export declare const $wrapText: (tag: string, attribs?: any, body?: any) => WrappedComponent<any>;
11
14
  /**
12
15
  * Returns a component wrapper for a single DOM element whose HTML body can be
13
16
  * later updated/replaced via `.update()`, similarly to setting `.innerHTML`.
@@ -35,7 +38,7 @@ export declare const $wrapText: (tag: string, attribs?: any, body?: any) => IMou
35
38
  * @param attribs - element attribs
36
39
  * @param body - optional initial body
37
40
  */
38
- export declare const $wrapHtml: (tag: string, attribs?: any, body?: import("@thi.ng/api").MaybeDeref<string> | undefined) => IMountWithState<import("@thi.ng/api").MaybeDeref<string>>;
41
+ export declare const $wrapHtml: (tag: string, attribs?: any, body?: import("@thi.ng/api").MaybeDeref<string> | undefined) => WrappedComponent<import("@thi.ng/api").MaybeDeref<string>>;
39
42
  /**
40
43
  * {@link IComponent} wrapper for an existing DOM element. When mounted, the
41
44
  * given element will be (re)attached to the parent node provided at that time.
package/wrap.js CHANGED
@@ -1,13 +1,14 @@
1
- import { $addChild, $el, $html, $remove, $text } from "./dom.js";
1
+ import { $compile } from "./compile.js";
2
+ import { $addChild, $html, $remove, $text } from "./dom.js";
2
3
  const wrapper = (update) => (tag, attribs, body) => ({
3
- el: void 0,
4
4
  async mount(parent, index, state) {
5
- this.el = $el(tag, attribs, null, parent, index);
5
+ this.inner = $compile([tag, attribs]);
6
+ this.el = await this.inner.mount(parent, index);
6
7
  update(this.el, state != null ? state : body);
7
8
  return this.el;
8
9
  },
9
10
  async unmount() {
10
- $remove(this.el);
11
+ this.inner.unmount();
11
12
  this.el = void 0;
12
13
  },
13
14
  update(body2) {