@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.
Files changed (63) hide show
  1. package/README.md +12 -7
  2. package/dist/cjs/constants.js +14 -0
  3. package/dist/cjs/constants.js.map +1 -0
  4. package/dist/cjs/dom/bind-each.js +90 -0
  5. package/dist/cjs/dom/bind-each.js.map +1 -0
  6. package/dist/cjs/dom/bind.js +29 -0
  7. package/dist/cjs/dom/bind.js.map +1 -0
  8. package/dist/cjs/dom/binding-cleanup.js +162 -0
  9. package/dist/cjs/dom/binding-cleanup.js.map +1 -0
  10. package/dist/cjs/dom/dom.js +184 -0
  11. package/dist/cjs/dom/dom.js.map +1 -0
  12. package/dist/cjs/dom/helpers.js +33 -0
  13. package/dist/cjs/dom/helpers.js.map +1 -0
  14. package/dist/cjs/dom/index.js +14 -0
  15. package/dist/cjs/dom/index.js.map +1 -0
  16. package/dist/cjs/dom/tag.js +207 -0
  17. package/dist/cjs/dom/tag.js.map +1 -0
  18. package/dist/cjs/element.js +265 -0
  19. package/dist/cjs/element.js.map +1 -0
  20. package/dist/cjs/events.js +204 -0
  21. package/dist/cjs/events.js.map +1 -0
  22. package/dist/cjs/ext.js +20 -0
  23. package/dist/cjs/ext.js.map +1 -0
  24. package/dist/cjs/index.js +40 -1455
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/reactive/computed.js +36 -0
  27. package/dist/cjs/reactive/computed.js.map +1 -0
  28. package/dist/cjs/reactive/effect.js +197 -0
  29. package/dist/cjs/reactive/effect.js.map +1 -0
  30. package/dist/cjs/reactive/reactive.js +106 -0
  31. package/dist/cjs/reactive/reactive.js.map +1 -0
  32. package/dist/mjs/constants.js +10 -0
  33. package/dist/mjs/constants.js.map +1 -0
  34. package/dist/mjs/dom/bind-each.js +86 -0
  35. package/dist/mjs/dom/bind-each.js.map +1 -0
  36. package/dist/mjs/dom/bind.js +26 -0
  37. package/dist/mjs/dom/bind.js.map +1 -0
  38. package/dist/mjs/dom/binding-cleanup.js +156 -0
  39. package/dist/mjs/dom/binding-cleanup.js.map +1 -0
  40. package/dist/mjs/dom/dom.js +169 -0
  41. package/dist/mjs/dom/dom.js.map +1 -0
  42. package/dist/mjs/dom/helpers.js +29 -0
  43. package/dist/mjs/dom/helpers.js.map +1 -0
  44. package/dist/mjs/dom/index.js +12 -0
  45. package/dist/mjs/dom/index.js.map +1 -0
  46. package/dist/mjs/dom/tag.js +203 -0
  47. package/dist/mjs/dom/tag.js.map +1 -0
  48. package/dist/mjs/element.js +260 -0
  49. package/dist/mjs/element.js.map +1 -0
  50. package/dist/mjs/events.js +202 -0
  51. package/dist/mjs/events.js.map +1 -0
  52. package/dist/mjs/ext.js +18 -0
  53. package/dist/mjs/ext.js.map +1 -0
  54. package/dist/mjs/index.js +11 -1431
  55. package/dist/mjs/index.js.map +1 -1
  56. package/dist/mjs/reactive/computed.js +33 -0
  57. package/dist/mjs/reactive/computed.js.map +1 -0
  58. package/dist/mjs/reactive/effect.js +187 -0
  59. package/dist/mjs/reactive/effect.js.map +1 -0
  60. package/dist/mjs/reactive/reactive.js +102 -0
  61. package/dist/mjs/reactive/reactive.js.map +1 -0
  62. package/dist/types.d.ts +18 -2
  63. 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
- ### Global click handler cleanup
252
+ ### Command click handler
250
253
 
251
- The library registers one global `click` listener on `window` to handle commands. Call `destroyUI()` to remove it on app teardown or during HMR disposal:
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
- destroyUI();
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 when its container is removed from the document (same lifecycle as `bind`).
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;;;;;"}