@skirbi/sugar 0.0.9 → 0.0.10

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,35 @@
1
1
  Revision history for @skirbi/sugar
2
2
 
3
+ 0.0.10 2026-02-24 03:09:34Z
4
+
5
+ * Improve Livewire/morphdom support in withConnectedSugar
6
+
7
+ In certain morph scenarios the host element instance remains the same
8
+ while its child nodes are replaced. In that case `connectedCallback`
9
+ is not triggered again.
10
+
11
+ The mixin now provides `_observeChildListOnce(when, fn)` which allows
12
+ components to react to child mutations and re-apply their compile logic
13
+ when necessary.
14
+
15
+ This keeps DOM-compiling components (e.g. semtic-steps in @skirbi/semtic)
16
+ stable even when morphing frameworks replace their internal markup without
17
+ recreating the custom element instance.
18
+
19
+ The pattern for a `connectedCallbackSugar` now becomes:
20
+
21
+ connectedCallbackSugar() {
22
+ this._compile();
23
+
24
+ this._observeChildListOnce(
25
+ () => this.querySelector(':scope > your-tag-here'),
26
+ () => this._compile()
27
+ );
28
+ }
29
+
30
+ Where `your-tag-here` represents the authored child element that
31
+ indicates the component has been reverted to its pre-compiled state.
32
+
3
33
  0.0.9 2026-02-23 10:56:27Z
4
34
 
5
35
  * Fix a bug for connectedCallbacks with Livewire
package/lib/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // SPDX-License-Identifier: MIT
4
4
 
5
- const VERSION = "0.0.9";
5
+ const VERSION = "0.0.10";
6
6
 
7
7
  export { HTMLElementSugar } from './htmlelement.mjs';
8
8
  export { HTMLElementSugarInput } from './htmlelement-input.mjs';
package/lib/testing.mjs CHANGED
@@ -56,23 +56,21 @@ export async function setupDomForTesting(
56
56
  *
57
57
  * This helper verifies:
58
58
  *
59
- * 1. `Class.exampleHTML` matches the provided `example` snippet.
60
- * 2. After mounting and lifecycle execution, the rendered output
61
- * matches `Class.exampleRenderedHTML`.
59
+ * 1. `Class.exampleHTML` matches the provided `options.example` snippet.
60
+ * 2. After mounting and lifecycle execution, the rendered output matches
61
+ * `Class.exampleRenderedHTML`.
62
62
  *
63
- * The component must define:
63
+ * The component class must define:
64
64
  *
65
- * - `static exampleHTML`
66
- * - `static exampleRenderedHTML`
65
+ * - `static exampleHTML` (string)
66
+ * - `static exampleRenderedHTML` (string)
67
67
  *
68
- * @template {typeof HTMLElement} T
68
+ * It may also define:
69
69
  *
70
- * @param {T & {
71
- * register?: () => void,
72
- * init?: () => void,
73
- * exampleHTML: string,
74
- * exampleRenderedHTML: string
75
- * }} Class
70
+ * - `static register()` (optional)
71
+ * - `static init()` (optional)
72
+ *
73
+ * @param {Function} Class
76
74
  * The component class under test.
77
75
  *
78
76
  * @param {Object} options
@@ -82,7 +80,7 @@ export async function setupDomForTesting(
82
80
  * @param {string} options.example
83
81
  * Expected authoring HTML to compare against `Class.exampleHTML`.
84
82
  *
85
- * @param {import('tap').Test} options.tap
83
+ * @param {Object} options.tap
86
84
  * Tap test instance used for assertions.
87
85
  *
88
86
  * @returns {Promise<void>}
@@ -11,20 +11,41 @@ export const withConnectedSugar = (Base) =>
11
11
 
12
12
  _shouldRenderOnConnect() {
13
13
  const guard = this.constructor.renderGuardSelector;
14
-
15
- if (guard) {
16
- return !this.querySelector(guard);
17
- }
14
+ if (guard) return !this.querySelector(guard);
18
15
 
19
16
  if (this._rendered) return false;
20
-
21
17
  this._rendered = true;
22
18
  return true;
23
19
  }
24
20
 
21
+ /**
22
+ * Install a single MutationObserver that calls `fn()` when direct children
23
+ * change and `when()` returns true.
24
+ *
25
+ * Intended for morphdom/livewire scenarios where the host stays the same
26
+ * instance.
27
+ *
28
+ * @param {Function} when - predicate
29
+ * @param {Function} fn - callback
30
+ */
31
+ _observeChildListOnce(when, fn) {
32
+ if (this._sugarMo) return;
33
+
34
+ this._sugarMo = new MutationObserver(() => {
35
+ if (when()) fn();
36
+ });
37
+
38
+ this._sugarMo.observe(this, { childList: true });
39
+ }
40
+
41
+ disconnectedCallback() {
42
+ // polite cleanup
43
+ this._sugarMo?.disconnect();
44
+ this._sugarMo = null;
45
+ }
46
+
25
47
  connectedCallback() {
26
48
  this._syncObservedAttributesToConfig();
27
-
28
49
  if (!this._shouldRenderOnConnect()) return;
29
50
 
30
51
  if (typeof this.connectedCallbackSugar === 'function') {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "Wesley Schwengle"
5
5
  },
6
6
  "bugs": {
7
- "url": "https://gitlab.com/skirbi/sugar/-/issues"
7
+ "url": "https://gitlab.com/skirbi/skirbi/-/issues"
8
8
  },
9
9
  "dependencies": {
10
10
  "@opndev/util": "latest"
@@ -29,7 +29,7 @@
29
29
  "./testing": "./lib/testing.mjs",
30
30
  "./with-connected-sugar": "./lib/with-connected-sugar.mjs"
31
31
  },
32
- "homepage": "https://gitlab.com/skirbi/sugar",
32
+ "homepage": "https://gitlab.com/skirbi/skirbi",
33
33
  "keywords": [
34
34
  "custom elements",
35
35
  "web components",
@@ -42,7 +42,7 @@
42
42
  "name": "@skirbi/sugar",
43
43
  "repository": {
44
44
  "type": "git",
45
- "url": "git+https://gitlab.com/skirbi/sugar.git"
45
+ "url": "git+https://gitlab.com/skirbi/skirbi.git"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "rzil build",
@@ -53,5 +53,5 @@
53
53
  },
54
54
  "sideEffects": false,
55
55
  "type": "module",
56
- "version": "0.0.9"
56
+ "version": "0.0.10"
57
57
  }