{"version":3,"file":"ScrollVideo.D2ha_2TM.mjs","names":["useRef","useState","useCallback","p"],"sources":["https:/framerusercontent.com/modules/rqHu2bc3hiTpSmoL5BY5/yZ181cGEqLBZttNkNw5n/ScrollVideo.js"],"sourcesContent":["import{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";import{addPropertyControls,ControlType}from\"framer\";import{useRef,useEffect,useState,useCallback}from\"react\";/**\n * ScrollVideo — Scroll-scrubbed video player (Apple-style).\n * Shows a poster <img> on top until the user scrolls, then switches to video.\n * Works on desktop and mobile (iOS Safari compatible).\n *\n * @framerSupportedLayoutWidth any\n * @framerSupportedLayoutHeight any\n */export default function ScrollVideo(props){const{videoUrl=\"\",posterUrl=\"\",stickyOffset=80,mobileStickyOffset=60,backgroundColor=\"transparent\"}=props;const containerRef=useRef(null);const videoRef=useRef(null);const trackElRef=useRef(null);const videoUnlocked=useRef(false);const hasScrolled=useRef(false);const[showVideo,setShowVideo]=useState(false);// Find the scrollable ancestor\nconst findTrackEl=useCallback(()=>{const container=containerRef.current;if(!container)return null;let el=container.parentElement;while(el){const s=getComputedStyle(el);if(s.position!==\"sticky\"&&(s.overflow===\"clip\"||s.overflow===\"hidden\"||s.overflowY===\"clip\"||s.overflowY===\"hidden\")&&el.offsetHeight>window.innerHeight*1.2){return el;}el=el.parentElement;}if(container.offsetHeight>window.innerHeight*1.2){return container;}el=container.parentElement;while(el){if(el.offsetHeight>window.innerHeight*1.2)return el;el=el.parentElement;}return null;},[]);// iOS Safari: unlock video seeking on first user interaction\nuseEffect(()=>{const video=videoRef.current;if(!video)return;const unlock=()=>{if(videoUnlocked.current)return;videoUnlocked.current=true;const p=video.play();if(p)p.then(()=>video.pause()).catch(()=>{});};window.addEventListener(\"touchstart\",unlock,{once:true,passive:true});window.addEventListener(\"scroll\",unlock,{once:true,passive:true});window.addEventListener(\"click\",unlock,{once:true,passive:true});return()=>{window.removeEventListener(\"touchstart\",unlock);window.removeEventListener(\"scroll\",unlock);window.removeEventListener(\"click\",unlock);};},[videoUrl]);// Main scroll handler\nuseEffect(()=>{const video=videoRef.current;if(!video)return;let scrollCleanup=null;const setupScroll=()=>{const trackEl=findTrackEl();if(!trackEl)return;trackElRef.current=trackEl;let ticking=false;const update=()=>{const rect=trackEl.getBoundingClientRect();const vh=window.innerHeight;const scrollable=Math.max(rect.height-vh,1);const progress=Math.max(0,Math.min(1,-rect.top/scrollable));// Show video once user has scrolled into the section\nif(!hasScrolled.current&&progress>0){hasScrolled.current=true;setShowVideo(true);}const targetTime=progress*video.duration;if(isFinite(targetTime)&&Math.abs(video.currentTime-targetTime)>.01){video.currentTime=targetTime;}ticking=false;};const onScroll=()=>{if(!ticking){ticking=true;requestAnimationFrame(update);}};window.addEventListener(\"scroll\",onScroll,{passive:true});window.addEventListener(\"resize\",onScroll,{passive:true});requestAnimationFrame(update);scrollCleanup=()=>{window.removeEventListener(\"scroll\",onScroll);window.removeEventListener(\"resize\",onScroll);};};const onCanPlay=()=>setupScroll();video.addEventListener(\"canplay\",onCanPlay);video.addEventListener(\"loadeddata\",onCanPlay);if(video.readyState>=2)setupScroll();const retryTimer=setInterval(()=>{if(!trackElRef.current)setupScroll();else clearInterval(retryTimer);},200);const retryClear=setTimeout(()=>clearInterval(retryTimer),5e3);return()=>{video.removeEventListener(\"canplay\",onCanPlay);video.removeEventListener(\"loadeddata\",onCanPlay);clearInterval(retryTimer);clearTimeout(retryClear);scrollCleanup?.();};},[videoUrl,findTrackEl]);const isTransparent=c=>!c||c===\"transparent\"||c===\"rgba(0, 0, 0, 0)\"||c===\"rgba(0,0,0,0)\";const cssVars=`\n        .scroll-video-sticky {\n            position: sticky;\n            top: ${stickyOffset}px;\n            height: calc(100vh - ${stickyOffset}px);\n        }\n        .scroll-video-media {\n            object-position: center center;\n        }\n        @media (max-width: 810px) {\n            .scroll-video-sticky {\n                top: ${mobileStickyOffset}px;\n                height: calc(100vh - ${mobileStickyOffset}px);\n            }\n            .scroll-video-media {\n                object-position: center top;\n            }\n        }\n    `;const mediaStyle={width:\"100%\",height:\"100%\",objectFit:\"contain\",display:\"block\",position:\"absolute\",top:0,left:0};return /*#__PURE__*/_jsxs(\"div\",{ref:containerRef,style:{width:\"100%\",height:\"100%\",position:\"relative\",backgroundColor:isTransparent(backgroundColor)?\"transparent\":backgroundColor,overflow:\"visible\"},children:[/*#__PURE__*/_jsx(\"style\",{children:cssVars}),/*#__PURE__*/_jsx(\"div\",{className:\"scroll-video-sticky\",style:{width:\"100%\",display:\"flex\",alignItems:\"center\",justifyContent:\"center\",overflow:\"hidden\"},children:/*#__PURE__*/_jsxs(\"div\",{style:{position:\"relative\",width:\"100%\",height:\"100%\"},children:[/*#__PURE__*/_jsx(\"video\",{ref:videoRef,className:\"scroll-video-media\",src:videoUrl,muted:true,playsInline:true,preload:\"auto\",crossOrigin:\"anonymous\",style:{...mediaStyle,opacity:showVideo?1:0}}),posterUrl&&/*#__PURE__*/_jsx(\"img\",{src:posterUrl,className:\"scroll-video-media\",alt:\"\",style:{...mediaStyle,opacity:showVideo?0:1,transition:\"opacity 0.3s ease\"}})]})})]});}addPropertyControls(ScrollVideo,{videoUrl:{title:\"Video URL\",type:ControlType.String,defaultValue:\"\",description:\"URL of the scroll-scrubbed video (MP4 or WebM)\"},posterUrl:{title:\"Poster Image\",type:ControlType.String,defaultValue:\"\",description:\"First frame image — shows instantly before video loads\"},stickyOffset:{title:\"Sticky Top\",type:ControlType.Number,defaultValue:80,min:0,max:200,step:10,unit:\"px\",description:\"Top offset for the sticky video on desktop\"},mobileStickyOffset:{title:\"Mobile Sticky Top\",type:ControlType.Number,defaultValue:60,min:0,max:200,step:10,unit:\"px\",description:\"Top offset for the sticky video on mobile (≤810px)\"},backgroundColor:{title:\"Background\",type:ControlType.Color,defaultValue:\"transparent\"}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"ScrollVideo\",\"slots\":[],\"annotations\":{\"framerSupportedLayoutWidth\":\"any\",\"framerContractVersion\":\"1\",\"framerSupportedLayoutHeight\":\"any\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./ScrollVideo.map"],"mappings":"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"}