{"version":3,"file":"MagicPortrait.CxYkPvRC.mjs","names":["React.useRef","React.useState","_Fragment"],"sources":["https:/framerusercontent.com/modules/B3UqAaZArKj0J5Zobxpj/1iZLHwOQR2J5Jobo6VF0/MagicPortrait.js"],"sourcesContent":["/***  MagicPortrait.tsx – Animate on View + No Flash + Animated Lightbox ***/import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from\"react/jsx-runtime\";import*as React from\"react\";import{createPortal}from\"react-dom\";import{addPropertyControls,ControlType}from\"framer\";import{motion,AnimatePresence}from\"framer-motion\";export default function MagicPortrait(props){const containerRef=React.useRef(null);const videoRef=React.useRef(null);const[ready,setReady]=React.useState(false);const[isHovering,setIsHovering]=React.useState(false);const[inView,setInView]=React.useState(false);const[mounted,setMounted]=React.useState(false);const[lightboxVisible,setLightboxVisible]=React.useState(false);const[originRect,setOriginRect]=React.useState(null);const[targetRect,setTargetRect]=React.useState(null);React.useEffect(()=>setMounted(true),[]);// Lock body scroll while lightbox is open\nReact.useEffect(()=>{if(!mounted)return;const body=document.body;const prevOverflow=body.style.overflow;if(lightboxVisible){body.style.overflow=\"hidden\";}return()=>{body.style.overflow=prevOverflow;};},[lightboxVisible,mounted]);// Determine when to play inline video\nconst shouldPlay=ready&&inView&&(props.playMode===\"load\"||props.playMode===\"hover\"&&isHovering);// --- Load inline video early ---\nReact.useEffect(()=>{const vid=videoRef.current;if(!vid)return;const onCanPlay=()=>setReady(true);vid.addEventListener(\"canplay\",onCanPlay);vid.preload=\"metadata\";vid.load();return()=>vid.removeEventListener(\"canplay\",onCanPlay);},[props.video]);// --- Intersection Observer: Trigger when 50% in view ---\nReact.useEffect(()=>{if(props.viewMode===\"immediate\"){setInView(true);return;}const vid=videoRef.current;if(!vid)return;const observer=new IntersectionObserver(([entry])=>{if(entry.isIntersecting){setInView(true);observer.disconnect();}},{threshold:.5});observer.observe(vid);return()=>observer.disconnect();},[props.viewMode]);// --- Play/Pause inline video ---\nReact.useEffect(()=>{const vid=videoRef.current;if(!vid)return;if(shouldPlay){vid.play().catch(()=>{});}else{vid.pause();vid.currentTime=0;}},[shouldPlay]);// --- Styles for inline portrait ---\nconst inlineRadius=props.circular?\"50%\":props.borderRadius??16;const containerStyle={position:\"relative\",width:\"100%\",height:\"100%\",borderRadius:inlineRadius,overflow:\"hidden\",boxShadow:props.shadow?\"0 16px 32px rgba(0, 0, 0, 0.25)\":\"none\",cursor:\"pointer\",outline:\"none\",WebkitTapHighlightColor:\"transparent\",transform:\"translateZ(0)\",userSelect:\"none\"};const mediaStyle={width:\"100%\",height:\"100%\",objectFit:\"cover\",position:\"absolute\",top:0,left:0,transition:\"opacity 0.7s ease-out\",pointerEvents:\"none\",imageRendering:\"-webkit-optimize-contrast\"};const imgStyle={...mediaStyle,opacity:ready&&shouldPlay?0:1};const vidStyle={...mediaStyle,opacity:ready&&shouldPlay?1:0};// --- Lightbox layout: always square, center of viewport ---\nconst computeTargetRect=()=>{const vw=window.innerWidth;const vh=window.innerHeight;const size=Math.min(vw*.9,vh*.9);return{width:size,height:size,left:(vw-size)/2,top:(vh-size)/2};};const openLightbox=()=>{const el=containerRef.current;if(!el)return;const r=el.getBoundingClientRect();const origin={top:r.top,left:r.left,width:r.width,height:r.height};setOriginRect(origin);setTargetRect(computeTargetRect());setLightboxVisible(true);};const closeLightbox=()=>{const el=containerRef.current;if(el){const r=el.getBoundingClientRect();setOriginRect({top:r.top,left:r.left,width:r.width,height:r.height});}setLightboxVisible(false);};// Radius during animation:\n// - Circular → stay a circle (\"50%\" the whole time, no snap).\n// - Non-circular → animate from inline radius to a slightly larger rounded rect.\nconst startRadius=inlineRadius;const endRadius=props.circular?\"50%\":props.borderRadius??24;// --- Lightbox Portal with shared-element style animation ---\nconst overlay=mounted&&originRect&&targetRect?/*#__PURE__*/createPortal(/*#__PURE__*/_jsx(AnimatePresence,{children:lightboxVisible&&/*#__PURE__*/_jsx(motion.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},transition:{duration:.25},style:{position:\"fixed\",top:0,left:0,width:\"100vw\",height:\"100vh\",background:\"rgba(0,0,0,0.75)\",zIndex:9999,overscrollBehavior:\"none\",touchAction:\"none\"},onClick:closeLightbox,onWheel:e=>e.stopPropagation(),onTouchMove:e=>e.stopPropagation(),children:/*#__PURE__*/_jsx(motion.div,{onClick:e=>e.stopPropagation(),initial:{top:originRect.top,left:originRect.left,width:originRect.width,height:originRect.height,borderRadius:startRadius,position:\"fixed\"},animate:{top:targetRect.top,left:targetRect.left,width:targetRect.width,height:targetRect.height,borderRadius:endRadius},exit:{top:originRect.top,left:originRect.left,width:originRect.width,height:originRect.height,borderRadius:startRadius},transition:{duration:.4,ease:[.16,1,.3,1]},style:{overflow:\"hidden\",boxShadow:\"0 24px 48px rgba(0,0,0,0.6)\",background:\"black\"},children:props.video?/*#__PURE__*/_jsx(\"video\",{src:props.video,autoPlay:true,loop:true,muted:true,playsInline:true,style:{width:\"100%\",height:\"100%\",objectFit:\"cover\"},onContextMenu:e=>e.preventDefault(),draggable:false}):/*#__PURE__*/_jsx(\"img\",{src:props.poster,alt:\"\",style:{width:\"100%\",height:\"100%\",objectFit:\"cover\"},draggable:false})})},\"scrim\")}),document.body):null;return /*#__PURE__*/_jsxs(_Fragment,{children:[/*#__PURE__*/_jsxs(\"div\",{ref:containerRef,style:containerStyle,onPointerEnter:()=>props.playMode===\"hover\"&&setIsHovering(true),onPointerLeave:()=>props.playMode===\"hover\"&&setIsHovering(false),onClick:openLightbox,tabIndex:-1,children:[/*#__PURE__*/_jsx(\"img\",{src:props.poster,style:imgStyle,alt:\"\",draggable:false}),/*#__PURE__*/_jsx(\"video\",{ref:videoRef,src:props.video,loop:true,muted:true,playsInline:true,style:vidStyle,preload:\"metadata\",onContextMenu:e=>e.preventDefault(),draggable:false})]}),overlay]});}/* ------------------- Property Controls ------------------- */addPropertyControls(MagicPortrait,{poster:{type:ControlType.Image,title:\"Poster Image (Square)\",description:\"720\\xd7720 or 800\\xd7800 recommended\"},video:{type:ControlType.File,title:\"Looping Video (Square)\",allowedFileTypes:[\"mp4\",\"webm\"],description:\"10-sec loop, ≤5 MB, 720\\xd7720, 24 fps\"},playMode:{type:ControlType.Enum,title:\"Play Trigger\",defaultValue:\"load\",options:[\"load\",\"hover\"],optionTitles:[\"As soon as loaded\",\"Only on hover\"]},viewMode:{type:ControlType.Enum,title:\"Start Animation\",defaultValue:\"onView\",options:[\"immediate\",\"onView\"],optionTitles:[\"Immediately\",\"When in view\"],description:\"Wait until 50% of portrait is visible\"},borderRadius:{type:ControlType.Number,title:\"Corner Radius\",defaultValue:16,min:0,max:200,unit:\"px\",hidden:props=>props.circular},circular:{type:ControlType.Boolean,title:\"Circular Frame\",defaultValue:false},shadow:{type:ControlType.Boolean,title:\"Drop Shadow\",defaultValue:true}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"MagicPortrait\",\"slots\":[],\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./MagicPortrait.map"],"mappings":"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"}