UNPKG

react-avatar-editor

Version:

Avatar / profile picture component. Resize and crop your uploaded image using a intuitive user interface.

2 lines 12.7 kB
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`react`);c=s(c);var l=(e,t,n,r,i,a)=>{if(a===0)e.rect(t,n,r,i);else{let o=r-a,s=i-a;e.translate(t,n),e.arc(a,a,a,Math.PI,Math.PI*1.5),e.lineTo(o,0),e.arc(o,a,a,Math.PI*1.5,Math.PI*2),e.lineTo(r,s),e.arc(o,s,a,Math.PI*2,Math.PI*.5),e.lineTo(a,i),e.arc(a,s,a,Math.PI*.5,Math.PI),e.closePath(),e.translate(-t,-n)}},u=(e,t,n,r,i,a)=>{e.fillStyle=a;let o=r/3,s=i/3;e.fillRect(t,n,1,i),e.fillRect(o+t,n,1,i),e.fillRect(o*2+t,n,1,i),e.fillRect(o*3+t,n,1,i),e.fillRect(o*4+t,n,1,i),e.fillRect(t,n,r,1),e.fillRect(t,s+n,r,1),e.fillRect(t,s*2+n,r,1),e.fillRect(t,s*3+n,r,1),e.fillRect(t,s*4+n,r,1)},d=e=>!!e.match(/^\s*data:([a-z]+\/[a-z]+(;[a-z-]+=[a-z-]+)?)?(;base64)?,[a-z0-9!$&',()*+;=\-._~:@/?%\s]*\s*$/i),f=(e,t)=>new Promise((n,r)=>{let i=new Image;i.addEventListener(`load`,()=>n(i)),i.addEventListener(`error`,r),!d(e)&&t&&(i.crossOrigin=t),i.src=e}),p=e=>new Promise((t,n)=>{let r=new FileReader;r.addEventListener(`load`,e=>{try{if(!e?.target?.result)throw Error(`No image data`);t(f(e.target.result))}catch(e){n(e)}}),r.readAsDataURL(e)}),m=typeof File<`u`,h=e=>Math.PI/180*e,g={x:.5,y:.5},_=class{constructor(e){this.imageState=g,this.config={border:25,borderRadius:0,scale:1,rotate:0,color:[0,0,0,.5],backgroundColor:``,borderColor:void 0,showGrid:!1,gridColor:`#666`,disableBoundaryChecks:!1,disableHiDPIScaling:!1,disableCanvasRotation:!0,crossOrigin:void 0,...e},this.pixelRatio=typeof window<`u`&&window.devicePixelRatio&&!this.config.disableHiDPIScaling?window.devicePixelRatio:1}getPixelRatio(){return this.pixelRatio}getImageState(){return this.imageState}setImageState(e){this.imageState=e}updateConfig(e){this.config={...this.config,...e}}isVertical(){return!this.config.disableCanvasRotation&&this.config.rotate%180!=0}getBorders(e){let t=e??this.config.border;return Array.isArray(t)?t:[t,t]}getDimensions(){let{width:e,height:t,rotate:n,border:r}=this.config,i={width:0,height:0},[a,o]=this.getBorders(r);return this.isVertical()?(i.width=t,i.height=e):(i.width=e,i.height=t),i.width+=a*2,i.height+=o*2,{canvas:i,rotate:n,width:e,height:t,border:r}}getXScale(){if(!this.imageState.width||!this.imageState.height)throw Error(`Image dimension is unknown.`);let e=this.config.width/this.config.height,t=this.imageState.width/this.imageState.height;return Math.min(1,e/t)}getYScale(){if(!this.imageState.width||!this.imageState.height)throw Error(`Image dimension is unknown.`);let e=this.config.height/this.config.width,t=this.imageState.height/this.imageState.width;return Math.min(1,e/t)}getCroppingRect(e){if(!this.imageState.width||!this.imageState.height)return{x:0,y:0,width:1,height:1};let t=e||{x:this.imageState.x,y:this.imageState.y},n=1/this.config.scale*this.getXScale(),r=1/this.config.scale*this.getYScale(),i={x:t.x-n/2,y:t.y-r/2,width:n,height:r},a=0,o=1-i.width,s=0,c=1-i.height;return(this.config.disableBoundaryChecks||n>1||r>1)&&(a=-i.width,o=1,s=-i.height,c=1),{...i,x:Math.max(a,Math.min(i.x,o)),y:Math.max(s,Math.min(i.y,c))}}getInitialSize(e,t){let n,r,i=this.getDimensions();return i.height/i.width>t/e?(n=i.height,r=n/t*e):(r=i.width,n=r/e*t),{height:n,width:r}}async loadImage(e){let t;if(m&&e instanceof File)t=await p(e);else if(typeof e==`string`)t=await f(e,this.config.crossOrigin);else throw Error(`Invalid image source`);let n={...this.getInitialSize(t.width,t.height),resource:t,x:.5,y:.5};return this.imageState=n,n}clearImage(){this.imageState=g}calculatePosition(e=this.imageState,t){let[n,r]=this.getBorders(t);if(!e.width||!e.height)throw Error(`Image dimension is unknown.`);let i=this.getCroppingRect(),a=e.width*this.config.scale,o=e.height*this.config.scale,s=-i.x*a,c=-i.y*o;return this.isVertical()?(s+=r,c+=n):(s+=n,c+=r),{x:s,y:c,height:o,width:a}}paint(e){e.save(),e.scale(this.pixelRatio,this.pixelRatio),e.translate(0,0),e.fillStyle=`rgba(`+this.config.color.slice(0,4).join(`,`)+`)`;let t=this.config.borderRadius,n=this.getDimensions(),[r,i]=this.getBorders(n.border),a=n.canvas.height,o=n.canvas.width;t=Math.max(t,0),t=Math.min(t,o/2-r,a/2-i),e.beginPath(),l(e,r,i,o-r*2,a-i*2,t),e.rect(o,0,-o,a),e.fill(`evenodd`),this.config.borderColor&&(e.strokeStyle=`rgba(`+this.config.borderColor.slice(0,4).join(`,`)+`)`,e.lineWidth=1,e.beginPath(),l(e,r+.5,i+.5,o-r*2-1,a-i*2-1,t),e.stroke()),this.config.showGrid&&u(e,r,i,o-r*2,a-i*2,this.config.gridColor),e.restore()}paintImage(e,t,n,r=this.pixelRatio){if(!t.resource)return;let i=this.calculatePosition(t,n);e.save(),e.translate(e.canvas.width/2,e.canvas.height/2),e.rotate(this.config.rotate*Math.PI/180),e.translate(-(e.canvas.width/2),-(e.canvas.height/2)),this.isVertical()&&e.translate((e.canvas.width-e.canvas.height)/2,(e.canvas.height-e.canvas.width)/2),e.scale(r,r),e.globalCompositeOperation=`destination-over`,e.drawImage(t.resource,i.x,i.y,i.width,i.height),this.config.backgroundColor&&(e.fillStyle=this.config.backgroundColor,e.fillRect(0,0,e.canvas.width,e.canvas.height)),e.restore()}getImage(){let e=this.getCroppingRect(),t=this.imageState;if(!t.resource)throw Error(`No image resource available, please report this to: https://github.com/mosch/react-avatar-editor/issues`);e.x*=t.resource.width,e.y*=t.resource.height,e.width*=t.resource.width,e.height*=t.resource.height;let n=document.createElement(`canvas`);this.isVertical()?(n.width=Math.round(e.height),n.height=Math.round(e.width)):(n.width=Math.round(e.width),n.height=Math.round(e.height));let r=n.getContext(`2d`);if(!r)throw Error(`No context found, please report this to: https://github.com/mosch/react-avatar-editor/issues`);return r.translate(n.width/2,n.height/2),r.rotate(this.config.rotate*Math.PI/180),r.translate(-(n.width/2),-(n.height/2)),this.isVertical()&&r.translate((n.width-n.height)/2,(n.height-n.width)/2),this.config.backgroundColor&&(r.fillStyle=this.config.backgroundColor,r.fillRect(0,0,n.width,n.height)),r.drawImage(t.resource,-e.x,-e.y),n}getImageScaledToCanvas(){let e=this.getDimensions(),t=this.imageState,n=document.createElement(`canvas`);if(this.isVertical()?(n.width=e.height,n.height=e.width):(n.width=e.width,n.height=e.height),!t.resource)return n;let r=n.getContext(`2d`);if(!r)return n;let i=this.calculatePosition(t,0);return r.save(),r.translate(n.width/2,n.height/2),r.rotate(this.config.rotate*Math.PI/180),r.translate(-(n.width/2),-(n.height/2)),this.isVertical()&&r.translate((n.width-n.height)/2,(n.height-n.width)/2),this.config.backgroundColor&&(r.fillStyle=this.config.backgroundColor,r.fillRect(0,0,n.width,n.height)),r.drawImage(t.resource,i.x,i.y,i.width,i.height),r.restore(),n}calculateDragPosition(e,t,n,r){let i=n-e,a=r-t;if(!this.imageState.width||!this.imageState.height)throw Error(`Image dimension is unknown.`);let o=this.imageState.width*this.config.scale,s=this.imageState.height*this.config.scale,{x:c,y:l}=this.getCroppingRect();c*=o,l*=s;let u=this.config.rotate;u%=360,u=u<0?u+360:u;let d=Math.cos(h(u)),f=Math.sin(h(u)),p=c+i*d+a*f,m=l+-i*f+a*d,g=1/this.config.scale*this.getXScale(),_=1/this.config.scale*this.getYScale();return{x:p/o+g/2,y:m/s+_/2}}},v=()=>{},y=()=>{let e=!1;try{let t=Object.defineProperty({},`passive`,{get:function(){e=!0}});window.addEventListener(`test`,v,t),window.removeEventListener(`test`,v,t)}catch{e=!1}return e},b=(0,c.forwardRef)((e,t)=>{let{scale:n=1,rotate:r=0,border:i=25,borderRadius:a=0,width:o=200,height:s=200,color:l=[0,0,0,.5],showGrid:u=!1,gridColor:d=`#666`,disableBoundaryChecks:f=!1,disableHiDPIScaling:p=!1,disableCanvasRotation:m=!0,image:h,position:g,backgroundColor:v,crossOrigin:b,onLoadStart:x,onLoadFailure:S,onLoadSuccess:C,onImageReady:w,onImageChange:T,onMouseUp:E,onMouseMove:D,onPositionChange:O,borderColor:k,style:A}=e,j=(0,c.useRef)(null),M=(0,c.useRef)(new _({width:o,height:s,border:i,borderRadius:a,scale:n,rotate:r,color:l,backgroundColor:v,borderColor:k,showGrid:u,gridColor:d,disableBoundaryChecks:f,disableHiDPIScaling:p,disableCanvasRotation:m,crossOrigin:b})),N=(0,c.useRef)(!1),P=(0,c.useRef)(void 0),F=(0,c.useRef)(void 0),[I,L]=(0,c.useState)(!1),[R,z]=(0,c.useState)(!1),[B,V]=(0,c.useState)(M.current.getImageState()),H=(0,c.useRef)(E);H.current=E;let U=(0,c.useRef)(D);U.current=D;let W=(0,c.useRef)(O);W.current=O,(0,c.useEffect)(()=>{M.current.updateConfig({width:o,height:s,border:i,borderRadius:a,scale:n,rotate:r,color:l,backgroundColor:v,borderColor:k,showGrid:u,gridColor:d,disableBoundaryChecks:f,disableHiDPIScaling:p,disableCanvasRotation:m,crossOrigin:b})},[o,s,i,a,n,r,l,v,k,u,d,f,p,m,b]);let G=(0,c.useCallback)(()=>{if(!j.current)throw Error(`No canvas found, please report this to: https://github.com/mosch/react-avatar-editor/issues`);return j.current},[]),K=(0,c.useCallback)(()=>{let e=G().getContext(`2d`);if(!e)throw Error(`No context found, please report this to: https://github.com/mosch/react-avatar-editor/issues`);return e},[G]),q=(0,c.useCallback)(async e=>{z(!0),x?.();try{let t=await M.current.loadImage(e);N.current=!1,L(!1),V(t),w?.(),C?.(t)}catch{S?.()}finally{z(!1)}},[x,w,C,S]),J=(0,c.useCallback)(()=>{let e=G();K().clearRect(0,0,e.width,e.height),M.current.clearImage(),V(M.current.getImageState())},[G,K]),Y=(0,c.useCallback)(()=>{let e=K(),t=G();e.clearRect(0,0,t.width,t.height),M.current.paint(e),M.current.paintImage(e,B,i)},[K,G,B,i,o,s,a,n,r,l,v,k,u,d,f,p,m,b]),X=(0,c.useCallback)(e=>{e.preventDefault(),N.current=!0,P.current=void 0,F.current=void 0,L(!0)},[]),ee=(0,c.useCallback)(()=>{N.current=!0,P.current=void 0,F.current=void 0,L(!0)},[]);(0,c.useImperativeHandle)(t,()=>({getImage:()=>M.current.getImage(),getImageScaledToCanvas:()=>M.current.getImageScaledToCanvas(),getCroppingRect:()=>M.current.getCroppingRect()}),[]),(0,c.useEffect)(()=>{let e=K();h&&q(h),M.current.paint(e);let t=e=>{if(!N.current)return;e.cancelable&&e.preventDefault();let t=`targetTouches`in e?e.targetTouches[0].pageX:e.clientX,n=`targetTouches`in e?e.targetTouches[0].pageY:e.clientY,r=P.current,i=F.current;if(P.current=t,F.current=n,r!==void 0&&i!==void 0){let e=M.current.getImageState();if(e.width&&e.height){let a=M.current.calculateDragPosition(t,n,r,i);W.current?.(a);let o={...e,...a};M.current.setImageState(o),V(o)}}U.current?.(e)},n=()=>{N.current&&(N.current=!1,L(!1),H.current?.())},r=y()?{passive:!1}:!1;return document.addEventListener(`mousemove`,t,r),document.addEventListener(`mouseup`,n,r),document.addEventListener(`touchmove`,t,r),document.addEventListener(`touchend`,n,r),()=>{document.removeEventListener(`mousemove`,t,!1),document.removeEventListener(`mouseup`,n,!1),document.removeEventListener(`touchmove`,t,!1),document.removeEventListener(`touchend`,n,!1)}},[]),(0,c.useEffect)(()=>{h?q(h):!h&&B.x!==.5&&B.y!==.5&&J()},[h,o,s,v]),(0,c.useEffect)(()=>{Y()},[Y]),(0,c.useEffect)(()=>{if(!R)return;let e=j.current;if(!e)return;let t=e.getContext(`2d`);if(!t)return;let n,r=performance.now(),i=a=>{let o=(a-r)/1e3,s=.03+Math.sin(o*2.5)*.02+.02;t.save(),t.clearRect(0,0,e.width,e.height),t.fillStyle=`rgba(255,255,255,${s})`,t.fillRect(0,0,e.width,e.height),t.restore(),n=requestAnimationFrame(i)};return n=requestAnimationFrame(i),()=>cancelAnimationFrame(n)},[R]);let Z=(0,c.useRef)({image:h,width:o,height:s,position:g,scale:n,rotate:r,imageX:B.x,imageY:B.y});(0,c.useEffect)(()=>{let e=Z.current;(e.image!==h||e.width!==o||e.height!==s||e.position!==g||e.scale!==n||e.rotate!==r||e.imageX!==B.x||e.imageY!==B.y)&&(T?.(),Z.current={image:h,width:o,height:s,position:g,scale:n,rotate:r,imageX:B.x,imageY:B.y})},[h,o,s,g,n,r,B.x,B.y,T]);let Q=M.current.getDimensions(),$=M.current.getPixelRatio(),te={width:Q.canvas.width,height:Q.canvas.height,cursor:I?`grabbing`:`grab`,touchAction:`none`,maxWidth:`none`,maxHeight:`none`};return c.default.createElement(`canvas`,{width:Q.canvas.width*$,height:Q.canvas.height*$,onMouseDown:X,onTouchStart:ee,style:{...te,...A},ref:j})});b.displayName=`AvatarEditor`;function x(){let e=(0,c.useRef)(null);return{ref:e,getImage:()=>{try{return e.current?.getImage()??null}catch{return null}},getImageScaledToCanvas:()=>{try{return e.current?.getImageScaledToCanvas()??null}catch{return null}},getCroppingRect:()=>e.current?.getCroppingRect()??null}}exports.default=b,exports.useAvatarEditor=x; //# sourceMappingURL=index.cjs.map