UNPKG

tiptap-extension-resizable-image

Version:
3 lines 10.4 kB
'use strict';var react$1=require('react'),jsxRuntime=require('react/jsx-runtime'),react=require('@tiptap/react'),core=require('@tiptap/core'),state=require('@tiptap/pm/state');var F=Object.defineProperty,K=Object.defineProperties;var j=Object.getOwnPropertyDescriptors;var k=Object.getOwnPropertySymbols;var B=Object.prototype.hasOwnProperty,_=Object.prototype.propertyIsEnumerable;var S=(e,r,t)=>r in e?F(e,r,{enumerable:true,configurable:true,writable:true,value:t}):e[r]=t,z=(e,r)=>{for(var t in r||(r={}))B.call(r,t)&&S(e,t,r[t]);if(k)for(var t of k(r))_.call(r,t)&&S(e,t,r[t]);return e},L=(e,r)=>K(e,j(r));var V=(e,r,t)=>new Promise((n,d)=>{var m=p=>{try{a(t.next(p));}catch(h){d(h);}},g=p=>{try{a(t.throw(p));}catch(h){d(h);}},a=p=>p.done?n(p.value):Promise.resolve(p.value).then(m,g);a((t=t.apply(e,r)).next());});var G=e=>{let{updateAttributes:r,node:{attrs:t},editor:n,extension:d}=e,{captionProps:m}=d.options,g=react$1.useRef(null),a=f=>{if(!g.current)return;let{innerText:b,innerHTML:R}=f.target,y=(b==null?void 0:b.replaceAll(` `,""))==="",H=R.replaceAll("<div>",` `).replaceAll("</div>","").replaceAll("<br>",""),P=y?"":H;g.current.innerHTML=P,r({caption:P});},p=f=>{f.preventDefault();let b=f.clipboardData.getData("text/plain"),R=window.getSelection();if(R&&b){let y=R.getRangeAt(0);R.deleteFromDocument(),y.insertNode(document.createTextNode(b)),y.setStart(y.endContainer,y.endOffset);}},h=f=>{if((f.ctrlKey||f.metaKey)&&f.key==="a"){f.preventDefault();let b=window.getSelection();if(b){let R=b.getRangeAt(0);R.selectNodeContents(f.currentTarget),b.addRange(R);}}};return jsxRuntime.jsx("span",L(z({},m),{ref:g,className:`caption ${(m==null?void 0:m.className)||""}`,contentEditable:n.isEditable,onBlur:a,onPaste:p,onKeyDown:h,dangerouslySetInnerHTML:{__html:t.caption||""}}))},N=G;function T(e,r,t){return Math.min(Math.max(e,r),t)}var s={east:1,north:8,south:2,west:4};function D({editor:e,imageRef:r,minWidth:t,maxWidth:n,minHeight:d,maxHeight:m,keepRatio:g,onResizeEnd:a,onResizeStart:p}){let h=react$1.useRef(null),f=react$1.useRef({currentHeight:0,currentWidth:0,direction:0,isResizing:false,ratio:0,startHeight:0,startWidth:0,startX:0,startY:0}),b=e.view.dom,R=i=>{let u=i===s.east||i===s.west,o=i===s.north||i===s.south,M=i&s.north&&i&s.west||i&s.south&&i&s.east,x=u?"ew":o?"ns":M?"nwse":"nesw";b!==null&&b.style.setProperty("cursor",`${x}-resize`,"important"),document.body!==null&&(document.body.style.setProperty("cursor",`${x}-resize`,"important"),document.body.style.setProperty("-webkit-user-select","none","important"));},y=()=>{b!==null&&b.style.removeProperty("cursor"),document.body!==null&&(document.body.style.removeProperty("cursor"),document.body.style.removeProperty("-webkit-user-select"));},H=(i,u)=>{if(!e.isEditable)return;let o=r.current,M=h.current;if(o!==null&&M!==null){i.preventDefault();let{width:x,height:c}=o.getBoundingClientRect(),l=f.current;l.startWidth=x,l.startHeight=c,l.ratio=x/c,l.currentWidth=x,l.currentHeight=c,l.startX=i.clientX,l.startY=i.clientY,l.isResizing=true,l.direction=u,R(u),p==null||p(),M.classList.add("image-control-wrapper--resizing"),o.style.height=`${c}px`,o.style.width=`${x}px`,document.addEventListener("pointermove",P),document.addEventListener("pointerup",v);}},P=i=>{let u=r.current,o=f.current,M=o.direction&(s.east|s.west),x=o.direction&(s.south|s.north);if(!(u===null||!o.isResizing)){if(g){let c=0,l=0;if(M){let w=Math.floor(o.startX-i.clientX);w=o.direction&s.east?-w:w,c=T(o.startWidth+w,t,n),l=c/o.ratio;}else {let w=Math.floor(o.startY-i.clientY);w=o.direction&s.south?-w:w,l=T(o.startHeight+w,d,m),c=l*o.ratio;}if(c<t||c>n||l<d||l>m)return;u.style.width=`${c}px`,u.style.height=`${l}px`,u.style.maxWidth=`${c}px`,o.currentHeight=l,o.currentWidth=c;return}if(M&&x){let c=Math.floor(o.startX-i.clientX);c=o.direction&s.east?-c:c;let l=Math.floor(o.startY-i.clientY);l=o.direction&s.south?-l:l;let w=T(o.startWidth+c,t,n),C=T(o.startHeight+l,d,m);u.style.width=`${w}px`,u.style.height=`${C}px`,u.style.maxWidth=`${w}px`,o.currentHeight=C,o.currentWidth=w;}else if(x){let c=Math.floor(o.startY-i.clientY);c=o.direction&s.south?-c:c;let l=T(o.startHeight+c,d,m);u.style.height=`${l}px`,o.currentHeight=l;}else {let c=Math.floor(o.startX-i.clientX);c=o.direction&s.east?-c:c;let l=T(o.startWidth+c,t,n);u.style.width=`${l}px`,u.style.maxWidth=`${l}px`,o.currentWidth=l;}}},v=()=>{let i=r.current,u=f.current,o=h.current;if(i!==null&&o!==null&&u.isResizing){let M=u.currentWidth,x=u.currentHeight;u.startWidth=0,u.startHeight=0,u.ratio=0,u.startX=0,u.startY=0,u.currentWidth=0,u.currentHeight=0,u.isResizing=false,o.classList.remove("image-control-wrapper--resizing"),y(),a(M,x),document.removeEventListener("pointermove",P),document.removeEventListener("pointerup",v);}};return jsxRuntime.jsxs("div",{ref:h,children:[jsxRuntime.jsx("div",{className:"image-resizer image-resizer-n",onPointerDown:i=>{H(i,s.north);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-ne",onPointerDown:i=>{H(i,s.north|s.east);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-e",onPointerDown:i=>{H(i,s.east);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-se",onPointerDown:i=>{H(i,s.south|s.east);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-s",onPointerDown:i=>{H(i,s.south);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-sw",onPointerDown:i=>{H(i,s.south|s.west);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-w",onPointerDown:i=>{H(i,s.west);}}),jsxRuntime.jsx("div",{className:"image-resizer image-resizer-nw",onPointerDown:i=>{H(i,s.north|s.west);}})]})}var ee=e=>{let{updateAttributes:r,node:t,extension:n,editor:d}=e,m=react$1.useRef(null),g=t.attrs,a=n.options,p=!d.isEditable,{width:h,height:f}=g,b=g["data-keep-ratio"],R=!b&&{width:h,height:f},y=L(z({},g),{style:L(z({},R||{}),{maxWidth:h})}),H=(v,i)=>{b&&m.current&&(m.current.style.width="",m.current.style.height=""),r({width:v,height:i});},P=v=>{var i;(i=a.onContextMenu)==null||i.call(a,v,e);};return p?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("img",z({},y)),a.withCaption&&g.caption&&jsxRuntime.jsx(N,z({},e))]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("img",L(z({},y),{ref:m,onContextMenu:P})),a.withCaption&&jsxRuntime.jsx(N,z({},e)),jsxRuntime.jsx(D,{editor:d,imageRef:m,minWidth:a.minWidth,maxWidth:a.maxWidth,minHeight:a.minHeight,maxHeight:a.maxHeight,keepRatio:b,onResizeEnd:H})]})},W=ee;var re=e=>jsxRuntime.jsx(react.NodeViewWrapper,{className:"image-component","data-drag-handle":true,children:jsxRuntime.jsx(W,z({},e))}),A=re;var me=/(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/,ce=e=>new Promise((r,t)=>{let n=new Image,d=URL.createObjectURL(e);n.onload=()=>{r({width:n.width,height:n.height}),URL.revokeObjectURL(d);},n.onerror=()=>{URL.revokeObjectURL(d),t(new Error("Failed to load image"));},n.src=d;}),O=(e,r,t)=>V(null,null,function*(){var a;if(!e["data-keep-ratio"])return Promise.resolve(e);let{width:n,height:d}=yield ce(r),m=(a=e.width)!=null?a:t.defaultWidth,g=d/n;return L(z({},e),{width:m,height:m*g})}),de=core.Node.create({name:"image",group:"inline",inline:true,draggable:true,atom:true,addOptions(){return {HTMLAttributes:{},defaultHeight:500,defaultWidth:500,minWidth:100,maxWidth:16384,minHeight:100,maxHeight:1/0,allowBase64:true}},addAttributes(){return {src:{default:""},alt:{default:""},title:{default:""},width:{default:this.options.defaultWidth},height:{default:this.options.defaultHeight},"data-keep-ratio":{parseHTML:e=>e.getAttribute("data-keep-ratio")!=="false",renderHTML(e){return e["data-keep-ratio"]?{style:[`max-width: ${e.width}px`].join(";"),"data-keep-ratio":"true"}:{}},default:true},className:{parseHTML:e=>e.getAttribute("class"),renderHTML:e=>({class:e.className}),default:""},caption:{parseHTML:e=>{var r,t;return (t=(r=e.parentElement)==null?void 0:r.querySelector("span"))==null?void 0:t.textContent},renderHTML(){return null},default:""}}},parseHTML(){return [{tag:this.options.allowBase64?"img[src]":'img[src]:not([src^="data:"])'},{tag:"span > img + span",ignore:true}]},renderHTML({HTMLAttributes:e,node:r}){var a,p;let t=document.createElement("span");t.classList.add("node-image");let n=document.createElement("span");n.classList.add("image-component");let d=document.createElement("img"),m=core.mergeAttributes(this.options.HTMLAttributes,e);Object.keys(m).forEach(h=>{h!=="caption"&&d.setAttribute(h,m[h]);}),n.appendChild(d);let g=r.attrs;if(g.caption){let h=document.createElement("span");h.classList.add("caption",...((p=(a=this.options.captionProps)==null?void 0:a.className)==null?void 0:p.split(" "))||""),h.innerHTML=g.caption,n.appendChild(h);}return t.appendChild(n),t},addCommands(){return {setResizableImage:(e,r,t)=>({commands:n})=>n.insertContentAt(r||this.editor.state.selection.head,{type:this.name,attrs:e},t)}},addInputRules(){return [core.nodeInputRule({find:me,type:this.type,getAttributes:e=>{let[,,r,t,n]=e;return {src:t,alt:r,title:n}}})]},addProseMirrorPlugins(){return [new state.Plugin({key:new state.PluginKey(this.name),props:{handlePaste:(e,r,t)=>{var g,a,p;let n=(g=r.clipboardData)==null?void 0:g.files;if(((a=t.content.firstChild)==null?void 0:a.type.name)===this.name)return this.editor.commands.setResizableImage(z({},t.content.firstChild.attrs)),true;let d=!((p=r.clipboardData)!=null&&p.getData("text/html"));if(!n||n.length===0||!this.options.onUpload||!d)return false;let m=this.editor.state.selection.head;for(let h of n)this.options.onUpload(h).then(f=>O(f,h,this.options)).then(f=>{this.editor.chain().focus().setResizableImage(f,m,{updateSelection:false}).run();});return true},handleDrop:(e,r)=>{var m,g;r.preventDefault();let t=(m=r.dataTransfer)==null?void 0:m.files,n=!((g=r.dataTransfer)!=null&&g.getData("text/html"));if(!t||t.length===0||!this.options.onUpload||!n)return false;let d=e.posAtCoords({left:r.clientX,top:r.clientY});for(let a of t)this.options.onUpload(a).then(p=>O(p,a,this.options)).then(p=>{this.editor.chain().focus().setResizableImage(p,d==null?void 0:d.pos,{updateSelection:false}).run();});}}})]},addNodeView(){return react.ReactNodeViewRenderer(e=>A(e),{className:"node-image"})}});exports.CaptionInput=N;exports.ImageResizer=D;exports.ResizableImage=de;exports.ResizableImageComponent=W;exports.ResizableImageNodeView=A;