{"version":3,"file":"Scroll_effect.B2ninAVy.mjs","names":["useRef","useState"],"sources":["https:/framerusercontent.com/modules/DsHt1ILtwAIQsUPpZARk/0w3f20iL6E9JpKsUIX4J/Scroll_effect.js"],"sourcesContent":["import{jsx as _jsx}from\"react/jsx-runtime\";import{useEffect,useRef,useState}from\"react\";import{useScroll,useMotionValue,useMotionValueEvent}from\"framer-motion\";// Animation completes at this fraction of the scroll range.\n// The remainder acts as a pause on the last card.\n// 0.85 = finish at 85%, hold for the final 15%.\nconst COMPLETE_AT=.85;// ---------------------------------------------\n// Shared: runs a measurement now, again as layout settles,\n// and on resize. Framer is rarely final on first paint.\n// ---------------------------------------------\nfunction useRetryMeasure(measure){const fn=useRef(measure);fn.current=measure;useEffect(()=>{const run=()=>fn.current();run();const timers=[100,400,1e3].map(ms=>setTimeout(run,ms));window.addEventListener(\"resize\",run);window.addEventListener(\"load\",run);return()=>{timers.forEach(clearTimeout);window.removeEventListener(\"resize\",run);window.removeEventListener(\"load\",run);};},[]);}// ---------------------------------------------\n// Shared: measures the scroll range spanned by the steps.\n// Any rendered element with an ID of step-1, step-2, step-3...\n// counts. Order comes from measured position, not the number,\n// so hidden breakpoint duplicates can't invert the range.\n// Returns null until it has a valid measurement — callers\n// must treat null as \"don't move anything yet\".\n// ---------------------------------------------\nfunction useStepRange(){const[range,setRange]=useState(null);useRetryMeasure(()=>{const steps=Array.from(document.querySelectorAll('[id^=\"step-\"]')).filter(el=>{if(!/^step-\\d+$/.test(el.id))return false;const r=el.getBoundingClientRect();// skip hidden breakpoint variants (zero-size rects)\nreturn r.height>0&&r.width>0;});if(steps.length===0){console.log(\"step range: no visible steps found\");return;}const scrollTop=window.scrollY;let top=Infinity;let bottom=-Infinity;for(const el of steps){const r=el.getBoundingClientRect();top=Math.min(top,r.top+scrollTop);bottom=Math.max(bottom,r.bottom+scrollTop);}const start=top;const end=bottom-window.innerHeight;if(end<=start){console.log(\"step range: invalid, ignoring\",{steps:steps.length,start,end});return;}console.log(\"step range:\",{steps:steps.length,ids:steps.map(s=>s.id),start,end});setRange([start,end]);});return range;}// progress 0..1 across the range, finishing early per COMPLETE_AT\nfunction scrubProgress(y,start,end){const raw=(y-start)/(end-start);return Math.min(Math.max(raw/COMPLETE_AT,0),1);}// ---------------------------------------------\n// Van — apply to the Van layer.\n// Van sits inside a full-width track, Position Absolute, Right = 0.\n// Travel distance measured against #cards-viewport.\n// ---------------------------------------------\nexport function withVanScrub(Component){return props=>{const vanRef=useRef(null);const{scrollY}=useScroll();const range=useStepRange();const x=useMotionValue(0);const dist=useRef(0);const rangeRef=useRef(range);rangeRef.current=range;useRetryMeasure(()=>{const van=vanRef.current;const viewport=document.querySelector(\"#cards-viewport\");if(!van||!viewport){console.log(\"van scrub: missing\",{van,viewport});return;}dist.current=Math.max(viewport.getBoundingClientRect().width-van.getBoundingClientRect().width,0);console.log(\"van scrub distance:\",dist.current);});useMotionValueEvent(scrollY,\"change\",y=>{const r=rangeRef.current;if(!r)return;x.set(-scrubProgress(y,r[0],r[1])*dist.current);});return /*#__PURE__*/_jsx(Component,{...props,ref:vanRef,style:{...props.style,x}});};}// ---------------------------------------------\n// Cards — apply to the Tabs stack (holds the cards).\n// Education Slider Sticky: Scroll Section name = cards-viewport,\n// Width = Fill, Overflow = Visible.\n// Tabs: horizontal stack, hugs its fixed-width cards.\n// Sideways input steers vertical scroll, so both\n// directions drive the same animation.\n// ---------------------------------------------\nexport function withCardsScrub(Component){return props=>{const ref=useRef(null);const{scrollY}=useScroll();const range=useStepRange();const x=useMotionValue(0);const dist=useRef(0);const rangeRef=useRef(range);rangeRef.current=range;// travel distance: content width minus viewport width\nuseRetryMeasure(()=>{const el=ref.current;const viewport=document.querySelector(\"#cards-viewport\");if(!el||!viewport){console.log(\"cards scrub: missing\",{el,viewport});return;}let contentWidth=Math.max(el.getBoundingClientRect().width,el.scrollWidth);for(const child of Array.from(el.children)){contentWidth=Math.max(contentWidth,child.scrollWidth,child.getBoundingClientRect().width);}dist.current=Math.max(contentWidth-viewport.getBoundingClientRect().width,0);console.log(\"cards scrub distance:\",dist.current);});// vertical page scroll is the single source of truth\nuseMotionValueEvent(scrollY,\"change\",y=>{const r=rangeRef.current;if(!r)return;x.set(-scrubProgress(y,r[0],r[1])*dist.current);});// sideways input steers the page's vertical scroll,\n// so cards, van and steps all stay in sync\nconst sidewaysToVertical=deltaX=>{const r=rangeRef.current;if(!r||dist.current===0)return;const factor=(r[1]-r[0])*COMPLETE_AT/dist.current;window.scrollBy(0,deltaX*factor);};useEffect(()=>{const el=ref.current;if(!el)return;const onWheel=e=>{if(Math.abs(e.deltaX)<=Math.abs(e.deltaY))return;e.preventDefault();sidewaysToVertical(e.deltaX);};el.addEventListener(\"wheel\",onWheel,{passive:false});return()=>el.removeEventListener(\"wheel\",onWheel);},[]);// touch: horizontal drag steers vertical scroll too\nuseEffect(()=>{const el=ref.current;if(!el)return;let lastX=0;let active=false;const down=e=>{lastX=e.touches[0].clientX;active=true;};const move=e=>{if(!active)return;const cur=e.touches[0].clientX;const deltaX=lastX-cur;lastX=cur;if(Math.abs(deltaX)>0)sidewaysToVertical(deltaX);};const up=()=>active=false;el.addEventListener(\"touchstart\",down,{passive:true});el.addEventListener(\"touchmove\",move,{passive:true});el.addEventListener(\"touchend\",up);return()=>{el.removeEventListener(\"touchstart\",down);el.removeEventListener(\"touchmove\",move);el.removeEventListener(\"touchend\",up);};},[]);return /*#__PURE__*/_jsx(Component,{...props,ref:ref,style:{...props.style,x}});};}\nexport const __FramerMetadata__ = {\"exports\":{\"withVanScrub\":{\"type\":\"reactHoc\",\"name\":\"withVanScrub\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withCardsScrub\":{\"type\":\"reactHoc\",\"name\":\"withCardsScrub\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./Scroll_effect.map"],"mappings":"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"}