bun-plugin-stx 0.2.382 → 0.2.384

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.
@@ -839,8 +839,14 @@ function routerSource() {
839
839
  log('[router] build skew: page is',loadedBuild,'server is',incoming,'\u2014 full navigation');
840
840
  location.href=url;
841
841
  }
842
+ // A link marked data-stx-transition="none" swaps without the cross-fade. A
843
+ // tab bar is the case: iOS switches tabs instantly, and the fade read as a
844
+ // quarter-second lag on every tap in a phone app. Set by the click that
845
+ // started the navigation, so programmatic and history navigations keep it.
846
+ var instantNext=false;
847
+ var instantNav=false;
842
848
  function runViewTransition(callback){
843
- if(!o.viewTransitions||!document.startViewTransition)return false;
849
+ if(instantNav||!o.viewTransitions||!document.startViewTransition)return false;
844
850
  try{
845
851
  var transition=document.startViewTransition(callback);
846
852
  var onAbort=function(err){log('[router] view transition aborted:',err&&err.message?err.message:err)};
@@ -867,19 +873,28 @@ function routerSource() {
867
873
  progEl.style.opacity=progVal>0?'1':'0';
868
874
  progEl.style.transform='scaleX('+(progVal/100)+')';
869
875
  }
876
+ // Shown only for a navigation that is actually waiting. A page served from
877
+ // the prefetch cache swaps in a few milliseconds, and drawing then fading a
878
+ // bar for it made every instant navigation look like a load.
879
+ var progDelay=null;
870
880
  function startProgress(){
871
881
  if(!o.progress||!progEl)return;
872
882
  if(progTimer){clearInterval(progTimer);progTimer=null}
873
- setProgress(8);
874
- progTimer=setInterval(function(){
875
- if(progVal>=90)return;
876
- // Asymptotic trickle \u2014 fast at first, slower near 90%
877
- var inc=Math.max(0.4,(90-progVal)*0.08);
878
- setProgress(progVal+inc);
879
- },160);
883
+ if(progDelay)clearTimeout(progDelay);
884
+ progDelay=setTimeout(function(){
885
+ progDelay=null;
886
+ setProgress(8);
887
+ progTimer=setInterval(function(){
888
+ if(progVal>=90)return;
889
+ // Asymptotic trickle \u2014 fast at first, slower near 90%
890
+ var inc=Math.max(0.4,(90-progVal)*0.08);
891
+ setProgress(progVal+inc);
892
+ },160);
893
+ },150);
880
894
  }
881
895
  function finishProgress(){
882
896
  if(!o.progress||!progEl)return;
897
+ if(progDelay){clearTimeout(progDelay);progDelay=null;return}
883
898
  if(progTimer){clearInterval(progTimer);progTimer=null}
884
899
  setProgress(100);
885
900
  // Fade out, then reset. Delays chosen so the "full" state is briefly
@@ -1129,6 +1144,47 @@ function routerSource() {
1129
1144
  function isComposablesScript(s){
1130
1145
  return !!s&&((s.hasAttribute&&s.hasAttribute('data-stx-composables'))||COMPOSABLES_TEXT.test(s.textContent||''));
1131
1146
  }
1147
+ /*
1148
+ * What the block wrap below would otherwise hide (stacksjs/stx#2041).
1149
+ *
1150
+ * A re-executed script is wrapped in a bare block so that top-level const
1151
+ * and let cannot collide across navigations. That wrap is invisible for a
1152
+ * plain function declaration -- Annex B.3.3 still hoists its binding to the
1153
+ * enclosing scope in sloppy mode -- and NOT invisible for anything else.
1154
+ * async function, function*, class, const and let are all block-scoped, so
1155
+ * the same source published a global when the browser parsed the script and
1156
+ * published nothing when the router re-ran it.
1157
+ *
1158
+ * The effect is a divergence between development and a built app, because
1159
+ * only the built one reaches a route as a fragment: a page served whole runs
1160
+ * its script natively. An inline onclick that names such a declaration then
1161
+ * worked in dev and threw ReferenceError in the packaged app, where there is
1162
+ * no console, so it read as a button that does nothing.
1163
+ *
1164
+ * So: re-publish what the browser would have published. Only values that are
1165
+ * functions, which is what an inline handler calls -- assigning every
1166
+ * top-level const would otherwise write over window.name and friends, which
1167
+ * a lexical global shadows rather than overwrites. Each name is guarded on
1168
+ * its own so an unmatched one cannot take the rest down, and typeof is safe
1169
+ * on a name that was never declared.
1170
+ *
1171
+ * Column-anchored: a declaration nested inside a function is indented, and
1172
+ * is not in scope at the end of the block anyway.
1173
+ */
1174
+ var TOP_LEVEL_DECL=/^(?:export\\s+)?(?:async\\s+)?(?:function\\s*\\*?|class|const|let|var)\\s+([A-Za-z_$][\\w$]*)/gm;
1175
+ function republishTopLevel(src){
1176
+ var names=[],m;
1177
+ TOP_LEVEL_DECL.lastIndex=0;
1178
+ while((m=TOP_LEVEL_DECL.exec(src))!==null){
1179
+ if(names.indexOf(m[1])===-1)names.push(m[1]);
1180
+ }
1181
+ if(!names.length)return '';
1182
+ var out='\\n;';
1183
+ for(var i=0;i<names.length;i++){
1184
+ out+='try{if(typeof '+names[i]+'==="function")window.'+names[i]+'='+names[i]+'}catch(e){}';
1185
+ }
1186
+ return out;
1187
+ }
1132
1188
  function runsAlways(declared, code){
1133
1189
  if(declared==='always')return true;
1134
1190
  if(declared==='once')return false;
@@ -1440,6 +1496,8 @@ function routerSource() {
1440
1496
  if(pushState!==false&&t.href===location.href&&!t.hash&&!force)return Promise.resolve(false);
1441
1497
 
1442
1498
  isNavigating=true;
1499
+ instantNav=instantNext;
1500
+ instantNext=false;
1443
1501
  document.body.classList.add(o.loadingClass);
1444
1502
  startProgress();
1445
1503
 
@@ -1975,6 +2033,7 @@ else {
1975
2033
  }catch(err){reject(err)}
1976
2034
  }
1977
2035
  if(runViewTransition(completeFragSwap)){}
2036
+ else if(instantNav){completeFragSwap()}
1978
2037
  else{currentContent.style.transition='opacity 0.12s ease-out';currentContent.style.opacity='0';setTimeout(function(){completeFragSwap();currentContent.style.opacity='1';setTimeout(function(){currentContent.style.transition=''},150)},120)}
1979
2038
  });
1980
2039
  }
@@ -2389,7 +2448,7 @@ else {
2389
2448
  // ESM, and top-level 'import' is illegal inside a block, which
2390
2449
  // would throw SyntaxError before the script ever runs.
2391
2450
  var alreadyScoped=runsAlways(typeof entry==='string'?'':entry.run,text);
2392
- ns.textContent=(hasImport||alreadyScoped)?text:'{'+text+'}';
2451
+ ns.textContent=(hasImport||alreadyScoped)?text:'{'+text+republishTopLevel(text)+'}';
2393
2452
  ns.setAttribute('data-stx-page','');
2394
2453
  var placeholder=entry.slot?qs('script[data-stx-route-script="'+entry.slot+'"]'):null;
2395
2454
  if(placeholder&&placeholder.parentNode){
@@ -2425,6 +2484,10 @@ else {
2425
2484
  }
2426
2485
  if(runViewTransition(completeSwap)){
2427
2486
  }
2487
+ else if(instantNav){
2488
+ // A tab: swap at once, no fade either way.
2489
+ completeSwap();
2490
+ }
2428
2491
  else {
2429
2492
  // Fallback fade for browsers without View Transitions API
2430
2493
  currentContent.style.transition='opacity 0.12s ease-out';
@@ -2543,6 +2606,7 @@ else {
2543
2606
  e.preventDefault();
2544
2607
  e.stopPropagation();
2545
2608
  log('[router] navigating to:',href);
2609
+ instantNext=link.getAttribute('data-stx-transition')==='none';
2546
2610
  navigate(withCurrentLocale(href));
2547
2611
  });
2548
2612
 
package/dist/serve.js CHANGED
@@ -9800,7 +9800,7 @@ function __stxOverlay(errs){
9800
9800
  rebuildDiscoveredPagePaths(kept);
9801
9801
  await indexPageMiddleware(kept);
9802
9802
  try {
9803
- const { Router } = await import("./chunk-cvtsgd6h.js");
9803
+ const { Router } = await import("./chunk-c7nhgech.js");
9804
9804
  const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
9805
9805
  const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName(), exclude: options.exclude });
9806
9806
  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.382",
4
+ "version": "0.2.384",
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.382",
78
- "stx-router": "0.2.382"
77
+ "@stacksjs/stx": "0.2.384",
78
+ "stx-router": "0.2.384"
79
79
  }
80
80
  }