@shamar/wire 0.3.0 → 1.0.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/README.md +3 -9
- package/client/wire.js +54 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,15 +8,7 @@ Existing Alpine UI stays. A piece of the panel moves onto Wire when its markup o
|
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
After that release, the panel package pulls Wire in:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
pnpm add @shamar/adonis
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
`@shamar/adonis` depends on `@shamar/wire` and re-exports `WireKernel`, `WireComponent`, and `WireRequest`. Install the kernel on its own only when you are not using the Adonis host:
|
|
11
|
+
`pnpm add @shamar/adonis` installs the panel and `@shamar/wire`. The host re-exports `WireKernel`, `WireComponent`, and `WireRequest`. Install the kernel on its own only when you are not using the Adonis host:
|
|
20
12
|
|
|
21
13
|
```bash
|
|
22
14
|
pnpm add @shamar/wire
|
|
@@ -24,6 +16,8 @@ pnpm add @shamar/wire
|
|
|
24
16
|
|
|
25
17
|
No peer dependencies. Node 20+.
|
|
26
18
|
|
|
19
|
+
New versions are published by GitHub Actions, not from a laptop token. npm trusted publishing for `@shamar/wire` accepts publishes from the `publish.yml` workflow in `coolsam726/shamar`. A GitHub release of the monorepo runs it.
|
|
20
|
+
|
|
27
21
|
## What a request does
|
|
28
22
|
|
|
29
23
|
1. **Mount.** The server creates the component, copies `data` into a signed snapshot, and returns one HTML island.
|
package/client/wire.js
CHANGED
|
@@ -297,7 +297,7 @@
|
|
|
297
297
|
const style = document.createElement('style');
|
|
298
298
|
style.textContent =
|
|
299
299
|
'[wire\\:loading]{display:none !important}.wire-loading [wire\\:loading]{display:revert !important}.wire-loading [wire\\:loading\\.remove]{display:none !important}' +
|
|
300
|
-
'.wire-progress{position:fixed;top:0;left:0;height:2px;width:0;opacity:0;z-index:2147483646;pointer-events:none;background
|
|
300
|
+
'.wire-progress{position:fixed;top:0;left:0;height:2px;width:0;opacity:0;z-index:2147483646;pointer-events:none;background:var(--color-shamar-accent,#286291);transition:width .2s ease,opacity .2s ease}' +
|
|
301
301
|
'.wire-progress.is-active{opacity:1}';
|
|
302
302
|
document.head.appendChild(style);
|
|
303
303
|
|
|
@@ -481,7 +481,7 @@
|
|
|
481
481
|
const show = setTimeout(() => {
|
|
482
482
|
bar.classList.add('is-active');
|
|
483
483
|
bar.style.width = '35%';
|
|
484
|
-
},
|
|
484
|
+
}, 80);
|
|
485
485
|
const tick = setInterval(() => {
|
|
486
486
|
const width = Number.parseFloat(bar.style.width) || 0;
|
|
487
487
|
if (width < 90) bar.style.width = `${width + 8}%`;
|
|
@@ -609,6 +609,43 @@
|
|
|
609
609
|
return null;
|
|
610
610
|
}
|
|
611
611
|
|
|
612
|
+
/**
|
|
613
|
+
* Swap chrome that sits outside the scroll morph root (sidebar roots, topbar
|
|
614
|
+
* menu, etc.) so active nav and Alpine menus match the destination page.
|
|
615
|
+
*/
|
|
616
|
+
function syncNavigateRegions(nextDoc) {
|
|
617
|
+
const updated = [];
|
|
618
|
+
for (const current of [...document.querySelectorAll('[data-wire-sync]')]) {
|
|
619
|
+
const key = current.getAttribute('data-wire-sync');
|
|
620
|
+
if (!key) continue;
|
|
621
|
+
const next = nextDoc.querySelector(`[data-wire-sync="${CSS.escape(key)}"]`);
|
|
622
|
+
if (!(next instanceof HTMLElement)) continue;
|
|
623
|
+
if (window.Alpine?.destroyTree) {
|
|
624
|
+
try {
|
|
625
|
+
window.Alpine.destroyTree(current);
|
|
626
|
+
} catch {
|
|
627
|
+
/* ignore */
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const clone = next.cloneNode(true);
|
|
631
|
+
current.replaceWith(clone);
|
|
632
|
+
updated.push(clone);
|
|
633
|
+
}
|
|
634
|
+
return updated;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function reviveAlpine(roots) {
|
|
638
|
+
if (!window.Alpine?.initTree) return;
|
|
639
|
+
for (const root of roots) {
|
|
640
|
+
if (!(root instanceof HTMLElement)) continue;
|
|
641
|
+
try {
|
|
642
|
+
window.Alpine.initTree(root);
|
|
643
|
+
} catch {
|
|
644
|
+
/* ignore */
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
612
649
|
function applyScroll(mode, scrollY, url) {
|
|
613
650
|
if (mode === 'preserve') return;
|
|
614
651
|
if (mode === 'restore') {
|
|
@@ -671,17 +708,28 @@
|
|
|
671
708
|
history.pushState({ wireScroll: 0 }, '', finalUrl);
|
|
672
709
|
}
|
|
673
710
|
mergeHead(doc);
|
|
711
|
+
const synced = syncNavigateRegions(doc);
|
|
674
712
|
const region = sharedRoot(doc);
|
|
675
713
|
const from = region ? region.current : document.body;
|
|
676
714
|
const to = region ? region.next : doc.body;
|
|
677
715
|
const kept = liftPersisted(from);
|
|
716
|
+
// Drop Alpine on the outgoing region before morph. Morph reuses matching
|
|
717
|
+
// nodes (same tag), so without destroyTree, list selection / open menus
|
|
718
|
+
// from the previous page leak into the next (bulk bar, dropdowns, etc.).
|
|
719
|
+
if (window.Alpine?.destroyTree) {
|
|
720
|
+
try {
|
|
721
|
+
window.Alpine.destroyTree(from);
|
|
722
|
+
} catch {
|
|
723
|
+
/* ignore */
|
|
724
|
+
}
|
|
725
|
+
}
|
|
678
726
|
morph(from, to, from, false);
|
|
679
727
|
const restored = restorePersisted(from, kept);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
}
|
|
728
|
+
const alpineRoots = [...synced, from];
|
|
729
|
+
for (const el of from.querySelectorAll('[wire\\:persist]')) {
|
|
730
|
+
if (!restored.includes(el)) alpineRoots.push(el);
|
|
684
731
|
}
|
|
732
|
+
reviveAlpine(alpineRoots);
|
|
685
733
|
reviveScripts(from, restored);
|
|
686
734
|
applyScroll(options.scroll, options.scrollY, new URL(finalUrl, window.location.href));
|
|
687
735
|
document.dispatchEvent(new CustomEvent('wire:navigated', { detail: { url: window.location.href } }));
|