stx-router 0.2.450 → 0.2.452

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 +42 -10
  2. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -678,6 +678,34 @@ function routerSource() {
678
678
  var head=code.trimStart();
679
679
  return head.charAt(0)==='('||head.charAt(0)===';';
680
680
  }
681
+ // A component rendered inside a client loop is not an instance yet. Its root
682
+ // and scoped setup script sit in the loop's SOURCE -- the element carrying
683
+ // :for, or a descendant of it, as in <tr :for> > <td> > <Avatar> -- which
684
+ // bindFor turns into the row template and clones per item. The runtime runs
685
+ // the setup once per clone (hydrateComponentScopes), but only from a script
686
+ // that still carries data-stx-scoped and its code.
687
+ //
688
+ // Only the shape where the component root is itself the :for element was
689
+ // recognised. A component one level down was run here in place instead,
690
+ // registering a scope for markup that bindFor discards, and its placeholder
691
+ // was replaced by an executed script without data-stx-scoped. Every row
692
+ // cloned from that template had no setup to run: the props reached the row's
693
+ // root, but its own :if/:src stayed raw. Only on a routed visit, which is
694
+ // when a store already holds the rows, so it read as a timing bug.
695
+ function hasLoopAttr(el){
696
+ return el.hasAttribute('@for')||el.hasAttribute(':for')||el.hasAttribute('x-for');
697
+ }
698
+ function loopOwnsScopedScript(script,code){
699
+ if(!script)return false;
700
+ for(var cursor=script.parentNode;cursor&&cursor.nodeType===1;cursor=cursor.parentNode){
701
+ if(hasLoopAttr(cursor))return true;
702
+ }
703
+ var root=script.previousSibling;
704
+ while(root&&((root.nodeType===3&&!(root.textContent||'').trim())||root.nodeType===8))root=root.previousSibling;
705
+ if(!root||root.nodeType!==1||!root.hasAttribute('data-stx-scope')||!hasLoopAttr(root))return false;
706
+ var scopeId=root.getAttribute('data-stx-scope');
707
+ return !!scopeId&&code.indexOf(scopeId)!==-1;
708
+ }
681
709
  // A component scope script names the root it binds in data-stx-owner (#1958).
682
710
  // On navigation it runs only for a root that just ARRIVED: one swapped in
683
711
  // with the new content, which is not bound yet. A layout component that
@@ -1625,16 +1653,7 @@ else {
1625
1653
  if(template.contains(placeholder)||(template.content&&template.content.contains(placeholder)))
1626
1654
  nestedScopedTemplate=true;
1627
1655
  });
1628
- var loopRoot=placeholder.previousSibling;
1629
- while(loopRoot&&(
1630
- (loopRoot.nodeType===3&&!(loopRoot.textContent||'').trim())
1631
- ||loopRoot.nodeType===8
1632
- ))loopRoot=loopRoot.previousSibling;
1633
- if(loopRoot&&loopRoot.nodeType===1&&loopRoot.hasAttribute('data-stx-scope')
1634
- &&(loopRoot.hasAttribute(':for')||loopRoot.hasAttribute('@for')||loopRoot.hasAttribute('x-for'))){
1635
- var loopScopeId=loopRoot.getAttribute('data-stx-scope');
1636
- scopedLoopSetup=!!loopScopeId&&code.indexOf(loopScopeId)!==-1;
1637
- }
1656
+ scopedLoopSetup=loopOwnsScopedScript(placeholder,code);
1638
1657
  }
1639
1658
  if(entry.scoped&&(!placeholder||!placeholder.parentNode||nestedScopedTemplate||scopedLoopSetup)){
1640
1659
  log('[router] leaving loop-scoped script for component hydration');
@@ -1901,6 +1920,9 @@ else {
1901
1920
  var executable=!type||type==='text/javascript'||type==='application/javascript'||type==='module';
1902
1921
  if(!executable||!text.trim())return;
1903
1922
  if(isSignalsRuntimeScript(s,text)||text.indexOf('__stxRouter')!==-1){s.remove();return}
1923
+ // Loop-owned component setup stays inert with its code, as the
1924
+ // fragment path leaves it: bindFor runs it per row.
1925
+ if(s.hasAttribute('data-stx-scoped')&&loopOwnsScopedScript(s,text)){s.setAttribute('type','application/stx-pending');return}
1904
1926
  var slot='document-'+(++routedBodyScriptId);
1905
1927
  var setupName=generatedSetupName(text);
1906
1928
  if(setupName)incomingSetupName=setupName;
@@ -1925,6 +1947,10 @@ else {
1925
1947
  document.body.innerHTML=bodyHTML;
1926
1948
  // Copy body attributes (class, data-stx, etc.)
1927
1949
  Array.from(newBody.attributes).forEach(function(attr){document.body.setAttribute(attr.name,attr.value)});
1950
+ // Copying only adds. data-stx names the page setup that stx:load falls
1951
+ // back to when no _latestSetup is set, so the outgoing page's name left
1952
+ // behind on a destination without one ran the page being left.
1953
+ if(!newBody.hasAttribute('data-stx'))document.body.removeAttribute('data-stx');
1928
1954
  // Update layout meta tag
1929
1955
  var oldMeta=qs(LAYOUT_META);
1930
1956
  var freshMeta=doc.querySelector(LAYOUT_META);
@@ -2113,6 +2139,12 @@ else {
2113
2139
 
2114
2140
  // Execute page scripts FIRST \u2014 they define setup functions and set _latestSetup
2115
2141
  function execScripts(){
2142
+ // The outgoing page's setup is not this page's. A destination whose
2143
+ // script defines no __stx_setup_ (a page that only calls useHead, say)
2144
+ // left it in place, and stx:load ran it again here: its effects, its
2145
+ // onMount -- HQ's calendar wrote ?athlete_id into /relax. Fragments
2146
+ // never hit this only because the server prepends the same clear.
2147
+ if(window.stx)window.stx._latestSetup=null;
2116
2148
  scripts.forEach(function(entry){
2117
2149
  var text=typeof entry==='string'?entry:entry.text;
2118
2150
  var runAlways=typeof entry==='string'?false:entry.runAlways;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stx-router",
3
3
  "type": "module",
4
- "version": "0.2.450",
4
+ "version": "0.2.452",
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",