{"version":3,"file":"DotGrid.C39MkXRT.mjs","names":["useRef"],"sources":["https:/framerusercontent.com/modules/5cIRoJQMEKXYXxDKRquq/1fsfoFSLnYltr7kffpbe/DotGrid.js"],"sourcesContent":["import{jsx as _jsx}from\"react/jsx-runtime\";import{addPropertyControls,ControlType,useIsStaticRenderer}from\"framer\";import{useRef,useEffect}from\"react\";/**\n * Dot Grid — subtle dotted background that brightens near the cursor (from /nordea).\n *\n * Hover maths: base alpha 0.18, and within `radius` each dot becomes\n * 0.18 + 0.5 * (1 - d/radius) — so 0.68 directly under the cursor. The\n * listener is on WINDOW, so the glow tracks the pointer even while the grid\n * sits behind other content.\n *\n * `fade` (default 0 = off, so existing instances are unchanged) softens the\n * TOP and BOTTOM edges with a mask. Needed whenever the grid fills one section\n * whose neighbours are the same colour but carry no dots: the canvas rectangle\n * then ends in a visible hard line and the adjacent sections read as black\n * bars. Fading the last `fade` px on each end dissolves the texture into them\n * instead of stopping dead.\n *\n * PERFORMANCE (2026-09-28, PageSpeed pass): the grid used to be repainted dot\n * by dot on EVERY animation frame, forever, whether or not the pointer moved,\n * whether or not it was on screen, and on phones that never hover (thousands\n * of separate fills, 60 times a second, per instance). Now the plain grid is\n * drawn ONCE into an offscreen layer; a pointer move schedules one frame that\n * restores the previous glow patch from that layer and redraws only the dots\n * within `radius` of the pointer. Nothing runs while the pointer is still, off\n * screen frames are skipped (repainted on re-entry), and devices without a\n * hover pointer get the static grid only. Same pixels as before.\n *\n * @framerSupportedLayoutWidth any-prefer-fixed\n * @framerSupportedLayoutHeight any-prefer-fixed\n * @framerIntrinsicWidth 600\n * @framerIntrinsicHeight 400\n * @framerDisableUnlink\n */export default function DotGrid(props){const{dot=\"90,96,208\",spacing=22,size=1.4,radius=130,fade=0}=props;const ref=useRef(null);const isStatic=useIsStaticRenderer();useEffect(()=>{const cv=ref.current;if(!cv)return;const c=cv.getContext(\"2d\");if(!c)return;const sp=Math.max(4,spacing);const R=Math.max(1,radius);const R2=R*R;let W=0,H=0,dpr=1,nx=0,ny=0;let base=null;let px=0,py=0,hasPointer=false;let raf=0,visible=true,dirty=false;let lastBox=null// device px [x, y, w, h] of the glow patch on screen\n;const setup=()=>{const r=cv.getBoundingClientRect();W=r.width;H=r.height;dpr=Math.min(2,window.devicePixelRatio||1);cv.width=W*dpr;cv.height=H*dpr;nx=0;for(let x=sp/2;x<W;x+=sp)nx++;ny=0;for(let y=sp/2;y<H;y+=sp)ny++;base=document.createElement(\"canvas\");base.width=cv.width;base.height=cv.height;const bc=base.getContext(\"2d\");if(bc){// One fill per dot, exactly as before: a single many-circle path\n// rasterises its edges differently and would shift the pixels.\nbc.setTransform(dpr,0,0,dpr,0,0);bc.fillStyle=\"rgba(\"+dot+\",0.180)\";for(let y=sp/2;y<H;y+=sp)for(let x=sp/2;x<W;x+=sp){bc.beginPath();bc.arc(x,y,size,0,7);bc.fill();}}lastBox=null;paint(true);};// Restore a device-pixel patch from the plain grid.\nconst restore=b=>{if(!base)return;c.setTransform(1,0,0,1,0,0);c.clearRect(b[0],b[1],b[2],b[3]);c.drawImage(base,b[0],b[1],b[2],b[3],b[0],b[1],b[2],b[3]);};const paint=full=>{if(!base)return;let box=null;let mx=0,my=0,i0=0,i1=-1,j0=0,j1=-1;if(hasPointer){const r=cv.getBoundingClientRect();mx=px-r.left;my=py-r.top;i0=Math.max(0,Math.floor((mx-R)/sp));i1=Math.min(nx-1,Math.floor((mx+R)/sp));j0=Math.max(0,Math.floor((my-R)/sp));j1=Math.min(ny-1,Math.floor((my+R)/sp));if(i1>=i0&&j1>=j0){const bx=Math.max(0,Math.floor(i0*sp*dpr)),by=Math.max(0,Math.floor(j0*sp*dpr));const bx2=Math.min(cv.width,Math.ceil((i1+1)*sp*dpr)),by2=Math.min(cv.height,Math.ceil((j1+1)*sp*dpr));box=[bx,by,bx2-bx,by2-by];}}if(full||!lastBox){c.setTransform(1,0,0,1,0,0);c.clearRect(0,0,cv.width,cv.height);c.drawImage(base,0,0);}else{restore(lastBox);}if(box){c.setTransform(1,0,0,1,0,0);c.clearRect(box[0],box[1],box[2],box[3]);c.setTransform(dpr,0,0,dpr,0,0);for(let j=j0;j<=j1;j++){const y=sp/2+j*sp;for(let i=i0;i<=i1;i++){const x=sp/2+i*sp;const dx=x-mx,dy=y-my,d2=dx*dx+dy*dy;const a=d2<R2?.18+.5*(1-Math.sqrt(d2)/R):.18;c.beginPath();c.fillStyle=\"rgba(\"+dot+\",\"+a.toFixed(3)+\")\";c.arc(x,y,size,0,7);c.fill();}}}lastBox=box;};const schedule=()=>{if(!visible){dirty=true;return;}if(!raf)raf=requestAnimationFrame(()=>{raf=0;paint(false);});};setup();if(isStatic)return;const move=e=>{px=e.clientX;py=e.clientY;hasPointer=true;schedule();};const canHover=!window.matchMedia||window.matchMedia(\"(any-hover: hover)\").matches;if(canHover)window.addEventListener(\"pointermove\",move,{passive:true});let io=null;if(typeof IntersectionObserver!==\"undefined\"){io=new IntersectionObserver(es=>{visible=es[es.length-1].isIntersecting;if(visible&&dirty){dirty=false;schedule();}});io.observe(cv);}let rw=W,rh=H;const ro=new ResizeObserver(()=>{const r=cv.getBoundingClientRect();if(Math.abs(r.width-rw)<.5&&Math.abs(r.height-rh)<.5)return;rw=r.width;rh=r.height;setup();});ro.observe(cv);return()=>{cancelAnimationFrame(raf);if(canHover)window.removeEventListener(\"pointermove\",move);io&&io.disconnect();ro.disconnect();};},[dot,spacing,size,radius,isStatic]);const f=Math.max(0,fade);const mask=f>0?`linear-gradient(to bottom, transparent 0px, #000 ${f}px, #000 calc(100% - ${f}px), transparent 100%)`:undefined;return /*#__PURE__*/_jsx(\"canvas\",{ref:ref,style:{width:\"100%\",height:\"100%\",display:\"block\",...mask?{maskImage:mask,WebkitMaskImage:mask}:null,...props.style}});}addPropertyControls(DotGrid,{dot:{type:ControlType.String,title:\"Dot RGB\",defaultValue:\"90,96,208\"},spacing:{type:ControlType.Number,title:\"Spacing\",defaultValue:22,min:10,max:60},size:{type:ControlType.Number,title:\"Dot size\",defaultValue:1.4,min:.5,max:4,step:.1},radius:{type:ControlType.Number,title:\"Hover radius\",defaultValue:130,min:40,max:400},fade:{type:ControlType.Number,title:\"Edge fade px\",description:\"Softens the top/bottom edge so the grid dissolves into neighbouring sections instead of ending in a hard line. 0 = off.\",defaultValue:0,min:0,max:300,step:10}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"DotGrid\",\"slots\":[],\"annotations\":{\"framerSupportedLayoutWidth\":\"any-prefer-fixed\",\"framerContractVersion\":\"1\",\"framerSupportedLayoutHeight\":\"any-prefer-fixed\",\"framerDisableUnlink\":\"\",\"framerIntrinsicHeight\":\"400\",\"framerIntrinsicWidth\":\"600\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./DotGrid.map"],"mappings":"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"}