{"version":3,"file":"BackgroundVideo.BmbYCqB2.mjs","names":["useRef","useState"],"sources":["https:/framerusercontent.com/modules/aWcblQx8JuBETNt5smgC/ngqdhk5uHHmiv4PwABu4/BackgroundVideo.js"],"sourcesContent":["import{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";import{addPropertyControls,ControlType,RenderTarget,useIsStaticRenderer}from\"framer\";import{useEffect,useRef,useState}from\"react\";// Below this an element contributes nothing worth decoding for.\nconst OPACITY_FLOOR=.02;// A layer has to be near enough to solid before it counts as hiding another.\nconst COVER_OPACITY=.99;// Comfortably longer than the 0.5s cross-fade these layers use.\nconst SETTLE_MS=700;// How long a clip may sit selected-but-frameless before its AV1 source is\n// given up on. A fetch that is still in flight is exempt, so this only has\n// to outlast a decoder that has gone quiet.\nconst STALL_MS=6e3;// Read out of the encoded file's own av1C box rather than guessed: profile 0,\n// level 4.0, Main tier, 8-bit. If this string is wrong the browser silently\n// skips the AV1 source and takes the H.264 one, so a mismatch costs bytes, not\n// playback - but it costs ALL of them, which is the entire point of shipping it.\nconst AV1_TYPE='video/mp4; codecs=\"av01.0.08M.08\"';/**\n * Enum controls can arrive as either the option value or its display title\n * depending on how the instance was written, so match on substance rather than\n * on an exact string. Same trap as the YouTube component.\n */function normalizeFit(value){return String(value??\"\").toLowerCase().includes(\"contain\")?\"contain\":\"cover\";}/**\n * Self-hosted looping background video. No controls, no chrome, no third-party\n * player — just a muted autoplaying <video>. Upload the file into the File\n * control and Framer serves it from its own CDN.\n *\n * @framerSupportedLayoutWidth any\n * @framerSupportedLayoutHeight any\n * @framerIntrinsicWidth 600\n * @framerIntrinsicHeight 338\n */export default function BackgroundVideo(props){const{file,fileAv1,fit,opacity,tint,poster,playInCanvas,borderRadius,style}=props;const videoRef=useRef(null);const loadedSourcesRef=useRef(\"\");const hostRef=useRef(null);const isStatic=useIsStaticRenderer();const[reducedMotion,setReducedMotion]=useState(false);const[inView,setInView]=useState(false);const[painted,setPainted]=useState(true);const[loaded,setLoaded]=useState(false);// Set once the browser has chosen the AV1 source and then failed to show\n// a frame. From then on only the H.264 file is offered.\nconst[av1Failed,setAv1Failed]=useState(false);// Set when play() was refused for want of a user gesture. Low Power Mode\n// and the iOS 27 \"Auto-Play Video Previews\" switch both answer that way.\nconst[needsGesture,setNeedsGesture]=useState(false);// Honour the OS \"reduce motion\" setting: hold the first frame instead of\n// looping. The poster still shows, so the section never looks empty.\nuseEffect(()=>{if(typeof window===\"undefined\"||!window.matchMedia)return;const query=window.matchMedia(\"(prefers-reduced-motion: reduce)\");const update=()=>setReducedMotion(query.matches);update();query.addEventListener(\"change\",update);return()=>query.removeEventListener(\"change\",update);},[]);const shouldPlay=!reducedMotion&&(playInCanvas||!isStatic);// RenderTarget - not useIsStaticRenderer - is what separates the canvas\n// from the published page's own static render, and it is the static render\n// that must ship without a src.\nconst shouldLoad=loaded||RenderTarget.current()===RenderTarget.canvas;const av1=fileAv1&&!av1Failed?fileAv1:undefined;// Only fetch the clip once it is near the viewport. This gate decides\n// whether the file is DOWNLOADED, not just whether it plays - the previous\n// version set src unconditionally, so every clip on the page pulled its\n// full body on load even while paused and parked thousands of pixels down.\n// The canvas is exempt so the designer still sees the video immediately.\nuseEffect(()=>{const host=hostRef.current;if(!host)return;if(typeof IntersectionObserver===\"undefined\"){setInView(true);return;}const observer=new IntersectionObserver(([entry])=>setInView(entry.isIntersecting),{rootMargin:\"400px 0px\",threshold:0});observer.observe(host);return()=>observer.disconnect();},[file,fileAv1]);// Latch. Once the bytes are in the cache, keep src attached: clearing it on\n// scroll-away would make the browser re-fetch the whole file every time the\n// section came back into view, which is worse than never gating at all.\nuseEffect(()=>{if(inView)setLoaded(true);},[inView]);// These layers are stacked: a variant shows its clip by fading it in over\n// the ones below, so most of them are either transparent or completely\n// covered by an opaque layer sitting on top. Neither state is something\n// IntersectionObserver can see - it only measures geometry - so without\n// this check every stacked clip decodes even though one is visible.\nuseEffect(()=>{const host=hostRef.current;if(!host||typeof window===\"undefined\"||isStatic)return;const effectiveOpacity=from=>{let node=from;let value=1;while(node&&node!==document.body){const computed=window.getComputedStyle(node);if(computed.display===\"none\"||computed.visibility===\"hidden\")return 0;value*=Number(computed.opacity)||0;if(value<=OPACITY_FLOOR)return 0;node=node.parentElement;}return value;};// A later sibling only hides this one if it is opaque AND actually\n// spans it. The bottle card is a later sibling too, but it sits in a\n// corner, so the bounds test is what keeps it from pausing the clip.\nconst isCovered=()=>{const rect=host.getBoundingClientRect();let sibling=host.nextElementSibling;while(sibling){if(effectiveOpacity(sibling)>COVER_OPACITY){const over=sibling.getBoundingClientRect();if(over.left<=rect.left+1&&over.top<=rect.top+1&&over.right>=rect.right-1&&over.bottom>=rect.bottom-1)return true;}sibling=sibling.nextElementSibling;}return false;};let settle;const read=()=>setPainted(effectiveOpacity(host)>OPACITY_FLOOR&&!isCovered());const update=()=>{read();// Mid cross-fade the value read is not the one it lands on, so take\n// a second look once the transition has had time to finish.\nclearTimeout(settle);settle=setTimeout(read,SETTLE_MS);};update();const observer=new MutationObserver(update);let node=host.parentElement;for(let depth=0;node&&depth<6;depth++){observer.observe(node,{attributes:true,subtree:depth===0,attributeFilter:[\"style\",\"class\"]});node=node.parentElement;}return()=>{observer.disconnect();clearTimeout(settle);};},[isStatic,inView]);// Some browsers ignore the autoplay attribute when the element mounts with\n// its source already set, so ask explicitly and swallow the rejection that\n// arrives when the tab is backgrounded.\nuseEffect(()=>{const video=videoRef.current;if(!video)return;if(!shouldPlay||!inView||!painted||!shouldLoad){video.pause();return;}// Swapping <source> children does nothing on its own - the resource\n// selection algorithm only re-runs on an explicit load(). Keyed so a\n// file swap reloads but an ordinary re-render does not, since load()\n// rewinds playback to zero.\nconst sources=`${av1??\"\"}|${file??\"\"}`;if(loadedSourcesRef.current!==sources){loadedSourcesRef.current=sources;video.load();}const attempt=video.play();if(attempt&&typeof attempt.catch===\"function\")attempt.catch(reason=>{// NotAllowedError is the browser saying \"not without a tap\":\n// iOS in Low Power Mode, or with video previews switched off,\n// refuses every play() that does not run inside a gesture.\n// Remember it so the next tap anywhere can try again.\nconst name=reason&&typeof reason===\"object\"&&\"name\"in reason?String(reason.name):\"\";if(name===\"NotAllowedError\")setNeedsGesture(true);});},[shouldPlay,inView,painted,shouldLoad,file,av1]);// A play() issued inside a user gesture lifts the restriction for the\n// rest of the element's life, and the gesture does not have to land on\n// the video. So after a refusal, wait for the first tap or click on the\n// page and ask again from inside it. Touch scrolling is not a gesture in\n// this sense, which is why pointerup/click and not pointerdown.\nuseEffect(()=>{if(!needsGesture||typeof document===\"undefined\")return;const retry=()=>{const video=videoRef.current;if(!video)return;if(!shouldPlay||!inView||!painted||!shouldLoad)return;const attempt=video.play();if(attempt&&typeof attempt.then===\"function\")attempt.then(()=>setNeedsGesture(false),()=>{});};document.addEventListener(\"pointerup\",retry,{passive:true});document.addEventListener(\"click\",retry,{passive:true});return()=>{document.removeEventListener(\"pointerup\",retry);document.removeEventListener(\"click\",retry);};},[needsGesture,shouldPlay,inView,painted,shouldLoad]);// The browser only moves on to the next <source> when it rejects a file\n// up front. Once it has accepted the AV1 source - the codec string\n// matched - and then cannot decode it, the element stops with a\n// MediaError and never looks at the H.264 file. So take that step by\n// hand: drop the AV1 source and let load() rerun with H.264 only.\n// Guarded on currentSrc so an H.264 failure cannot loop.\nconst handleError=()=>{const video=videoRef.current;if(!video||!av1||!file||!video.error)return;if(video.currentSrc&&video.currentSrc!==av1)return;setAv1Failed(true);};// Some decoder failures are silent: no error event, readyState never\n// reaches a frame, the poster just stays. Give the AV1 source a fixed\n// grace period while it is meant to be playing, then fall back the same\n// way. A fetch still in flight is left alone, so a slow network is not\n// mistaken for a broken decoder, and a refused play() is left alone too,\n// since swapping codecs cannot fix a missing gesture.\nuseEffect(()=>{const video=videoRef.current;if(!video||!av1||!file)return;if(!shouldPlay||!inView||!painted||!shouldLoad||needsGesture)return;const timer=setTimeout(()=>{if(video.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA)return;if(video.networkState===HTMLMediaElement.NETWORK_LOADING)return;setAv1Failed(true);},STALL_MS);return()=>clearTimeout(timer);},[av1,file,shouldPlay,inView,painted,shouldLoad,needsGesture]);const objectFit=normalizeFit(fit);const container={position:\"relative\",overflow:\"hidden\",borderRadius,width:\"100%\",height:\"100%\",...style};const media={position:\"absolute\",inset:0,width:\"100%\",height:\"100%\",objectFit,opacity,display:\"block\"};// With no file this layer must disappear completely rather than paint a\n// placeholder, so whatever sits behind it still shows. The hint is only\n// useful in the editor, and RenderTarget (not useIsStaticRenderer) is what\n// distinguishes the canvas from the published page's own static render.\nif(!file&&!fileAv1){if(RenderTarget.current()!==RenderTarget.canvas)return null;return /*#__PURE__*/_jsx(\"div\",{style:container,children:/*#__PURE__*/_jsx(\"div\",{style:{position:\"absolute\",inset:0,display:\"flex\",alignItems:\"center\",justifyContent:\"center\",background:\"rgba(0,0,0,0.06)\",color:\"rgba(0,0,0,0.45)\",font:\"500 13px/1.4 Inter, sans-serif\",textAlign:\"center\",padding:16},children:\"Pick a video file in the properties panel\"})});}return /*#__PURE__*/_jsxs(\"div\",{style:container,ref:hostRef,children:[/*#__PURE__*/_jsxs(\"video\",{ref:videoRef,poster:poster?.src,style:media,loop:true,muted:true,playsInline:true,preload:shouldLoad?\"auto\":\"none\",controls:false,disablePictureInPicture:true,tabIndex:-1,\"aria-hidden\":\"true\",onError:handleError,children:[shouldLoad&&av1?/*#__PURE__*/_jsx(\"source\",{src:av1,type:AV1_TYPE}):null,shouldLoad&&file?/*#__PURE__*/_jsx(\"source\",{src:file,type:\"video/mp4\"}):null]}),tint&&tint.opacity?/*#__PURE__*/_jsx(\"div\",{style:{position:\"absolute\",inset:0,background:tint.color??\"#000000\",opacity:tint.opacity,pointerEvents:\"none\"}}):null]});}BackgroundVideo.displayName=\"Background Video\";addPropertyControls(BackgroundVideo,{file:{type:ControlType.File,title:\"Video\",allowedFileTypes:[\"mp4\",\"webm\",\"mov\"],description:\"Framer hosts the file unaltered and bills its bytes. Aim under 5 MB so it stays in the browser media cache.\"},fileAv1:{type:ControlType.File,title:\"AV1\",allowedFileTypes:[\"mp4\"],description:\"Optional, and served first where it is supported. Same clip encoded as AV1 - about a quarter the bytes at equal quality. Anything that cannot decode it falls back to Video on its own.\"},fit:{type:ControlType.Enum,title:\"Fit\",options:[\"cover\",\"contain\"],optionTitles:[\"Cover\",\"Contain\"],defaultValue:\"cover\",displaySegmentedControl:true},opacity:{type:ControlType.Number,title:\"Opacity\",defaultValue:1,min:0,max:1,step:.05},borderRadius:{type:ControlType.BorderRadius,title:\"Radius\",defaultValue:\"0px\"},tint:{type:ControlType.Object,title:\"Tint\",optional:true,icon:\"effect\",controls:{color:{type:ControlType.Color,title:\"Color\",defaultValue:\"#000000\"},opacity:{type:ControlType.Number,title:\"Opacity\",defaultValue:.3,min:0,max:1,step:.05}}},poster:{type:ControlType.ResponsiveImage,title:\"Poster\",description:\"Shows until the first frame decodes.\"},playInCanvas:{type:ControlType.Boolean,title:\"Play in Canvas\",defaultValue:false}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"BackgroundVideo\",\"slots\":[],\"annotations\":{\"framerSupportedLayoutWidth\":\"any\",\"framerIntrinsicWidth\":\"600\",\"framerSupportedLayoutHeight\":\"any\",\"framerContractVersion\":\"1\",\"framerIntrinsicHeight\":\"338\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./BackgroundVideo.map"],"mappings":"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"}