@brandup/ui 2.0.1 → 2.0.3
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/README.md +12 -7
- package/dist/cjs/constants.js +14 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/dom/bind-each.js +90 -0
- package/dist/cjs/dom/bind-each.js.map +1 -0
- package/dist/cjs/dom/bind.js +29 -0
- package/dist/cjs/dom/bind.js.map +1 -0
- package/dist/cjs/dom/binding-cleanup.js +162 -0
- package/dist/cjs/dom/binding-cleanup.js.map +1 -0
- package/dist/cjs/dom/dom.js +184 -0
- package/dist/cjs/dom/dom.js.map +1 -0
- package/dist/cjs/dom/helpers.js +33 -0
- package/dist/cjs/dom/helpers.js.map +1 -0
- package/dist/cjs/dom/index.js +14 -0
- package/dist/cjs/dom/index.js.map +1 -0
- package/dist/cjs/dom/tag.js +207 -0
- package/dist/cjs/dom/tag.js.map +1 -0
- package/dist/cjs/element.js +265 -0
- package/dist/cjs/element.js.map +1 -0
- package/dist/cjs/events.js +204 -0
- package/dist/cjs/events.js.map +1 -0
- package/dist/cjs/ext.js +20 -0
- package/dist/cjs/ext.js.map +1 -0
- package/dist/cjs/index.js +40 -1455
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/reactive/computed.js +36 -0
- package/dist/cjs/reactive/computed.js.map +1 -0
- package/dist/cjs/reactive/effect.js +197 -0
- package/dist/cjs/reactive/effect.js.map +1 -0
- package/dist/cjs/reactive/reactive.js +106 -0
- package/dist/cjs/reactive/reactive.js.map +1 -0
- package/dist/mjs/constants.js +10 -0
- package/dist/mjs/constants.js.map +1 -0
- package/dist/mjs/dom/bind-each.js +86 -0
- package/dist/mjs/dom/bind-each.js.map +1 -0
- package/dist/mjs/dom/bind.js +26 -0
- package/dist/mjs/dom/bind.js.map +1 -0
- package/dist/mjs/dom/binding-cleanup.js +156 -0
- package/dist/mjs/dom/binding-cleanup.js.map +1 -0
- package/dist/mjs/dom/dom.js +169 -0
- package/dist/mjs/dom/dom.js.map +1 -0
- package/dist/mjs/dom/helpers.js +29 -0
- package/dist/mjs/dom/helpers.js.map +1 -0
- package/dist/mjs/dom/index.js +12 -0
- package/dist/mjs/dom/index.js.map +1 -0
- package/dist/mjs/dom/tag.js +203 -0
- package/dist/mjs/dom/tag.js.map +1 -0
- package/dist/mjs/element.js +260 -0
- package/dist/mjs/element.js.map +1 -0
- package/dist/mjs/events.js +202 -0
- package/dist/mjs/events.js.map +1 -0
- package/dist/mjs/ext.js +18 -0
- package/dist/mjs/ext.js.map +1 -0
- package/dist/mjs/index.js +11 -1431
- package/dist/mjs/index.js.map +1 -1
- package/dist/mjs/reactive/computed.js +33 -0
- package/dist/mjs/reactive/computed.js.map +1 -0
- package/dist/mjs/reactive/effect.js +187 -0
- package/dist/mjs/reactive/effect.js.map +1 -0
- package/dist/mjs/reactive/reactive.js +102 -0
- package/dist/mjs/reactive/reactive.js.map +1 -0
- package/dist/types.d.ts +18 -2
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -59,9 +59,12 @@ class MyWidget extends UIElement {
|
|
|
59
59
|
}
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
The `HTMLElement.prototype.ui` extension lets you bind a `UIElement` through a factory and returns the element itself:
|
|
62
|
+
The `HTMLElement.prototype.ui` extension lets you bind a `UIElement` through a factory and returns the element itself. It is opt-in (not installed on import) — call `enableElementExtensions()` once before using it:
|
|
63
63
|
|
|
64
64
|
```ts
|
|
65
|
+
import { enableElementExtensions } from "@brandup/ui";
|
|
66
|
+
|
|
67
|
+
enableElementExtensions();
|
|
65
68
|
document.getElementById("widget")!.ui(elem => new MyWidget(elem));
|
|
66
69
|
```
|
|
67
70
|
|
|
@@ -122,7 +125,7 @@ this.registerCommand(
|
|
|
122
125
|
);
|
|
123
126
|
```
|
|
124
127
|
|
|
125
|
-
Commands are triggered by the `click` event. The handler is looked up by walking up the DOM from the element with the `data-command` attribute to the nearest `UIElement` in which that command is registered.
|
|
128
|
+
Commands are triggered by the `click` event. The handler is looked up by walking up the DOM from the element with the `data-command` attribute to the nearest `UIElement` in which that command is registered. The global click listener must be enabled once via `initUICommands()` — `Application` does this automatically (see [Command click handler](#command-click-handler)).
|
|
126
129
|
|
|
127
130
|
While an asynchronous command is running, the **executing** CSS class is added to the target element (and removed once the `Promise` settles).
|
|
128
131
|
|
|
@@ -246,14 +249,16 @@ elem.remove(); // destroy() fires automatically on next microtask
|
|
|
246
249
|
|
|
247
250
|
If the element was never connected to the document (e.g. built in memory and then discarded), auto-destroy does **not** fire — only mounted-then-removed elements are watched.
|
|
248
251
|
|
|
249
|
-
###
|
|
252
|
+
### Command click handler
|
|
250
253
|
|
|
251
|
-
|
|
254
|
+
Commands are dispatched by a single global `click` listener on `window`. It is **not** registered automatically on import (so the command system can be tree-shaken away when unused) — call `initUICommands()` once during startup. It is idempotent and a no-op without a DOM. `Application.run()` (from `@brandup/ui-app`) calls it for you, so you only need it when using `UIElement` commands **without** an `Application`:
|
|
252
255
|
|
|
253
256
|
```ts
|
|
254
|
-
import { destroyUI } from "@brandup/ui";
|
|
257
|
+
import { initUICommands, destroyUI } from "@brandup/ui";
|
|
255
258
|
|
|
256
|
-
|
|
259
|
+
initUICommands(); // enable command handling
|
|
260
|
+
// ...
|
|
261
|
+
destroyUI(); // remove the listener on app teardown or HMR disposal
|
|
257
262
|
```
|
|
258
263
|
|
|
259
264
|
## DOM helpers
|
|
@@ -462,7 +467,7 @@ user => DOM.tag("li", null, bind(() => user.name))
|
|
|
462
467
|
user => DOM.tag("li", null, user.name)
|
|
463
468
|
```
|
|
464
469
|
|
|
465
|
-
The binding stops automatically
|
|
470
|
+
The binding stops automatically once its rendered nodes leave the document — whether the container is removed or just cleared/replaced (same lifecycle as `bind`).
|
|
466
471
|
|
|
467
472
|
### Disposal
|
|
468
473
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/** Default constant values used across the library. */
|
|
6
|
+
const constants = {
|
|
7
|
+
ElemAttributeName: "uiElement",
|
|
8
|
+
ElemPropertyName: "uielement",
|
|
9
|
+
CommandAttributeName: "command",
|
|
10
|
+
CommandExecutingCssClassName: "executing"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
exports.default = constants;
|
|
14
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../source/constants.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAYA;AACA,MAAM,SAAS,GAAgB;AAC9B,IAAA,iBAAiB,EAAE,WAAW;AAC9B,IAAA,gBAAgB,EAAE,WAAW;AAC7B,IAAA,oBAAoB,EAAE,SAAS;AAC/B,IAAA,4BAA4B,EAAE;;;;;"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var effect = require('../reactive/effect.js');
|
|
4
|
+
var bindingCleanup = require('./binding-cleanup.js');
|
|
5
|
+
|
|
6
|
+
/** A keyed-list binding produced by {@link bindEach}; handled by `appendChild` in `tag.ts`. */
|
|
7
|
+
class BindingEach {
|
|
8
|
+
getItems;
|
|
9
|
+
getKey;
|
|
10
|
+
render;
|
|
11
|
+
constructor(getItems, getKey, render) {
|
|
12
|
+
this.getItems = getItems;
|
|
13
|
+
this.getKey = getKey;
|
|
14
|
+
this.render = render;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a reactive keyed-list binding for use as a {@link tag} child.
|
|
19
|
+
*
|
|
20
|
+
* The `getItems` function is tracked; the list is reconciled whenever the array
|
|
21
|
+
* changes (push, splice, reassignment, etc.). Items are matched by `getKey` so
|
|
22
|
+
* unchanged nodes stay in place — only new, removed, or reordered nodes are touched.
|
|
23
|
+
*
|
|
24
|
+
* `render` is called **once per key** and runs **untracked**. Use `bind()` inside
|
|
25
|
+
* the render function for item properties that should update independently:
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ The item object passed to `render` is captured at first render for that key.
|
|
28
|
+
* Mutate items in place (`item.name = "..."`) so `bind()` reactions fire. Replacing
|
|
29
|
+
* the array with **new objects that reuse the same keys** keeps the cached node bound
|
|
30
|
+
* to the *old* object, so per-item `bind()`s won't update — change the key, or mutate
|
|
31
|
+
* the existing item, when its identity should change.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* DOM.tag("ul", null,
|
|
35
|
+
* bindEach(() => state.users, u => u.id, u =>
|
|
36
|
+
* DOM.tag("li", null, bind(() => u.name))
|
|
37
|
+
* )
|
|
38
|
+
* );
|
|
39
|
+
*/
|
|
40
|
+
function bindEach(getItems, getKey, render) {
|
|
41
|
+
return new BindingEach(getItems, getKey, render);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Mount a {@link BindingEach} into `container` and start tracking.
|
|
45
|
+
* Called by `appendChild` in `tag.ts`; not intended for direct use.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
function appendBindingEach(container, binding) {
|
|
49
|
+
const nodes = new Map();
|
|
50
|
+
// Anchor comment marks the start of the managed region inside the container.
|
|
51
|
+
// Using an anchor (rather than container.firstChild) lets other children coexist.
|
|
52
|
+
const anchor = document.createComment("");
|
|
53
|
+
container.append(anchor);
|
|
54
|
+
const eff = effect.effect(() => {
|
|
55
|
+
const items = binding.getItems();
|
|
56
|
+
const nextKeys = new Set();
|
|
57
|
+
for (let i = 0; i < items.length; i++)
|
|
58
|
+
nextKeys.add(binding.getKey(items[i], i));
|
|
59
|
+
// Remove nodes whose keys are no longer present
|
|
60
|
+
for (const [key, node] of nodes) {
|
|
61
|
+
if (!nextKeys.has(key)) {
|
|
62
|
+
node.remove();
|
|
63
|
+
nodes.delete(key);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Insert new nodes and restore order in a single pass starting after the anchor.
|
|
67
|
+
// If the node is already at the expected position we advance; otherwise insertBefore moves it.
|
|
68
|
+
let cursor = anchor.nextSibling;
|
|
69
|
+
for (let i = 0; i < items.length; i++) {
|
|
70
|
+
const key = binding.getKey(items[i], i);
|
|
71
|
+
let node = nodes.get(key);
|
|
72
|
+
if (!node) {
|
|
73
|
+
// Render untracked so item-property reads don't create dependencies on
|
|
74
|
+
// this list effect — use bind() inside render for fine-grained updates.
|
|
75
|
+
node = effect.untrack(() => binding.render(items[i]));
|
|
76
|
+
nodes.set(key, node);
|
|
77
|
+
}
|
|
78
|
+
if (cursor !== node)
|
|
79
|
+
container.insertBefore(node, cursor);
|
|
80
|
+
else
|
|
81
|
+
cursor = cursor.nextSibling;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
bindingCleanup.autoDisposeBinding(container, () => anchor, eff);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
exports.BindingEach = BindingEach;
|
|
88
|
+
exports.appendBindingEach = appendBindingEach;
|
|
89
|
+
exports.bindEach = bindEach;
|
|
90
|
+
//# sourceMappingURL=bind-each.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind-each.js","sources":["../../../../source/dom/bind-each.ts"],"sourcesContent":[null],"names":["effect","untrack","autoDisposeBinding"],"mappings":";;;;;AAGA;MACa,WAAW,CAAA;AAEb,IAAA,QAAA;AACA,IAAA,MAAA;AACA,IAAA,MAAA;AAHV,IAAA,WAAA,CACU,QAAmB,EACnB,MAAmD,EACnD,MAA4B,EAAA;QAF5B,IAAA,CAAA,QAAQ,GAAR,QAAQ;QACR,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,MAAM,GAAN,MAAM;IACZ;AACJ;AAED;;;;;;;;;;;;;;;;;;;;;;AAsBG;SACa,QAAQ,CACvB,QAAmB,EACnB,MAAmD,EACnD,MAA4B,EAAA;IAE5B,OAAO,IAAI,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;AACjD;AAEA;;;;AAIG;AACG,SAAU,iBAAiB,CAAI,SAAsB,EAAE,OAAuB,EAAA;AACnF,IAAA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B;;;IAIjD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;AACzC,IAAA,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;AAExB,IAAA,MAAM,GAAG,GAAGA,aAAM,CAAC,MAAK;AACvB,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE;AAEhC,QAAA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB;AAC3C,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;AACpC,YAAA,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;;QAG1C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE;YAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBACvB,IAAI,CAAC,MAAM,EAAE;AACb,gBAAA,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;YAClB;QACD;;;AAIA,QAAA,IAAI,MAAM,GAAqB,MAAM,CAAC,WAAW;AACjD,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACtC,YAAA,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvC,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAEzB,IAAI,CAAC,IAAI,EAAE;;;AAGV,gBAAA,IAAI,GAAGC,cAAO,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,gBAAA,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;YACrB;YAEA,IAAI,MAAM,KAAK,IAAI;AAClB,gBAAA,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;;AAEpC,gBAAA,MAAM,GAAG,MAAM,CAAC,WAAW;QAC7B;AACD,IAAA,CAAC,CAAC;IAEFC,iCAAkB,CAAC,SAAS,EAAE,MAAM,MAAM,EAAE,GAAG,CAAC;AACjD;;;;;;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A reactive binding for use as a {@link tag} child. Its `compute` function is
|
|
5
|
+
* re-evaluated and re-rendered whenever the reactive state it reads changes.
|
|
6
|
+
*/
|
|
7
|
+
class Binding {
|
|
8
|
+
compute;
|
|
9
|
+
constructor(compute) {
|
|
10
|
+
this.compute = compute;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a reactive {@link Binding} that can be passed as a `tag` child. The
|
|
15
|
+
* compute function is tracked: it re-runs (updating the DOM in place) whenever
|
|
16
|
+
* any reactive value it reads changes.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const state = reactive({ name: "Alice" });
|
|
20
|
+
* DOM.tag("div", null, "Hi, ", bind(() => state.name));
|
|
21
|
+
* state.name = "Bob"; // the text updates in place
|
|
22
|
+
*/
|
|
23
|
+
function bind(compute) {
|
|
24
|
+
return new Binding(compute);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.Binding = Binding;
|
|
28
|
+
exports.bind = bind;
|
|
29
|
+
//# sourceMappingURL=bind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind.js","sources":["../../../../source/dom/bind.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAKA;;;AAGG;MACU,OAAO,CAAA;AACE,IAAA,OAAA;AAArB,IAAA,WAAA,CAAqB,OAA2B,EAAA;QAA3B,IAAA,CAAA,OAAO,GAAP,OAAO;IAAwB;AACpD;AAED;;;;;;;;;AASG;AACG,SAAU,IAAI,CAAC,OAA2B,EAAA;AAC/C,IAAA,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;AAC5B;;;;;"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// UIElements are located via the data attribute `UIElement.setElement` already sets
|
|
4
|
+
// (`elem.dataset.uiElement` → `data-ui-element`), so no extra marker is needed for them.
|
|
5
|
+
const UIELEM_SELECTOR = "[data-ui-element]";
|
|
6
|
+
// Marker placed on every element a reactive binding renders into, so a removed
|
|
7
|
+
// subtree (or a cleared container) can be queried for affected bindings.
|
|
8
|
+
const BINDING_ATTR = "data-bui-binding";
|
|
9
|
+
const BINDING_SELECTOR = "[data-bui-binding]";
|
|
10
|
+
// node → UIElement auto-destroy entry
|
|
11
|
+
const trackedElements = new Map();
|
|
12
|
+
// container element → bindings rendered into it (one marker per container)
|
|
13
|
+
const bindingsByContainer = new Map();
|
|
14
|
+
let observer;
|
|
15
|
+
function ensureObserver() {
|
|
16
|
+
if (typeof MutationObserver !== "undefined" && !observer) {
|
|
17
|
+
observer = new MutationObserver(onMutations);
|
|
18
|
+
observer.observe(document, { childList: true, subtree: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function disconnectIfEmpty() {
|
|
22
|
+
if (trackedElements.size === 0 && bindingsByContainer.size === 0 && observer) {
|
|
23
|
+
observer.disconnect();
|
|
24
|
+
observer = undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* React only to *removed* nodes (insertions never disconnect anything). Two cases:
|
|
29
|
+
* - a removed element subtree → dispose the tracked UIElements/bindings inside it;
|
|
30
|
+
* - children removed from a surviving container (e.g. `container.innerHTML = ""`) →
|
|
31
|
+
* re-check the bindings rendered directly into that container.
|
|
32
|
+
* Work stays proportional to what changed, not to the total number tracked.
|
|
33
|
+
*/
|
|
34
|
+
function onMutations(mutations) {
|
|
35
|
+
for (const mutation of mutations) {
|
|
36
|
+
mutation.removedNodes.forEach(node => {
|
|
37
|
+
if (node instanceof HTMLElement)
|
|
38
|
+
disposeDisconnectedWithin(node);
|
|
39
|
+
});
|
|
40
|
+
// A binding's managed node (a text/comment) can be removed while its container
|
|
41
|
+
// stays connected (a cleared/replaced container). The container itself is then
|
|
42
|
+
// the mutation target, not a removed node, so check its bindings here.
|
|
43
|
+
const target = mutation.target;
|
|
44
|
+
if (mutation.removedNodes.length && target instanceof HTMLElement && target.hasAttribute(BINDING_ATTR))
|
|
45
|
+
disposeDisconnectedBindings(target);
|
|
46
|
+
}
|
|
47
|
+
disconnectIfEmpty();
|
|
48
|
+
}
|
|
49
|
+
/** Apply `fn` to `root` itself (when it matches) and every descendant matching `selector`. */
|
|
50
|
+
function forEachSelfAndMatches(root, selector, fn) {
|
|
51
|
+
if (root.matches(selector))
|
|
52
|
+
fn(root);
|
|
53
|
+
root.querySelectorAll(selector).forEach(el => fn(el));
|
|
54
|
+
}
|
|
55
|
+
/** Destroy/stop tracked entries inside a removed subtree that are no longer in the document. */
|
|
56
|
+
function disposeDisconnectedWithin(removed) {
|
|
57
|
+
// UIElements first: destroying one cascades to its nested UIElements and bindings.
|
|
58
|
+
forEachSelfAndMatches(removed, UIELEM_SELECTOR, el => {
|
|
59
|
+
// `isConnected` guards against moves (removed from one place, re-inserted in another).
|
|
60
|
+
if (!el.isConnected) {
|
|
61
|
+
const entry = trackedElements.get(el);
|
|
62
|
+
if (entry)
|
|
63
|
+
entry.destroy(); // destroy() untracks itself, cascades, and disposes its bindings
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
forEachSelfAndMatches(removed, BINDING_SELECTOR, disposeDisconnectedBindings);
|
|
67
|
+
}
|
|
68
|
+
/** Stop the bindings of `container` whose managed node has left the document. */
|
|
69
|
+
function disposeDisconnectedBindings(container) {
|
|
70
|
+
const set = bindingsByContainer.get(container);
|
|
71
|
+
if (!set)
|
|
72
|
+
return;
|
|
73
|
+
for (const binding of [...set]) {
|
|
74
|
+
if (!binding.getNode().isConnected) {
|
|
75
|
+
set.delete(binding);
|
|
76
|
+
binding.effect.stop();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!set.size) {
|
|
80
|
+
bindingsByContainer.delete(container);
|
|
81
|
+
container.removeAttribute(BINDING_ATTR);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Stop and forget every binding of `container`, unconditionally (owner is being destroyed). */
|
|
85
|
+
function stopAllBindings(container) {
|
|
86
|
+
const set = bindingsByContainer.get(container);
|
|
87
|
+
if (!set)
|
|
88
|
+
return;
|
|
89
|
+
bindingsByContainer.delete(container);
|
|
90
|
+
container.removeAttribute(BINDING_ATTR);
|
|
91
|
+
set.forEach(binding => binding.effect.stop());
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Track a binding so its reactive effect is stopped automatically once its managed node has
|
|
95
|
+
* been mounted and then removed from the document (via a shared `MutationObserver`), and so
|
|
96
|
+
* {@link disposeBindingsWithin} can stop it when its owning UIElement is destroyed.
|
|
97
|
+
*
|
|
98
|
+
* @param container Element the binding renders into (indexed/marked for subtree queries).
|
|
99
|
+
* @param getNode Returns the binding's current managed node — its connectivity drives disposal.
|
|
100
|
+
* @param effect The reactive effect to stop on disposal.
|
|
101
|
+
*/
|
|
102
|
+
function autoDisposeBinding(container, getNode, effect) {
|
|
103
|
+
let set = bindingsByContainer.get(container);
|
|
104
|
+
if (!set) {
|
|
105
|
+
bindingsByContainer.set(container, set = new Set());
|
|
106
|
+
container.setAttribute(BINDING_ATTR, "");
|
|
107
|
+
}
|
|
108
|
+
set.add({ getNode, container, effect });
|
|
109
|
+
ensureObserver();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Register a `UIElement`'s DOM node for auto-destroy: once the node has been mounted
|
|
113
|
+
* into the document and then removed, `destroy` is called automatically.
|
|
114
|
+
* @internal — called by `UIElement.setElement`.
|
|
115
|
+
*/
|
|
116
|
+
function trackAutoDestroy(node, destroy) {
|
|
117
|
+
trackedElements.set(node, { node, destroy });
|
|
118
|
+
ensureObserver();
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Remove a node from auto-destroy tracking (called when `UIElement.destroy` is
|
|
122
|
+
* invoked explicitly so the entry does not linger).
|
|
123
|
+
* @internal — called by `UIElement.destroy`.
|
|
124
|
+
*/
|
|
125
|
+
function untrackAutoDestroy(node) {
|
|
126
|
+
trackedElements.delete(node);
|
|
127
|
+
disconnectIfEmpty();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Destroy every tracked `UIElement` nested within `root` (excluding `root` itself),
|
|
131
|
+
* deepest first. Located via the `data-ui-element` marker, so the cost is proportional
|
|
132
|
+
* to the subtree rather than to the total number of tracked elements.
|
|
133
|
+
* @internal — called by `UIElement.destroy`.
|
|
134
|
+
*/
|
|
135
|
+
function destroyUIElementsWithin(root) {
|
|
136
|
+
const victims = [];
|
|
137
|
+
root.querySelectorAll(UIELEM_SELECTOR).forEach(el => {
|
|
138
|
+
if (trackedElements.has(el))
|
|
139
|
+
victims.push(el);
|
|
140
|
+
});
|
|
141
|
+
// querySelectorAll yields document order (ancestors before descendants);
|
|
142
|
+
// iterate in reverse so deeper / nested elements are destroyed first.
|
|
143
|
+
for (let i = victims.length - 1; i >= 0; i--)
|
|
144
|
+
trackedElements.get(victims[i])?.destroy();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Stop and forget every tracked binding rendered within `root` (used when a UIElement is
|
|
148
|
+
* destroyed). Unlike the observer path this is unconditional — it does not check connectivity,
|
|
149
|
+
* because the owner is being torn down.
|
|
150
|
+
*/
|
|
151
|
+
function disposeBindingsWithin(root) {
|
|
152
|
+
if (root instanceof HTMLElement)
|
|
153
|
+
forEachSelfAndMatches(root, BINDING_SELECTOR, stopAllBindings);
|
|
154
|
+
disconnectIfEmpty();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
exports.autoDisposeBinding = autoDisposeBinding;
|
|
158
|
+
exports.destroyUIElementsWithin = destroyUIElementsWithin;
|
|
159
|
+
exports.disposeBindingsWithin = disposeBindingsWithin;
|
|
160
|
+
exports.trackAutoDestroy = trackAutoDestroy;
|
|
161
|
+
exports.untrackAutoDestroy = untrackAutoDestroy;
|
|
162
|
+
//# sourceMappingURL=binding-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binding-cleanup.js","sources":["../../../../source/dom/binding-cleanup.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var helpers = require('./helpers.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Finds an element by its `id` within the whole document.
|
|
7
|
+
* @param id The element id to look up.
|
|
8
|
+
* @returns The matching element, or `null` if none exists.
|
|
9
|
+
*/
|
|
10
|
+
function getById(id) {
|
|
11
|
+
return document.getElementById(id);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns the first descendant of `container` that has the given class.
|
|
15
|
+
* @param container Element to search within.
|
|
16
|
+
* @param className Single class name to match.
|
|
17
|
+
* @returns The first matching element, or `null` if none found.
|
|
18
|
+
*/
|
|
19
|
+
function getByClass(container, className) {
|
|
20
|
+
const elements = container.getElementsByClassName(className);
|
|
21
|
+
if (elements.length === 0)
|
|
22
|
+
return null;
|
|
23
|
+
return elements.item(0);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the first element in the document with the given `name` attribute.
|
|
27
|
+
* @param name The `name` attribute value to look up.
|
|
28
|
+
* @returns The first matching element, or `null` if none found.
|
|
29
|
+
*/
|
|
30
|
+
function getByName(name) {
|
|
31
|
+
const elements = document.getElementsByName(name);
|
|
32
|
+
if (elements.length === 0)
|
|
33
|
+
return null;
|
|
34
|
+
return elements.item(0);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Returns the first descendant of `container` with the given tag name.
|
|
38
|
+
* @param container Element to search within.
|
|
39
|
+
* @param tagName Tag name to match (e.g. `"input"`).
|
|
40
|
+
* @returns The first matching element, or `null` if none found.
|
|
41
|
+
*/
|
|
42
|
+
function getElementByTagName(container, tagName) {
|
|
43
|
+
const elements = container.getElementsByTagName(tagName);
|
|
44
|
+
if (elements.length === 0)
|
|
45
|
+
return null;
|
|
46
|
+
return elements.item(0);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Returns all descendants of `container` with the given tag name as a live collection.
|
|
50
|
+
* @param container Element to search within.
|
|
51
|
+
* @param tagName Tag name to match (e.g. `"li"`).
|
|
52
|
+
* @returns A live `HTMLCollection` of matching elements.
|
|
53
|
+
*/
|
|
54
|
+
function getElementsByTagName(container, tagName) {
|
|
55
|
+
return container.getElementsByTagName(tagName);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the first descendant of `container` matching the CSS selector.
|
|
59
|
+
* @param container Element to search within.
|
|
60
|
+
* @param query CSS selector.
|
|
61
|
+
* @returns The first matching element, or `null` if none found.
|
|
62
|
+
*/
|
|
63
|
+
function queryElement(container, query) {
|
|
64
|
+
return container.querySelector(query);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns all descendants of `container` matching the CSS selector.
|
|
68
|
+
* @param container Element to search within.
|
|
69
|
+
* @param query CSS selector.
|
|
70
|
+
* @returns A static `NodeList` of matching elements.
|
|
71
|
+
*/
|
|
72
|
+
function queryElements(container, query) {
|
|
73
|
+
return container.querySelectorAll(query);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Walks forward through the following siblings of `current` and returns the first one that has the given class.
|
|
77
|
+
* @param current Element to start from.
|
|
78
|
+
* @param className Class name to match.
|
|
79
|
+
* @returns The first matching following sibling, or `null` if none found.
|
|
80
|
+
*/
|
|
81
|
+
function nextElementByClass(current, className) {
|
|
82
|
+
let elem = current.nextSibling;
|
|
83
|
+
while (elem) {
|
|
84
|
+
if (elem.nodeType === Node.ELEMENT_NODE && elem instanceof HTMLElement && elem.classList.contains(className))
|
|
85
|
+
return elem;
|
|
86
|
+
elem = elem.nextSibling;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Walks backward through the preceding siblings of `current` and returns the first one that has the given class.
|
|
92
|
+
* @param current Element to start from.
|
|
93
|
+
* @param className Class name to match.
|
|
94
|
+
* @returns The first matching preceding sibling, or `null` if none found.
|
|
95
|
+
*/
|
|
96
|
+
function prevElementByClass(current, className) {
|
|
97
|
+
let elem = current.previousSibling;
|
|
98
|
+
while (elem) {
|
|
99
|
+
if (elem.nodeType === Node.ELEMENT_NODE && elem instanceof HTMLElement && elem.classList.contains(className))
|
|
100
|
+
return elem;
|
|
101
|
+
elem = elem.previousSibling;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns the nearest preceding sibling element of `current`, skipping non-element nodes (e.g. text nodes).
|
|
107
|
+
* @param current Element to start from.
|
|
108
|
+
* @returns The previous sibling element, or `null` if none found.
|
|
109
|
+
*/
|
|
110
|
+
function prevElement(current) {
|
|
111
|
+
let elem = current.previousSibling;
|
|
112
|
+
while (elem) {
|
|
113
|
+
if (elem.nodeType === Node.ELEMENT_NODE && elem instanceof HTMLElement)
|
|
114
|
+
return elem;
|
|
115
|
+
elem = elem.previousSibling;
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns the nearest following sibling element of `current`, skipping non-element nodes (e.g. text nodes).
|
|
121
|
+
* @param current Element to start from.
|
|
122
|
+
* @returns The next sibling element, or `null` if none found.
|
|
123
|
+
*/
|
|
124
|
+
function nextElement(current) {
|
|
125
|
+
let elem = current.nextSibling;
|
|
126
|
+
while (elem) {
|
|
127
|
+
if (elem.nodeType === Node.ELEMENT_NODE && elem instanceof HTMLElement)
|
|
128
|
+
return elem;
|
|
129
|
+
elem = elem.nextSibling;
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Adds the given CSS class(es) to every descendant of `container` matching the selector. No-op when `container` or `cssClass` is falsy.
|
|
135
|
+
* @param container Element to search within (ignored when null/undefined).
|
|
136
|
+
* @param selectors CSS selector for the elements to modify.
|
|
137
|
+
* @param cssClass Class name(s) to add.
|
|
138
|
+
*/
|
|
139
|
+
function addClass(container, selectors, cssClass) {
|
|
140
|
+
if (!container || !cssClass)
|
|
141
|
+
return;
|
|
142
|
+
const nodes = container.querySelectorAll(selectors);
|
|
143
|
+
nodes.forEach(node => helpers.default.addCssClass(node, cssClass));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Removes the given CSS class(es) from every descendant of `container` matching the selector. No-op when `container` or `cssClass` is falsy.
|
|
147
|
+
* @param container Element to search within (ignored when null/undefined).
|
|
148
|
+
* @param selectors CSS selector for the elements to modify.
|
|
149
|
+
* @param cssClass Class name(s) to remove.
|
|
150
|
+
*/
|
|
151
|
+
function removeClass(container, selectors, cssClass) {
|
|
152
|
+
if (!container || !cssClass)
|
|
153
|
+
return;
|
|
154
|
+
const nodes = container.querySelectorAll(selectors);
|
|
155
|
+
nodes.forEach(elem => helpers.default.removeCssClass(elem, cssClass));
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Removes all child nodes from `container`, leaving it empty. No-op when `container` is null/undefined.
|
|
159
|
+
* @param container Element to clear.
|
|
160
|
+
*/
|
|
161
|
+
function empty(container) {
|
|
162
|
+
if (!container)
|
|
163
|
+
return;
|
|
164
|
+
while (container.hasChildNodes()) {
|
|
165
|
+
if (container.firstChild)
|
|
166
|
+
container.removeChild(container.firstChild);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
exports.addClass = addClass;
|
|
171
|
+
exports.empty = empty;
|
|
172
|
+
exports.getByClass = getByClass;
|
|
173
|
+
exports.getById = getById;
|
|
174
|
+
exports.getByName = getByName;
|
|
175
|
+
exports.getElementByTagName = getElementByTagName;
|
|
176
|
+
exports.getElementsByTagName = getElementsByTagName;
|
|
177
|
+
exports.nextElement = nextElement;
|
|
178
|
+
exports.nextElementByClass = nextElementByClass;
|
|
179
|
+
exports.prevElement = prevElement;
|
|
180
|
+
exports.prevElementByClass = prevElementByClass;
|
|
181
|
+
exports.queryElement = queryElement;
|
|
182
|
+
exports.queryElements = queryElements;
|
|
183
|
+
exports.removeClass = removeClass;
|
|
184
|
+
//# sourceMappingURL=dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sources":["../../../../source/dom/dom.ts"],"sourcesContent":[null],"names":["helpers"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
* Adds one or more CSS classes to a single element. A string is split on spaces. No-op when `cssClass` is falsy.
|
|
8
|
+
*/
|
|
9
|
+
const addCssClass = (elem, cssClass) => {
|
|
10
|
+
if (!cssClass)
|
|
11
|
+
return;
|
|
12
|
+
const tokens = (Array.isArray(cssClass) ? cssClass : cssClass.split(' ')).filter(Boolean);
|
|
13
|
+
if (tokens.length)
|
|
14
|
+
elem.classList.add(...tokens);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
* Removes one or more CSS classes from a single element. A string is split on spaces. No-op when `cssClass` is falsy.
|
|
19
|
+
*/
|
|
20
|
+
const removeCssClass = (elem, cssClass) => {
|
|
21
|
+
if (!cssClass)
|
|
22
|
+
return;
|
|
23
|
+
const tokens = (Array.isArray(cssClass) ? cssClass : cssClass.split(' ')).filter(Boolean);
|
|
24
|
+
if (tokens.length)
|
|
25
|
+
elem.classList.remove(...tokens);
|
|
26
|
+
};
|
|
27
|
+
var helpers = {
|
|
28
|
+
addCssClass,
|
|
29
|
+
removeCssClass
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.default = helpers;
|
|
33
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sources":["../../../../source/dom/helpers.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAEA;;;AAGG;AACH,MAAM,WAAW,GAAG,CAAC,IAAa,EAAE,QAAkB,KAAI;AACzD,IAAA,IAAI,CAAC,QAAQ;QACZ;AAED,IAAA,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IACzF,IAAI,MAAM,CAAC,MAAM;QAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;AAC/B,CAAC;AAED;;;AAGG;AACH,MAAM,cAAc,GAAG,CAAC,IAAa,EAAE,QAAkB,KAAI;AAC5D,IAAA,IAAI,CAAC,QAAQ;QACZ;AAED,IAAA,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IACzF,IAAI,MAAM,CAAC,MAAM;QAChB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAClC,CAAC;AAED,cAAe;IACd,WAAW;IACX;CACA;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('../reactive/effect.js');
|
|
4
|
+
var dom = require('./dom.js');
|
|
5
|
+
var tag = require('./tag.js');
|
|
6
|
+
|
|
7
|
+
/** Collection of DOM helper functions: element queries/traversal ({@link getById}, {@link queryElement}, {@link nextElement}, ...), class manipulation ({@link addClass}, {@link removeClass}), {@link empty}, and element creation via {@link tag}. */
|
|
8
|
+
const DOM = {
|
|
9
|
+
...dom,
|
|
10
|
+
...tag
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
exports.DOM = DOM;
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../source/dom/index.ts"],"sourcesContent":[null],"names":["DomHelpers","TagHelpers"],"mappings":";;;;;;AAMA;AACO,MAAM,GAAG,GAAG;AAClB,IAAA,GAAGA,GAAU;AACb,IAAA,GAAGC;;;;;"}
|