1(function () { 2 'use strict'; 3 4 const header = document.querySelector( 'header.wp-block-template-part' ); 5 if ( ! header ) return; 6 7 // Temporary: when our header is rendered inside a wrapping template part 8 // that opts in by carrying .ext-header-wrapper (e.g. no-title-sticky- 9 // header.html in the agent plugin), strip the overlay-system classes so 10 // none of our CSS rules fire â the outer wrapper handles layout natively. 11 // Remove once the upstream template stops wrapping. 12 if ( header.closest( '.ext-header-wrapper' ) ) { 13 const overlay = header.querySelector( '.ext-header-overlay' ); 14 if ( overlay ) { 15 overlay.classList.remove( 16 'ext-header-overlay', 17 'ext-header-glass', 18 'ext-header-sticky', 19 'ext-header-sticky--floating-pill', 20 'ext-header--dark' 21 ); 22 } 23 } 24 25 const findHero = () => document.querySelector( 26 '.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child' 27 ); 28 29 new ResizeObserver( function ( entries ) { 30 document.documentElement.style.setProperty( 31 '--ext-header-height', 32 entries[ 0 ].borderBoxSize[ 0 ].blockSize + 'px' 33 ); 34 } ).observe( header, { box: 'border-box' } ); 35 36 // Normal mode: IntersectionObservers against the viewport. 37 // Original behavior, preserved for real frontend pages. 38 const setupNormal = () => { 39 const hero = findHero(); 40 let heroObs; 41 if ( hero ) { 42 heroObs = new IntersectionObserver( function ( entries ) { 43 header.classList.toggle( 'is-past-hero', ! entries[ 0 ].isIntersecting ); 44 }, { rootMargin: '-50% 0px 0px 0px' } ); 45 heroObs.observe( hero ); 46 } 47 48 const sentinel = document.createElement( 'div' ); 49 sentinel.style.cssText = 'position:absolute;top:0;left:0;height:16px;width:1px;pointer-events:none;'; 50 document.body.prepend( sentinel ); 51 52 const scrollObs = new IntersectionObserver( function ( entries ) { 53 header.classList.toggle( 'is-scrolled', ! entries[ 0 ].isIntersecting ); 54 } ); 55 scrollObs.observe( sentinel ); 56 57 return () => { 58 heroObs?.disconnect(); 59 scrollObs.disconnect(); 60 sentinel.remove(); 61 }; 62 }; 63 64 // Agent mode: rAF-throttled scroll/resize listener with CSS-pixel math. 65 // The agent's transform: scale() on .wp-site-blocks breaks 66 // IntersectionObserver geometry, but offsetTop / offsetHeight / scrollTop 67 // are unaffected by transforms â stable at any scale. 68 const setupAgent = ( root ) => { 69 let rafId = 0; 70 const update = () => { 71 rafId = 0; 72 header.classList.toggle( 'is-scrolled', root.scrollTop > 0 ); 73 const hero = findHero(); 74 if ( ! hero ) return; 75 const heroBottom = hero.offsetTop + hero.offsetHeight; 76 header.classList.toggle( 'is-past-hero', root.scrollTop > heroBottom ); 77 }; 78 const schedule = () => { 79 if ( rafId ) return; 80 rafId = requestAnimationFrame( update ); 81 }; 82 83 root.addEventListener( 'scroll', schedule, { passive: true } ); 84 window.addEventListener( 'resize', schedule, { passive: true } ); 85 update(); 86 87 return () => { 88 if ( rafId ) cancelAnimationFrame( rafId ); 89 root.removeEventListener( 'scroll', schedule ); 90 window.removeEventListener( 'resize', schedule ); 91 }; 92 }; 93 94 let teardown; 95 const setup = ( root ) => { 96 teardown?.(); 97 teardown = root ? setupAgent( root ) : setupNormal(); 98 }; 99 100 setup( null ); 101 102 // Optional integration: if the Extendify Agent is active it dispatches 103 // extendify-agent:layout-shift on open/close (see useLayoutShift in 104 // SidebarLayout.jsx). When the agent isn't installed this listener is 105 // simply never invoked â the file works standalone with normal-mode 106 // IntersectionObservers, identical to its original behavior. 107 window.addEventListener( 'extendify-agent:layout-shift', function ( event ) { 108 const open = event?.detail?.open; 109 const root = open ? document.querySelector( '.wp-site-blocks' ) : null; 110 // Wait one frame so the agent's transform / overflow changes commit 111 // before we attach handlers and read geometry. 112 requestAnimationFrame( () => setup( root ) ); 113 } ); 114} )();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.