@skirbi/sugar 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Changes CHANGED
@@ -1,5 +1,40 @@
1
1
  Revision history for @skirbi/sugar
2
2
 
3
+ 0.1.1 2026-06-04 15:34:20Z
4
+
5
+ * Added morph-* attributes to withConnectedSugar, the API of this is
6
+ unstable and should probably only be used when debugging Livewire morphing
7
+ or similar tools.
8
+
9
+ Some debugging artifacts have become morph-* attributes:
10
+
11
+ * morph-ignore — disarm the observer entirely (no-op against full node
12
+ replacement by Livewire, but prevents cascade
13
+ re-renders during normal morphing)
14
+ * morph-child — observe childList only (explicit opt-in)
15
+ * morph-attribute — observe attribute changes only
16
+ * morph-subtree — observe the full descendant subtree
17
+ * morph-debug — Enable debuging used by `_armMorphObserver`.
18
+
19
+ When none are present, the existing default (childList: true) applies.
20
+
21
+ * Add `withMorphObserverPaused(fn)` to withConnectedSugar.
22
+ Components that mutate their own children in morphedCallbackSugar or
23
+ connectedCallbackSugar risk triggering their own MutationObserver,
24
+ causing infinite loops.
25
+
26
+ `withMorphObserverPaused(fn)` disconnects the observer, runs `fn`, then
27
+ reconnects with the original options. It is a public API intended for
28
+ use by component authors.
29
+
30
+ Observer options are now stored as `_morphObserveOptions` when the
31
+ observer is armed, so they can be reused by withMorphObserverPaused
32
+ and any future callers without re-deriving them.
33
+
34
+ This again is a WIP feature that may change based on Livewire morphing
35
+ insights.
36
+
37
+
3
38
  0.1.0 2026-06-04 01:20:59Z
4
39
 
5
40
  * BREAKING: Sugar components may no longer manually define
package/lib/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // SPDX-License-Identifier: MIT
4
4
 
5
- const VERSION = "0.1.0";
5
+ const VERSION = "0.1.1";
6
6
 
7
7
  export { HTMLElementSugar } from './htmlelement.mjs';
8
8
  export { HTMLElementSugarInput } from './htmlelement-input.mjs';
@@ -27,19 +27,51 @@ export const withConnectedSugar = (Base) =>
27
27
 
28
28
  _armMorphObserver() {
29
29
  if (this._sugarMo) return;
30
+ if (this.hasAttribute('morph-ignore')) return;
30
31
 
31
- this._sugarMo = new MutationObserver(() => {
32
- if (this._shouldRenderOnMorph()) {
33
- this.connectedCallbackSugar();
34
- return;
35
- }
36
- if (this.hasRenderedShape() && this.morphedCallbackSugar) {
37
- this.morphedCallbackSugar();
38
- return;
32
+ const hasExplicit = this.hasAttribute('morph-child') ||
33
+ this.hasAttribute('morph-attribute') ||
34
+ this.hasAttribute('morph-subtree');
35
+
36
+ this._morphObserveOptions = hasExplicit ? {
37
+ childList: this.hasAttribute('morph-child'),
38
+ attributes: this.hasAttribute('morph-attribute'),
39
+ subtree: this.hasAttribute('morph-subtree'),
40
+ } : {
41
+ childList: true,
42
+ };
43
+
44
+ this._sugarMo = new MutationObserver((mutations) => {
45
+
46
+ if (this.hasAttribute('morph-debug')) {
47
+ console.group(`[sugar-morph] ${this.tagName}${this.id ? '#' + this.id : ''}${this.getAttribute('label') ? `[label="${this.getAttribute('label')}"]` : ''}${this.getAttribute('title') ? `[title="${this.getAttribute('title')}"]` : ''}`);
48
+ console.log('parent:', this.parentElement?.tagName);
49
+ console.log('mutations:', mutations.map(m => ({
50
+ type: m.type,
51
+ added: Array.from(m.addedNodes).map(n => n.nodeName),
52
+ removed: Array.from(m.removedNodes).map(n => n.nodeName)
53
+ })));
54
+ console.log('hasRenderedShape:', this.hasRenderedShape());
55
+ console.log('shouldRenderOnMorph:', this._shouldRenderOnMorph());
56
+ setTimeout(() => console.log('innerHTML after:', this.innerHTML), 0);
57
+ console.groupEnd();
39
58
  }
59
+
60
+
61
+ queueMicrotask(() => {
62
+ if (this._shouldRenderOnMorph()) {
63
+ this.connectedCallbackSugar();
64
+ return;
65
+ }
66
+ if (this.hasRenderedShape() && this.morphedCallbackSugar) {
67
+ this.morphedCallbackSugar();
68
+ return;
69
+ }
70
+ });
71
+
40
72
  });
41
73
 
42
- this._sugarMo.observe(this, { childList: true });
74
+ this._sugarMo.observe(this, this._morphObserveOptions);
43
75
  }
44
76
 
45
77
  _shouldRenderOnMorph() {
@@ -58,6 +90,17 @@ export const withConnectedSugar = (Base) =>
58
90
  return true;
59
91
  }
60
92
 
93
+ withMorphObserverPaused(fn) {
94
+ this._sugarMo?.disconnect();
95
+ try {
96
+ fn();
97
+ } finally {
98
+ if (this._morphObserveOptions) {
99
+ this._sugarMo?.observe(this, this._morphObserveOptions);
100
+ }
101
+ }
102
+ }
103
+
61
104
  disconnectedCallback() {
62
105
  this._sugarMo?.disconnect();
63
106
  this._sugarMo = null;
package/package.json CHANGED
@@ -52,5 +52,5 @@
52
52
  },
53
53
  "sideEffects": false,
54
54
  "type": "module",
55
- "version": "0.1.0"
55
+ "version": "0.1.1"
56
56
  }