stx-router 0.2.383 → 0.2.385

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.
Files changed (2) hide show
  1. package/dist/client.js +37 -20
  2. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -182,8 +182,14 @@ function routerSource() {
182
182
  log('[router] build skew: page is',loadedBuild,'server is',incoming,'\u2014 full navigation');
183
183
  location.href=url;
184
184
  }
185
+ // A link marked data-stx-transition="none" swaps without the cross-fade. A
186
+ // tab bar is the case: iOS switches tabs instantly, and the fade read as a
187
+ // quarter-second lag on every tap in a phone app. Set by the click that
188
+ // started the navigation, so programmatic and history navigations keep it.
189
+ var instantNext=false;
190
+ var instantNav=false;
185
191
  function runViewTransition(callback){
186
- if(!o.viewTransitions||!document.startViewTransition)return false;
192
+ if(instantNav||!o.viewTransitions||!document.startViewTransition)return false;
187
193
  try{
188
194
  var transition=document.startViewTransition(callback);
189
195
  var onAbort=function(err){log('[router] view transition aborted:',err&&err.message?err.message:err)};
@@ -210,19 +216,28 @@ function routerSource() {
210
216
  progEl.style.opacity=progVal>0?'1':'0';
211
217
  progEl.style.transform='scaleX('+(progVal/100)+')';
212
218
  }
219
+ // Shown only for a navigation that is actually waiting. A page served from
220
+ // the prefetch cache swaps in a few milliseconds, and drawing then fading a
221
+ // bar for it made every instant navigation look like a load.
222
+ var progDelay=null;
213
223
  function startProgress(){
214
224
  if(!o.progress||!progEl)return;
215
225
  if(progTimer){clearInterval(progTimer);progTimer=null}
216
- setProgress(8);
217
- progTimer=setInterval(function(){
218
- if(progVal>=90)return;
219
- // Asymptotic trickle \u2014 fast at first, slower near 90%
220
- var inc=Math.max(0.4,(90-progVal)*0.08);
221
- setProgress(progVal+inc);
222
- },160);
226
+ if(progDelay)clearTimeout(progDelay);
227
+ progDelay=setTimeout(function(){
228
+ progDelay=null;
229
+ setProgress(8);
230
+ progTimer=setInterval(function(){
231
+ if(progVal>=90)return;
232
+ // Asymptotic trickle \u2014 fast at first, slower near 90%
233
+ var inc=Math.max(0.4,(90-progVal)*0.08);
234
+ setProgress(progVal+inc);
235
+ },160);
236
+ },150);
223
237
  }
224
238
  function finishProgress(){
225
239
  if(!o.progress||!progEl)return;
240
+ if(progDelay){clearTimeout(progDelay);progDelay=null;return}
226
241
  if(progTimer){clearInterval(progTimer);progTimer=null}
227
242
  setProgress(100);
228
243
  // Fade out, then reset. Delays chosen so the "full" state is briefly
@@ -499,19 +514,13 @@ function routerSource() {
499
514
  * Column-anchored: a declaration nested inside a function is indented, and
500
515
  * is not in scope at the end of the block anyway.
501
516
  */
502
- var TOP_LEVEL_DECL=/^(?:export\\s+)?(?:async\\s+)?(?:function\\s*\\*?|class|const|let|var)\\s+([A-Za-z_$][\\w$]*)/gm;
517
+ var TLD=/^(?:export\\s+)?(?:async\\s+)?(?:function\\s*\\*?|class|const|let|var)\\s+([$\\w]+)/gm;
503
518
  function republishTopLevel(src){
504
- var names=[],m;
505
- TOP_LEVEL_DECL.lastIndex=0;
506
- while((m=TOP_LEVEL_DECL.exec(src))!==null){
507
- if(names.indexOf(m[1])===-1)names.push(m[1]);
508
- }
509
- if(!names.length)return '';
510
- var out='\\n;';
511
- for(var i=0;i<names.length;i++){
512
- out+='try{if(typeof '+names[i]+'==="function")window.'+names[i]+'='+names[i]+'}catch(e){}';
513
- }
514
- return out;
519
+ var n=[],m,o='',i;
520
+ TLD.lastIndex=0;
521
+ while((m=TLD.exec(src))!==null)if(n.indexOf(m[1])<0)n.push(m[1]);
522
+ for(i=0;i<n.length;i++)o+='try{typeof '+n[i]+'=="function"&&(window.'+n[i]+'='+n[i]+')}catch(e){}';
523
+ return o?'\\n;'+o:'';
515
524
  }
516
525
  function runsAlways(declared, code){
517
526
  if(declared==='always')return true;
@@ -824,6 +833,8 @@ function routerSource() {
824
833
  if(pushState!==false&&t.href===location.href&&!t.hash&&!force)return Promise.resolve(false);
825
834
 
826
835
  isNavigating=true;
836
+ instantNav=instantNext;
837
+ instantNext=false;
827
838
  document.body.classList.add(o.loadingClass);
828
839
  startProgress();
829
840
 
@@ -1359,6 +1370,7 @@ else {
1359
1370
  }catch(err){reject(err)}
1360
1371
  }
1361
1372
  if(runViewTransition(completeFragSwap)){}
1373
+ else if(instantNav){completeFragSwap()}
1362
1374
  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)}
1363
1375
  });
1364
1376
  }
@@ -1809,6 +1821,10 @@ else {
1809
1821
  }
1810
1822
  if(runViewTransition(completeSwap)){
1811
1823
  }
1824
+ else if(instantNav){
1825
+ // A tab: swap at once, no fade either way.
1826
+ completeSwap();
1827
+ }
1812
1828
  else {
1813
1829
  // Fallback fade for browsers without View Transitions API
1814
1830
  currentContent.style.transition='opacity 0.12s ease-out';
@@ -1927,6 +1943,7 @@ else {
1927
1943
  e.preventDefault();
1928
1944
  e.stopPropagation();
1929
1945
  log('[router] navigating to:',href);
1946
+ instantNext=link.getAttribute('data-stx-transition')==='none';
1930
1947
  navigate(withCurrentLocale(href));
1931
1948
  });
1932
1949
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stx-router",
3
3
  "type": "module",
4
- "version": "0.2.383",
4
+ "version": "0.2.385",
5
5
  "description": "File-based router for STX — .stx template discovery, nested layouts, typed route params, middleware, and client-side SPA navigation.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",