{"version":3,"file":"SmoothScrollControl.CbPYbafg.mjs","names":[],"sources":["https:/framerusercontent.com/modules/3xQjmSVQlIuTzOXxuMdb/zfCn88Zdx6wUeNLLFBAn/SmoothScrollControl.js"],"sourcesContent":["// SmoothScrollControl.tsx — Custom smooth scroll for Cohestra\n// A self-contained, dependency-free smoothness controller.\n// It eases the REAL native scroll position (window.scrollTo), so position:sticky,\n// fixed headers and anchor jumps keep working — unlike transform-based smoothers.\n//\n// This is a standalone alternative to the marketplace \"Smooth Scroll\" component.\n// Both can live in the project at once; enable only ONE per page while testing.\nimport{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";import{useEffect}from\"react\";import{addPropertyControls,ControlType,RenderTarget}from\"framer\";// Starts the smoothing engine and returns a cleanup function.\nfunction startEngine(opts){const{smoothness,wheelStrength,keyboard,smoothTouch}=opts;// Respect user + device preferences — fall back to native scrolling.\nconst reduceMotion=window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;if(reduceMotion)return()=>{};const isTouch=window.matchMedia(\"(pointer: coarse)\").matches;if(isTouch&&!smoothTouch)return()=>{};const doc=document.documentElement;let target=window.scrollY;let current=window.scrollY;let lastAppliedY=window.scrollY// last position WE set — used to ignore our own scroll events\n;let rafId=0;let running=false;let lastTime=0;// \"smoothness\" (0.2–2) maps to a catch-up time constant in ms.\n// Bigger value = longer glide = smoother/heavier feel.\nconst tau=Math.max(45,smoothness*150);const maxScroll=()=>Math.max(0,doc.scrollHeight-window.innerHeight);const clamp=v=>Math.min(Math.max(v,0),maxScroll());const apply=y=>{const rounded=Math.round(y);window.scrollTo(0,rounded);lastAppliedY=rounded;};const step=time=>{if(!lastTime)lastTime=time;// Cap dt so returning to a backgrounded tab doesn't cause a jump.\nconst dt=Math.min(64,time-lastTime);lastTime=time;const diff=target-current;if(Math.abs(diff)<.4){current=target;apply(current);running=false;lastTime=0;return;}// Frame-rate independent exponential damping (works on 60/120/144Hz).\nconst alpha=1-Math.exp(-dt/tau);current+=diff*alpha;apply(current);rafId=requestAnimationFrame(step);};const startLoop=()=>{if(running)return;running=true;lastTime=0;rafId=requestAnimationFrame(step);};// Let genuinely-scrollable inner areas (modals, dropdowns, code blocks) keep\n// native scrolling. Also honors an explicit opt-out via [data-native-scroll].\nconst shouldLetNativeHandle=(node,deltaY)=>{let el=node;while(el&&el!==document.body&&el!==doc){if(el.nodeType===1){if(el.hasAttribute(\"data-native-scroll\"))return true;const s=getComputedStyle(el);const oy=s.overflowY;if((oy===\"auto\"||oy===\"scroll\")&&el.scrollHeight>el.clientHeight){const atTop=el.scrollTop<=0;const atBottom=el.scrollTop+el.clientHeight>=el.scrollHeight-1;if(deltaY<0&&!atTop)return true;if(deltaY>0&&!atBottom)return true;}}el=el.parentElement;}return false;};const onWheel=e=>{if(e.ctrlKey)return;// pinch-to-zoom\nif(shouldLetNativeHandle(e.target,e.deltaY))return;let delta=e.deltaY;if(e.deltaMode===1)delta*=16// deltaMode: lines\n;else if(e.deltaMode===2)delta*=window.innerHeight// deltaMode: pages\n;e.preventDefault();target=clamp(target+delta*wheelStrength);startLoop();};const onKey=e=>{if(!keyboard)return;const t=e.target;const tag=t?.tagName||\"\";if(/INPUT|TEXTAREA|SELECT/.test(tag)||t?.isContentEditable)return;const vh=window.innerHeight;let handled=true;switch(e.key){case\"ArrowDown\":target=clamp(target+90);break;case\"ArrowUp\":target=clamp(target-90);break;case\"PageDown\":target=clamp(target+vh*.9);break;case\"PageUp\":target=clamp(target-vh*.9);break;case\" \":target=clamp(target+(e.shiftKey?-1:1)*vh*.9);break;case\"Home\":target=clamp(0);break;case\"End\":target=clamp(maxScroll());break;default:handled=false;}if(handled){e.preventDefault();startLoop();}};// Adopt scroll changes we didn't cause (scrollbar drag, hash navigation, etc.).\n// Scroll events fire asynchronously, so we can't rely on a sync flag — instead we\n// compare against the last position we set. A meaningful difference means an\n// external source moved the page, so we re-sync to it.\nconst onScroll=()=>{if(Math.abs(window.scrollY-lastAppliedY)<=2)return;// our own scroll\ntarget=window.scrollY;current=window.scrollY;lastAppliedY=window.scrollY;};const onResize=()=>{target=clamp(target);};window.addEventListener(\"wheel\",onWheel,{passive:false});window.addEventListener(\"keydown\",onKey);window.addEventListener(\"scroll\",onScroll,{passive:true});window.addEventListener(\"resize\",onResize);return()=>{cancelAnimationFrame(rafId);window.removeEventListener(\"wheel\",onWheel);window.removeEventListener(\"keydown\",onKey);window.removeEventListener(\"scroll\",onScroll);window.removeEventListener(\"resize\",onResize);};}const badgeStyle={display:\"inline-flex\",alignItems:\"center\",gap:8,padding:\"8px 12px\",borderRadius:8,background:\"#0c0a09\",color:\"#fafaf9\",fontFamily:\"Inter, sans-serif\",fontSize:12,fontWeight:600,whiteSpace:\"nowrap\",border:\"1px solid #e11d0022\"};/**\n * Smooth Scroll (Custom)\n *\n * @framerIntrinsicWidth 220\n * @framerIntrinsicHeight 40\n *\n * @framerSupportedLayoutWidth any-prefer-fixed\n * @framerSupportedLayoutHeight any-prefer-fixed\n */export default function SmoothScrollControl(props){const{enabled=true,smoothness=.8,wheelStrength=1,keyboard=true,smoothTouch=false}=props;const onCanvas=RenderTarget.current()===RenderTarget.canvas;useEffect(()=>{if(onCanvas)return;if(!enabled)return;const cleanup=startEngine({smoothness,wheelStrength,keyboard,smoothTouch});return cleanup;},[onCanvas,enabled,smoothness,wheelStrength,keyboard,smoothTouch]);// Invisible on the live site; a small badge in the editor so it's selectable.\nif(onCanvas){return /*#__PURE__*/_jsx(\"div\",{style:badgeStyle,children:/*#__PURE__*/_jsxs(\"span\",{children:[\"⟳ Smooth Scroll (custom)\",enabled?\"\":\" \\xb7 off\"]})});}return null;}addPropertyControls(SmoothScrollControl,{enabled:{type:ControlType.Boolean,title:\"Enabled\",defaultValue:true,enabledTitle:\"On\",disabledTitle:\"Off\"},smoothness:{type:ControlType.Number,title:\"Smoothness\",defaultValue:.8,min:.2,max:2,step:.05,description:\"Higher = smoother, longer glide\"},wheelStrength:{type:ControlType.Number,title:\"Wheel\",defaultValue:1,min:.3,max:2.5,step:.05,description:\"Scroll speed multiplier\"},keyboard:{type:ControlType.Boolean,title:\"Keyboard\",defaultValue:true,enabledTitle:\"On\",disabledTitle:\"Off\"},smoothTouch:{type:ControlType.Boolean,title:\"Touch\",defaultValue:false,enabledTitle:\"Smooth\",disabledTitle:\"Native\",description:\"Smooth scrolling on touch devices\"}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"SmoothScrollControl\",\"slots\":[],\"annotations\":{\"framerSupportedLayoutWidth\":\"any-prefer-fixed\",\"framerIntrinsicWidth\":\"220\",\"framerSupportedLayoutHeight\":\"any-prefer-fixed\",\"framerContractVersion\":\"1\",\"framerIntrinsicHeight\":\"40\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./SmoothScrollControl.map"],"mappings":"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"}