bun-plugin-stx 0.2.338 → 0.2.339

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.
@@ -712,7 +712,7 @@ function routerSource() {
712
712
  if(window.__stxRouter&&window.__stxRouter.__rev===ROUTER_REV)return;
713
713
 
714
714
  // \u2500\u2500 Configuration \u2500\u2500
715
- var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false,prefetchCacheMax:50,routeFocus:true,announceRoute:true,interceptForms:false,cssLoadTimeout:1500};
715
+ var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false,prefetchCacheMax:50,routeFocus:true,announceRoute:true,interceptForms:false,cssLoadTimeout:1500,scrollRestoration:true};
716
716
  var o=Object.assign({},defaults,window.__stxRouterConfig||{},window.STX_ROUTER_OPTIONS||{});
717
717
  var containerSel=o.container;
718
718
  var debug=!!o.debug;
@@ -729,6 +729,84 @@ function routerSource() {
729
729
  function ce(tag){return document.createElement(tag)}
730
730
  function dhead(){return document.head}
731
731
 
732
+ // \u2500\u2500 Scroll position \u2500\u2500
733
+ // Forward navigation goes to the top, or to the hash. Back and forward return
734
+ // to where the entry was left -- the browser cannot do that for us, because
735
+ // by the time it would restore, the content of the entry has not been fetched
736
+ // yet, so it clamps to whatever height the outgoing page happened to have.
737
+ // history.scrollRestoration therefore goes to manual and the positions are
738
+ // kept here, keyed by a token written into each history entry (two entries
739
+ // for the same URL keep their own positions, which is the point).
740
+ //
741
+ // Manual restoration also takes the browser's reload behaviour away, so the
742
+ // positions are mirrored into sessionStorage: a reload, or a return to the
743
+ // tab, finds the entry's token already in history.state and restores from
744
+ // there. sessionStorage is per tab and dies with it, same as the history.
745
+ var SCROLL_TOKEN='__stxScroll';
746
+ var SCROLL_STORE='stx:scroll:';
747
+ var scrollSeq=0;
748
+ var pendingScroll=null;
749
+ var restoreScroll=!!o.scrollRestoration;
750
+ function newScrollToken(){return 's'+(++scrollSeq)+'-'+Date.now()}
751
+ var scrollToken=(history.state&&history.state[SCROLL_TOKEN])||newScrollToken();
752
+ // sessionStorage is the only store: it is synchronous, it is per tab, it dies
753
+ // with the tab exactly as the history does, and it is the one that survives a
754
+ // reload. A private window that refuses it degrades to scrolling to the top.
755
+ function readScroll(token){
756
+ try{
757
+ var parts=(window.sessionStorage.getItem(SCROLL_STORE+token)||'').split(',');
758
+ return parts.length===2?[parseFloat(parts[0])||0,parseFloat(parts[1])||0]:null;
759
+ }catch(e){return null}
760
+ }
761
+ // Called while the outgoing entry is still the current one, so the position
762
+ // read here belongs to the token being written.
763
+ function rememberScroll(){
764
+ if(!restoreScroll)return;
765
+ try{window.sessionStorage.setItem(SCROLL_STORE+scrollToken,(window.pageXOffset||window.scrollX||0)+','+(window.pageYOffset||window.scrollY||0))}catch(e){}
766
+ }
767
+ // One place decides where a swap leaves the viewport, so the fragment path
768
+ // and the whole-document path cannot drift apart.
769
+ function applyScroll(hash){
770
+ if(pendingScroll){
771
+ var at=pendingScroll;
772
+ pendingScroll=null;
773
+ window.scrollTo({left:at[0],top:at[1],behavior:'instant'});
774
+ return;
775
+ }
776
+ if(o.scrollToTop&&!hash){window.scrollTo({top:0,behavior:'instant'});return}
777
+ if(hash){var el=qs(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
778
+ }
779
+ // Keeps whatever another script put in the entry; only adds the token.
780
+ function stampScrollToken(){
781
+ var state={};
782
+ var current=history.state;
783
+ if(current&&typeof current==='object')for(var key in current)state[key]=current[key];
784
+ state[SCROLL_TOKEN]=scrollToken;
785
+ try{history.replaceState(state,'',location.href)}catch(e){}
786
+ }
787
+ if(restoreScroll){
788
+ try{history.scrollRestoration='manual'}catch(e){}
789
+ // A token already in the entry means this document is a reload or a
790
+ // restore of an entry visited before, so its position is worth asking for.
791
+ var known=history.state&&history.state[SCROLL_TOKEN];
792
+ if(known){
793
+ var saved=readScroll(scrollToken);
794
+ if(saved&&(saved[0]||saved[1])){
795
+ var restoreAt=function(){window.scrollTo({left:saved[0],top:saved[1],behavior:'instant'})};
796
+ if(document.readyState==='complete')restoreAt();
797
+ else window.addEventListener('load',restoreAt,{once:true});
798
+ }
799
+ }
800
+ else{
801
+ stampScrollToken();
802
+ }
803
+ // A reload or a link out of the app never calls writeHistory, so this is
804
+ // the only chance to record where the page was left. pagehide fires for
805
+ // both, and unlike beforeunload it does not keep the page out of the
806
+ // back/forward cache.
807
+ window.addEventListener('pagehide',rememberScroll);
808
+ }
809
+
732
810
  // Replace, never merge: absent payloads must forget the outgoing page's data.
733
811
  // Run at the committed swap, not during prefetch or a superseded navigation.
734
812
  function hydrateServerData(html){
@@ -1319,9 +1397,14 @@ function routerSource() {
1319
1397
  // through swap() to each of the three history sites would have been the
1320
1398
  // alternative (#1807).
1321
1399
  function writeHistory(mode,href){
1322
- if(mode==='replace')history.replaceState({},'',href);
1323
- else history.pushState({},'',href);
1400
+ // The position belongs to the entry being left, and scrollToken still
1401
+ // names it here.
1402
+ rememberScroll();
1403
+ if(mode==='replace'){history.replaceState(tokenState(),'',href);return}
1404
+ scrollToken=newScrollToken();
1405
+ history.pushState(tokenState(),'',href);
1324
1406
  }
1407
+ function tokenState(){var state={};state[SCROLL_TOKEN]=scrollToken;return state}
1325
1408
 
1326
1409
  // Second arg accepts the legacy pushState boolean OR an options object
1327
1410
  // { replace }. Callers inside this file still pass the boolean.
@@ -1776,8 +1859,7 @@ else {
1776
1859
  qsa('script[data-stx-page]').forEach(function(s){s.remove()});
1777
1860
  if(pushState!==false)writeHistory(pushState,url+(hash||''));
1778
1861
  refreshCurrentLinks();
1779
- if(o.scrollToTop&&!hash)window.scrollTo({top:0,behavior:'instant'});
1780
- else if(hash){var el=qs(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
1862
+ applyScroll(hash);
1781
1863
  window.dispatchEvent(new CustomEvent('stx:navigate',{detail:{url:url}}));
1782
1864
  // Before page scripts run, so a page that focuses its own control on
1783
1865
  // mount still wins \u2014 its script executes after this.
@@ -2235,8 +2317,7 @@ else {
2235
2317
  refreshCurrentLinks();
2236
2318
 
2237
2319
  // Scroll
2238
- if(o.scrollToTop&&!hash)window.scrollTo({top:0,behavior:'instant'});
2239
- else if(hash){var el=qs(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
2320
+ applyScroll(hash);
2240
2321
 
2241
2322
  // Update title
2242
2323
  var newTitle=doc.querySelector('title');
@@ -2602,6 +2683,16 @@ else {
2602
2683
 
2603
2684
  // \u2500\u2500 Back/forward \u2500\u2500
2604
2685
  window.addEventListener('popstate',function(){
2686
+ // Nothing has scrolled yet (restoration is manual), so the viewport still
2687
+ // shows the entry being left: save it under its own token before adopting
2688
+ // the popped entry's, and hand the swap the position to land on.
2689
+ rememberScroll();
2690
+ if(restoreScroll){
2691
+ var popped=history.state&&history.state[SCROLL_TOKEN];
2692
+ scrollToken=popped||newScrollToken();
2693
+ if(!popped)stampScrollToken();
2694
+ pendingScroll=readScroll(scrollToken);
2695
+ }
2605
2696
  navigate(location.pathname+location.search+location.hash,false);
2606
2697
  });
2607
2698
 
package/dist/serve.js CHANGED
@@ -9791,7 +9791,7 @@ function __stxOverlay(errs){
9791
9791
  rebuildDiscoveredPagePaths(kept);
9792
9792
  await indexPageMiddleware(kept);
9793
9793
  try {
9794
- const { Router } = await import("./chunk-bw4fd40r.js");
9794
+ const { Router } = await import("./chunk-zd4nfpfq.js");
9795
9795
  const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
9796
9796
  const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName(), exclude: options.exclude });
9797
9797
  if (!options.quiet)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-plugin-stx",
3
3
  "type": "module",
4
- "version": "0.2.338",
4
+ "version": "0.2.339",
5
5
  "description": "A Bun plugin that allows for using Laravel Blade-like syntax.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",
@@ -74,7 +74,7 @@
74
74
  "typecheck": "bun tsc --noEmit"
75
75
  },
76
76
  "dependencies": {
77
- "@stacksjs/stx": "0.2.338",
78
- "stx-router": "0.2.338"
77
+ "@stacksjs/stx": "0.2.339",
78
+ "stx-router": "0.2.339"
79
79
  }
80
80
  }