@shamar/wire 1.0.0 → 1.0.2

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 CHANGED
@@ -123,7 +123,7 @@ save() {
123
123
 
124
124
  `@shamar/adonis` serves `assets/wire.js` at `{panel}/assets/wire.js` and loads it from the admin shell. The script listens on `document`, so every island on the page shares one runtime.
125
125
 
126
- It coexists with Alpine. On `alpine:init` it registers the `$wire` magic. After a morph it calls `Alpine.initTree` on nodes that were inserted.
126
+ It coexists with Alpine. On `alpine:init` it registers the `$wire` magic. Island morphs call `Alpine.initTree` on inserted nodes while the parent scope is still alive. Full-page `wire:navigate` destroys Alpine on the outgoing region, morphs without initializing orphans, then `Alpine.initTree`s the destination root so nested `x-data` (media library, forms, …) sees its scope.
127
127
 
128
128
  ### Bindings
129
129
 
package/client/wire.js CHANGED
@@ -79,7 +79,7 @@
79
79
  return from.nodeType === 1 && to.nodeType === 1 && from.tagName === to.tagName;
80
80
  }
81
81
 
82
- function morph(from, to, origin, skipIslands = true) {
82
+ function morph(from, to, origin, skipIslands = true, initAlpine = true) {
83
83
  if (from.nodeType === 3 && to.nodeType === 3) {
84
84
  if (from.nodeValue !== to.nodeValue) from.nodeValue = to.nodeValue;
85
85
  return;
@@ -110,10 +110,10 @@
110
110
  from.checked = to.checked;
111
111
  }
112
112
 
113
- morphChildren(from, to, origin, skipIslands);
113
+ morphChildren(from, to, origin, skipIslands, initAlpine);
114
114
  }
115
115
 
116
- function morphChildren(from, to, origin, skipIslands = true) {
116
+ function morphChildren(from, to, origin, skipIslands = true, initAlpine = true) {
117
117
  const current = [...from.childNodes];
118
118
  const incoming = [...to.childNodes];
119
119
  const used = new Set();
@@ -141,7 +141,7 @@
141
141
  }
142
142
  if (match) {
143
143
  used.add(match);
144
- morph(match, target, origin, skipIslands);
144
+ morph(match, target, origin, skipIslands, initAlpine);
145
145
  ordered.push(match);
146
146
  } else {
147
147
  ordered.push(target.cloneNode(true));
@@ -153,7 +153,12 @@
153
153
  ordered.forEach((node, index) => {
154
154
  if (from.childNodes[index] !== node) from.insertBefore(node, from.childNodes[index] || null);
155
155
  });
156
- if (window.Alpine?.initTree) {
156
+ // Island updates init Alpine on newly inserted subtrees while the parent
157
+ // scope is still alive. Full-page navigate must skip this — destroyTree already
158
+ // ran and reviveAlpine() re-inits the whole region after morph. Calling
159
+ // initTree on orphans here throws (selectedFiles/viewMode/… not defined)
160
+ // and leaves the destination page blank until a hard refresh.
161
+ if (initAlpine && window.Alpine?.initTree) {
157
162
  for (const node of ordered) {
158
163
  if (!used.has(node) && node.nodeType === 1 && !node.hasAttribute('wire:persist')) {
159
164
  window.Alpine.initTree(node);
@@ -723,7 +728,8 @@
723
728
  /* ignore */
724
729
  }
725
730
  }
726
- morph(from, to, from, false);
731
+ // Skip Alpine.initTree during morph — parent x-data is dead until reviveAlpine.
732
+ morph(from, to, from, false, false);
727
733
  const restored = restorePersisted(from, kept);
728
734
  const alpineRoots = [...synced, from];
729
735
  for (const el of from.querySelectorAll('[wire\\:persist]')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shamar/wire",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Server-driven reactive components. Usable on its own or inside a Shamar admin panel.",
5
5
  "license": "MIT",
6
6
  "type": "module",