stx-router 0.2.325 → 0.2.326

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 +27 -11
  2. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -1046,8 +1046,7 @@ else {
1046
1046
  // Remove old page scripts
1047
1047
  document.querySelectorAll('script[data-stx-page]').forEach(function(s){s.remove()});
1048
1048
  if(pushState!==false)writeHistory(pushState,url+(hash||''));
1049
- updateNav();
1050
- updateActiveLinks();
1049
+ refreshCurrentLinks();
1051
1050
  if(o.scrollToTop&&!hash)window.scrollTo({top:0,behavior:'instant'});
1052
1051
  else if(hash){var el=document.querySelector(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
1053
1052
  window.dispatchEvent(new CustomEvent('stx:navigate',{detail:{url:url}}));
@@ -1497,8 +1496,7 @@ else {
1497
1496
  if(pushState!==false)writeHistory(pushState,url+(hash||''));
1498
1497
 
1499
1498
  // Update active nav links
1500
- updateNav();
1501
- updateActiveLinks();
1499
+ refreshCurrentLinks();
1502
1500
 
1503
1501
  // Scroll
1504
1502
  if(o.scrollToTop&&!hash)window.scrollTo({top:0,behavior:'instant'});
@@ -1906,7 +1904,14 @@ else {
1906
1904
  // Null for links the router does not own (another origin, a bare #fragment,
1907
1905
  // anything unparseable), which are left exactly as the server rendered them.
1908
1906
  function normPath(p){return p.length>1&&p.charAt(p.length-1)==='/'?p.slice(0,-1):p}
1909
- function linkState(href){
1907
+ // Paths beyond the link's own that make it current: a tab bar's Calendar
1908
+ // tab stays lit on a workout opened from it (data-stx-active-match, a
1909
+ // space-separated list of path prefixes).
1910
+ function matchesAny(list,cur){
1911
+ if(!list)return false;
1912
+ return list.split(/\\s+/).some(function(p){p=normPath(p);return p&&(cur===p||cur.indexOf(p+'/')===0)});
1913
+ }
1914
+ function linkState(href,also){
1910
1915
  if(!href||href.charAt(0)==='#')return null;
1911
1916
  var u;
1912
1917
  try{u=new URL(href,location.href)}catch(e){return null}
@@ -1918,27 +1923,39 @@ else {
1918
1923
  // point at this path, exactly one is.
1919
1924
  var have=new URLSearchParams(location.search),q=true;
1920
1925
  u.searchParams.forEach(function(v,k){if(have.getAll(k).indexOf(v)===-1)q=false});
1926
+ var matched=matchesAny(also,cur);
1921
1927
  return {
1922
1928
  exact:q&&path===cur,
1923
- active:q&&(path==='/'?cur==='/':(cur===path||cur.indexOf(path+'/')===0))
1929
+ active:q&&(path==='/'?cur==='/':(cur===path||cur.indexOf(path+'/')===0))||matched,
1930
+ matched:matched
1924
1931
  };
1925
1932
  }
1926
1933
 
1927
1934
  function updateNav(){
1928
1935
  document.querySelectorAll('nav a[href], #mobileNav a[href], [data-stx-nav] a[href]').forEach(function(a){
1929
1936
  if(!a.hasAttribute('data-stx-link'))return;
1930
- var st=linkState(a.getAttribute('href'));
1937
+ var st=linkState(a.getAttribute('href'),a.getAttribute('data-stx-active-match'));
1931
1938
  if(!st)return;
1932
1939
  var ac=a.getAttribute('data-stx-active-class')||'active';
1933
- if(st.exact)ac.split(' ').forEach(function(cls){if(cls)a.classList.add(cls)});else ac.split(' ').forEach(function(cls){if(cls)a.classList.remove(cls)});
1940
+ if(st.exact||st.matched)ac.split(' ').forEach(function(cls){if(cls)a.classList.add(cls)});else ac.split(' ').forEach(function(cls){if(cls)a.classList.remove(cls)});
1934
1941
  });
1935
1942
  }
1936
1943
 
1944
+ // Both passes, always in this order. A link inside a <nav> is current only on
1945
+ // its own page (or one it names in data-stx-active-match), so updateNav has
1946
+ // the last word. Navigation used to run them the other way round, which lit
1947
+ // a nav's parent links by prefix after an in-app navigation but not after a
1948
+ // full load of the same URL.
1949
+ function refreshCurrentLinks(){
1950
+ updateActiveLinks();
1951
+ updateNav();
1952
+ }
1953
+
1937
1954
  function updateActiveLinks(){
1938
1955
  // Update active classes on <stx-link> elements (and legacy data-stx-link)
1939
1956
  var links=document.querySelectorAll('[data-stx-link]');
1940
1957
  links.forEach(function(link){
1941
- var st=linkState(link.getAttribute('to')||link.getAttribute('href')||'');
1958
+ var st=linkState(link.getAttribute('to')||link.getAttribute('href')||'',link.getAttribute('data-stx-active-match'));
1942
1959
  if(!st)return;
1943
1960
  var ac=link.getAttribute('active-class')||link.getAttribute('data-stx-active-class')||'active';
1944
1961
  var eac=link.getAttribute('exact-active-class')||link.getAttribute('data-stx-exact-active-class')||'exact-active';
@@ -2069,8 +2086,7 @@ else {
2069
2086
  function init(){
2070
2087
  injectStyles();
2071
2088
  injectViewTransitionCSS();
2072
- updateActiveLinks();
2073
- updateNav();
2089
+ refreshCurrentLinks();
2074
2090
  }
2075
2091
 
2076
2092
  if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else init();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stx-router",
3
3
  "type": "module",
4
- "version": "0.2.325",
4
+ "version": "0.2.326",
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",