polotno 2.29.0 → 2.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,4 +12,4 @@ import t from"react";import{observer as e}from"mobx-react-lite";import{Image as
12
12
  .ql-direction-rtl {
13
13
  direction: rtl;
14
14
  }
15
- `;let A=["bold","color","font","italic","size","strike","underline","indent","list","direction"];export const setQuillFormats=t=>{A=t};export const createQuill=t=>new a(t,{toolbar:!1,keyboard:!1,clipboard:{matchVisual:!1},formats:A});export const setQuillContent=(t,e)=>{var o=t.clipboard.convert("<div class='ql-editor' style='outline: none;'>"+e+"<p><br></p></div>");t.setContents(o),t.history.clear()};const X=({html:e,onBlur:o,onChange:n,element:i,clickCoords:r})=>{const l=t.useRef(null);t.useEffect(()=>{if(!l.current){return}const t=(i=l.current,new a(i,{toolbar:!1,keyboard:!1,clipboard:{matchVisual:!1},formats:A}));var i;return s.runInAction(()=>{quillRef.editor.instance=t}),window.__polotnoQuill=t,t.on("text-change",()=>{t.getSelection()&&s.runInAction(()=>{quillRef.currentFormat=t.getFormat(t.getSelection())}),setTimeout(()=>{var t;const e=null===(t=l.current)||void 0===t?void 0:t.childNodes[0];if(!e){return}const o=e.innerHTML;n(T(o))},10)}),setQuillContent(t,e),r?setCursorFromCoords(t,r):t.setSelection(0,0,"api"),t.on("selection-change",(e,o,n)=>{e&&s.runInAction(()=>{quillRef.currentFormat=t.getFormat(t.getSelection())})}),l.current.childNodes[0].addEventListener("blur",t=>{var e;if(null===(e=t.relatedTarget)||void 0===e?void 0:e.classList.contains("ql-clipboard")){return}const n=function(t){return!!t&&!!t.closest(".sketch-picker")}(t.relatedTarget);n||o()}),()=>{s.runInAction(()=>{quillRef.editor.instance=null,quillRef.currentFormat={}}),delete window.__polotnoQuill}},[]),t.useEffect(()=>c(()=>i.text,()=>{var t;const o=quillRef.editor.instance;if(!o){return}const n=o.getSelection();T(null===(t=l.current)||void 0===t?void 0:t.childNodes[0].innerHTML)===i.text||(setQuillContent(o,e),n&&(o.setSelection(n.index,n.length),s.runInAction(()=>{quillRef.currentFormat=o.getFormat(o.getSelection())})))},{fireImmediately:!0}),[]),t.useEffect(()=>{window.addEventListener("blur",o);const t=t=>{var e;(null===(e=l.current)||void 0===e?void 0:e.contains(t.target))||o()};return window.addEventListener("touchstart",t),()=>{window.removeEventListener("blur",o),window.removeEventListener("touchstart",t)}},[]);const f={color:i.fill};i.fill.indexOf("gradient")>=0&&(f.backgroundColor=i.fill,f.backgroundImage=i.fill,f.backgroundSize="100% 100%",f.backgroundRepeat="repeat",f.webkitBackgroundClip="text",f.MozBackgroundClip="text",f.WebkitTextFillColor="transparent",f.MozTextFillColor="transparent");const d=M(i);return t.createElement(W,{ref:l,style:Object.assign(Object.assign({},f),{fontSize:i.fontSize,fontWeight:i.fontWeight,textTransform:i.textTransform,width:i.a.width,fontFamily:'"'+i.fontFamily+'"',lineHeight:i.lineHeight,letterSpacing:i.letterSpacing*i.fontSize+"px",textAlign:i.align,opacity:Math.max(i.a.opacity,.2),textShadow:i.shadowEnabled?`${i.shadowOffsetX}px ${i.shadowOffsetY}px ${i.shadowBlur}px ${i.shadowColor}`:void 0,caretColor:d}),dir:h($(i.text))})};function Y(t){return!function(t){const e=t.getContext("2d").getImageData(0,0,t.width,t.height).data;for(let o=0;o<e.length;o+=4){if(0!==e[o+3]){return!0}}return!1}(t)}function I(t,{fontFamily:e="",color:o="black"}={}){let n=`color: ${o||t.fill}`;t.fill.indexOf("gradient")>=0&&(n=`\n background-color: ${o};\n background-image: ${t.fill};\n background-size: 100% 100%;\n background-repeat: repeat;\n -webkit-background-clip: text;\n -moz-background-clip: text;\n -webkit-text-fill-color: transparent;\n -moz-text-fill-color: transparent;\n `);const i=["white-space: pre-wrap","word-break: break-word",`width: ${Math.round(t.width||100)}px`,n,`font-size: ${t.fontSize}px`,`font-family: '${e}'`,`text-align: ${t.align}`,`text-transform: ${t.textTransform}`,t.textDecoration?`text-decoration: ${t.textDecoration}; text-decoration-color: ${o||t.fill}; text-decoration-layer: over`:"",t.lineHeight?`line-height: ${t.lineHeight}`:"",t.letterSpacing?`letter-spacing: ${t.letterSpacing*t.fontSize}px`:"",t.fontStyle?`font-style: ${t.fontStyle}`:"",t.fontWeight?`font-weight: ${t.fontWeight}`:"",t.strokeWidth?`-webkit-text-stroke: ${t.strokeWidth}px ${t.stroke}`:"",t.strokeWidth?"paint-order: stroke fill":""].filter(Boolean).join("; ");if(t.curveEnabled){const n=function(t){const e=t.a?t.a:t,o=new l.TextPath({data:P(e.width,e.height,t.curvePower,e.fontSize),align:"center",textBaseline:"middle",text:$(t.text),fontSize:e.fontSize,fontFamily:t.fontFamily,fontWeight:t.fontWeight,fontStyle:t.fontStyle,letterSpacing:t.letterSpacing*e.fontSize,fill:t.fill}),n=o.getSelfRect().height;return o.destroy(),n}(t),i=Math.round(t.width||100);return`\n <svg xmlns="http://www.w3.org/2000/svg" width="${i}" height="${n}">\n <defs><path id="curve" d="${P(i,n,t.curvePower,t.fontSize)}" fill="none" /></defs>\n <text\n font-family="'${e}'"\n font-size="${t.fontSize}"\n font-weight="${t.fontWeight}"\n font-style="${t.fontStyle}"\n fill="${o}"\n text-anchor="middle"\n dominant-baseline="central"${t.strokeWidth?` stroke="${t.stroke}" stroke-width="${t.strokeWidth}" paint-order="stroke fill"`:""}>\n <textPath href="#curve" startOffset="50%">\n ${$(t.text).replace(/\\n/g," ")}\n </textPath>\n </text>\n </svg>`}return`<div style="${i}" contentEditable dir="${h($(t.text))}">${F(t.text).replace(/\n/g,"</br>")}</div>`}const q=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);export const HTMLElement=e(({element:e,store:a})=>{const c=t.useRef(null),[h,b]=t.useState(),[k,F]=t.useState(!1),[M,T]=t.useState(!1),A=t.useRef(e.height),B=a.selectedShapes.indexOf(e)>=0&&e.selectable,L=e.fontSize/3,{textVerticalResizeEnabled:H}=f,_=m(e.fontFamily),[D]=g(a,e.fontFamily),N=e._editModeEnabled;v(c);const Q=D?e.fontFamily:_!==e.fontFamily?_:"Arial",V=p(e).fill,J=I(e,{fontFamily:Q,color:V});let{width:G,height:K}=function(e,o,n){return t.useMemo(()=>x(e),[e,o.width,n])}(J,e,D);t.useEffect(()=>{if(!D){return}if(!e.height){return void a.history.ignore(()=>{e.set({height:K})})}const{textOverflow:t}=f;if("change-font-size"!==t||k){"resize"===t&&(H&&e.height<K&&!k&&a.history.ignore(()=>{e.set({height:K})}),H||e.height===K||a.history.ignore(()=>{e.set({height:K})}))}else{const t=(t=>{let e=t.fontSize;for(let o=1;o<50;o++){const o=I(Object.assign(Object.assign({},t.toJSON()),{fontSize:e}),{fontFamily:t.fontFamily}),{height:n}=x(o);if(!(t.height&&n>t.height||!f.textSplitAllowed&&!t.curveEnabled&&y({html:o}))){break}e-=.5}return e})(e);t!==e.fontSize?a.history.ignore(()=>{e.set({fontSize:t})}):e.height!==K&&(H&&e.height<K?a.history.ignore(()=>{e.set({height:K})}):H||a.history.ignore(()=>{e.set({height:K})}))}});const U=t.useMemo(()=>{const t={lastArgs:null,lastResult:null};return async function(e){return t.lastArgs&&t.lastResult&&(o=t.lastArgs,n=e,JSON.stringify(o)===JSON.stringify(n))||(t.lastResult=await w(e),t.lastArgs=Object.assign({},e)),t.lastResult;var o,n}},[]),Z=t.useRef(0),tt=t.useRef(null);t.useEffect(()=>{k||N||(async()=>{Z.current++;const t=Z.current;let o=E(`text ${e.id} ${t}`);tt.current&&tt.current(),tt.current=o,T(!0);let n=null;const i=q?5:1;for(let l=0;l<i;l++){const o=l>0?U:w;try{if(n=await o({skipCache:l>0,html:J,width:e.width||1,height:e.height||K||1,fontFamily:Q,padding:L,pixelRatio:a._elementsPixelRatio,font:a.fonts.find(t=>t.fontFamily===Q)||O.globalFonts.find(t=>t.fontFamily===Q)}),t!==Z.current){return}if(q&&Y(n)){await new Promise(t=>setTimeout(t,50*(l+1)));continue}break}catch(r){console.error(r),z(`Error rendering rich text with id ${e.id}`);break}}n?b(n):o?(o(),o=null):console.error("Finish function is called twice!"),T(!1)})()},[J,k,K,N,Q,e.height,a._elementsPixelRatio,D]);const[et,ot]=j(M,300),[nt]=j(k,300,!0),it=nt||et;t.useEffect(()=>{var t;if(!it){return s.autorun(()=>{const t=c.current;d(t,e)})}null===(t=c.current)||void 0===t||t.clearCache()},[h,it,e.shadowColor,e.shadowOffsetX,e.shadowOffsetY,e.shadowOpacity]),t.useEffect(()=>{h&&!M&&tt.current&&(tt.current(),tt.current=null)},[h,M]),t.useLayoutEffect(()=>{if(!D){return}if(!e.curveEnabled){return}const t=new l.TextPath({data:P(e.a.width,e.a.height,e.curvePower,e.a.fontSize),text:$(e.text),letterSpacing:e.letterSpacing*e.a.fontSize,fontSize:e.a.fontSize,fontFamily:e.fontFamily,fontWeight:e.fontWeight,fontStyle:e.fontStyle,align:"center",textBaseline:"middle",fill:e.fill}),o=t.getSelfRect().width;if(o){const t=o-e.a.width,n=e.a.rotation*Math.PI/180,i=-t/2*Math.cos(n),r=-t/2*Math.sin(n);e.set({width:o,x:e.a.x+i,y:e.a.y+r})}t.destroy()},[D,e.curveEnabled,e.curvePower,e.text,e.fontSize,e.fontFamily,e.fontWeight,e.fontStyle,e.letterSpacing]),t.useEffect(()=>()=>{tt.current&&tt.current()},[]),t.useEffect(()=>{B||""!==$(e.text)||!e.removable||e.placeholder||a.deleteElements([e.id])},[B]);let rt=0;"middle"===e.verticalAlign&&(rt=(e.height-K)/2),"bottom"===e.verticalAlign&&(rt=e.height-K);const at=u({fontLoaded:D,fontFamily:e.fontFamily,fontSize:e.fontSize,lineHeight:e.lineHeight}),lt=R(),st=P(e.a.width,K,e.curvePower,e.fontSize),ct=t.useRef(null),ft=t.useRef(null),dt=N&&e.strokeWidth>0;return t.createElement(t.Fragment,null,t.createElement(i,{x:e.a.x,y:e.a.y,offsetX:e.backgroundPadding*(e.fontSize*at*.5),offsetY:e.backgroundPadding*(e.fontSize*at*.5),rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*e.a.opacity,fill:e.backgroundColor,width:e.a.width+e.backgroundPadding*(e.fontSize*at),height:e.a.height+e.backgroundPadding*(e.fontSize*at),cornerRadius:e.backgroundCornerRadius*(e.fontSize*at*.5)}),t.createElement(r,{x:e.a.x,y:e.a.y,rotation:e.a.rotation,data:st,stroke:"red",strokeWidth:1,visible:!1}),t.createElement(i,{ref:c,name:"element",x:e.a.x,y:e.a.y,listening:e.selectable,rotation:e.a.rotation,width:e.a.width,height:e.a.height,visible:!it,draggable:lt?e.draggable&&B:e.draggable,preventDefault:!lt||B,opacity:N?0:e.a.opacity,hideInExport:!e.showInExport,onDragMove:t=>{e.set({x:t.target.x(),y:t.target.y()})},onDragEnd:t=>{e.set({x:t.target.x(),y:t.target.y()})},id:e.id,onDblClick:t=>{e.contentEditable&&(ft.current={x:t.evt.clientX,y:t.evt.clientY},e.toggleEditMode(!0))},onDblTap:t=>{var o;if(e.contentEditable){const n=null===(o=t.evt.changedTouches)||void 0===o?void 0:o[0];ft.current=n?{x:n.clientX,y:n.clientY}:null,e.toggleEditMode(!0)}},onTransformStart:t=>{F(!0),A.current=e.height},onTransform:t=>{var o;const n=t.target,i=(null===(o=n.getStage())||void 0===o?void 0:o.findOne("Transformer")).getActiveAnchor(),r="middle-left"===i||"middle-right"===i,a="top-center"===i||"bottom-center"===i,l=n.scaleX();if(r){const t=n.scaleX(),o=n.width()*t,i=e.fontSize;let r=o;if(o<i&&(r=i,ct.current&&n.position(ct.current)),n.width(r),n.scaleX(1),f.textVerticalResizeEnabled){const t=Math.max(K,A.current);e.set({height:t})}e.set({width:n.width(),x:n.x(),y:n.y()})}else if(a){let o="resize"===f.textOverflow?K:e.lineHeight*e.fontSize;const i=Math.max(o,t.target.height()*t.target.scaleY());n.scaleY(1),e.set({x:n.x(),y:n.y(),height:i,rotation:n.rotation()})}else{n.scaleX(1),n.scaleY(1),e.set({fontSize:e.fontSize*l,letterSpacing:e.letterSpacing,width:n.width()*l,x:n.x(),y:n.y(),rotation:n.rotation(),height:n.height()*l})}ct.current=t.target.position()},onTransformEnd:t=>{F(!1),T(!0);const o=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:e.fontSize*o,width:t.target.width()*o,x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),shadowBlur:e.shadowBlur*o,shadowOffsetX:e.shadowOffsetX*o,shadowOffsetY:e.shadowOffsetY*o,strokeWidth:e.strokeWidth*o})}}),t.createElement(o,{ref:c,image:h,x:e.a.x,y:e.a.y,offsetX:L,offsetY:L-rt,listening:!1,rotation:e.a.rotation,width:e.a.width+2*L,height:(e.a.width+2*L)*((null==h?void 0:h.height)/(null==h?void 0:h.width)||1),visible:!it&&!N,opacity:e.a.opacity,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,hideInExport:!e.showInExport,editModeEnabled:e._editModeEnabled||k||it}),(it||dt)&&t.createElement(n,{x:e.a.x,y:e.a.y,rotation:e.a.rotation,offsetY:-rt},t.createElement(S,{divProps:{style:{pointerEvents:"none"}}},t.createElement(W,{dangerouslySetInnerHTML:{__html:J},style:{pointerEvents:"none",opacity:e.a.opacity,textShadow:e.shadowEnabled?`${e.shadowOffsetX}px ${e.shadowOffsetY}px ${e.shadowBlur}px ${e.shadowColor}`:void 0}}))),N&&t.createElement(n,{x:e.a.x,y:e.a.y,rotation:e.a.rotation,offsetY:-rt},t.createElement(S,null,t.createElement(X,{html:J,element:e,onChange:t=>{const o=C({oldText:$(e.text),newText:$(t),element:e});e.set({text:t,fontSize:o})},onBlur:t=>{e.toggleEditMode(!1),ot(!0)},clickCoords:ft.current}))))});export function setCursorFromCoords(t,e){if(!t||!e){return}const{x:o,y:n}=e;try{let e=null;if(document.caretRangeFromPoint){e=document.caretRangeFromPoint(o,n)}else if(document.caretPositionFromPoint){const t=document.caretPositionFromPoint(o,n);t&&(e=document.createRange(),e.setStart(t.offsetNode,t.offset))}if(e){const o=a.find(e.startContainer,!0);if(o){const n=o.offset(t.scroll)+e.startOffset;return void t.setSelection(n,0,"api")}}}catch(i){}t.setSelection(0,0,"api")}
15
+ `;let A=["bold","color","font","italic","size","strike","underline","indent","list","direction"];export const setQuillFormats=t=>{A=t};export const createQuill=t=>new a(t,{toolbar:!1,keyboard:!1,clipboard:{matchVisual:!1},formats:A});export const setQuillContent=(t,e)=>{var o=t.clipboard.convert("<div class='ql-editor' style='outline: none;'>"+e+"<p><br></p></div>");t.setContents(o),t.history.clear()};const X=({html:e,onBlur:o,onChange:n,element:i,clickCoords:r})=>{const l=t.useRef(null);t.useEffect(()=>{if(!l.current){return}const t=(i=l.current,new a(i,{toolbar:!1,keyboard:!1,clipboard:{matchVisual:!1},formats:A}));var i;return s.runInAction(()=>{quillRef.editor.instance=t}),window.__polotnoQuill=t,t.on("text-change",()=>{t.getSelection()&&s.runInAction(()=>{quillRef.currentFormat=t.getFormat(t.getSelection())}),setTimeout(()=>{var t;const e=null===(t=l.current)||void 0===t?void 0:t.childNodes[0];if(!e){return}const o=e.innerHTML;n(T(o))},10)}),setQuillContent(t,e),r?setCursorFromCoords(t,r):t.setSelection(0,0,"api"),t.on("selection-change",(e,o,n)=>{e&&s.runInAction(()=>{quillRef.currentFormat=t.getFormat(t.getSelection())})}),l.current.childNodes[0].addEventListener("blur",t=>{var e;if(null===(e=t.relatedTarget)||void 0===e?void 0:e.classList.contains("ql-clipboard")){return}const n=function(t){return!!t&&!!t.closest(".sketch-picker")}(t.relatedTarget);n||o()}),()=>{s.runInAction(()=>{quillRef.editor.instance=null,quillRef.currentFormat={}}),delete window.__polotnoQuill}},[]),t.useEffect(()=>c(()=>i.text,()=>{var t;const o=quillRef.editor.instance;if(!o){return}const n=o.getSelection();T(null===(t=l.current)||void 0===t?void 0:t.childNodes[0].innerHTML)===i.text||(setQuillContent(o,e),n&&(o.setSelection(n.index,n.length),s.runInAction(()=>{quillRef.currentFormat=o.getFormat(o.getSelection())})))},{fireImmediately:!0}),[]),t.useEffect(()=>{window.addEventListener("blur",o);const t=t=>{var e;(null===(e=l.current)||void 0===e?void 0:e.contains(t.target))||o()};return window.addEventListener("touchstart",t),()=>{window.removeEventListener("blur",o),window.removeEventListener("touchstart",t)}},[]);const f={color:i.fill};i.fill.indexOf("gradient")>=0&&(f.backgroundColor=i.fill,f.backgroundImage=i.fill,f.backgroundSize="100% 100%",f.backgroundRepeat="repeat",f.webkitBackgroundClip="text",f.MozBackgroundClip="text",f.WebkitTextFillColor="transparent",f.MozTextFillColor="transparent");const d=M(i);return t.createElement(W,{ref:l,style:Object.assign(Object.assign({},f),{fontSize:i.fontSize,fontWeight:i.fontWeight,textTransform:i.textTransform,width:i.a.width,fontFamily:'"'+i.fontFamily+'"',lineHeight:i.lineHeight,letterSpacing:i.letterSpacing*i.fontSize+"px",textAlign:i.align,opacity:Math.max(i.a.opacity,.2),textShadow:i.shadowEnabled?`${i.shadowOffsetX}px ${i.shadowOffsetY}px ${i.shadowBlur}px ${i.shadowColor}`:void 0,caretColor:d}),dir:h($(i.text))})};function Y(t){return!function(t){const e=t.getContext("2d").getImageData(0,0,t.width,t.height).data;for(let o=0;o<e.length;o+=4){if(0!==e[o+3]){return!0}}return!1}(t)}function I(t,{fontFamily:e="",color:o="black"}={}){let n=`color: ${o||t.fill}`;t.fill.indexOf("gradient")>=0&&(n=`\n background-color: ${o};\n background-image: ${t.fill};\n background-size: 100% 100%;\n background-repeat: repeat;\n -webkit-background-clip: text;\n -moz-background-clip: text;\n -webkit-text-fill-color: transparent;\n -moz-text-fill-color: transparent;\n `);const i=["white-space: pre-wrap","word-break: break-word",`width: ${Math.round(t.width||100)}px`,n,`font-size: ${t.fontSize}px`,`font-family: '${e}'`,`text-align: ${t.align}`,`text-transform: ${t.textTransform}`,t.textDecoration?`text-decoration: ${t.textDecoration}; text-decoration-color: ${o||t.fill}; text-decoration-layer: over`:"",t.lineHeight?`line-height: ${t.lineHeight}`:"",t.letterSpacing?`letter-spacing: ${t.letterSpacing*t.fontSize}px`:"",t.fontStyle?`font-style: ${t.fontStyle}`:"",t.fontWeight?`font-weight: ${t.fontWeight}`:"",t.strokeWidth?`-webkit-text-stroke: ${t.strokeWidth}px ${t.stroke}`:"",t.strokeWidth?"paint-order: stroke fill":""].filter(Boolean).join("; ");if(t.curveEnabled){const n=function(t){const e=t.a?t.a:t,o=new l.TextPath({data:P(e.width,e.height,t.curvePower,e.fontSize),align:"center",textBaseline:"middle",text:$(t.text),fontSize:e.fontSize,fontFamily:t.fontFamily,fontWeight:t.fontWeight,fontStyle:t.fontStyle,letterSpacing:t.letterSpacing*e.fontSize,fill:t.fill}),n=o.getSelfRect().height;return o.destroy(),n}(t),i=Math.round(t.width||100);return`\n <svg xmlns="http://www.w3.org/2000/svg" width="${i}" height="${n}">\n <defs><path id="curve" d="${P(i,n,t.curvePower,t.fontSize)}" fill="none" /></defs>\n <text\n font-family="'${e}'"\n font-size="${t.fontSize}"\n font-weight="${t.fontWeight}"\n font-style="${t.fontStyle}"\n fill="${o}"\n text-anchor="middle"\n dominant-baseline="central"${t.strokeWidth?` stroke="${t.stroke}" stroke-width="${t.strokeWidth}" paint-order="stroke fill"`:""}>\n <textPath href="#curve" startOffset="50%">\n ${$(t.text).replace(/\\n/g," ")}\n </textPath>\n </text>\n </svg>`}return`<div style="${i}" contentEditable dir="${h($(t.text))}">${F(t.text).replace(/\n/g,"</br>")}</div>`}const q=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);export const HTMLElement=e(({element:e,store:a})=>{const c=t.useRef(null),[h,b]=t.useState(),[k,F]=t.useState(!1),[M,T]=t.useState(!1),A=t.useRef(e.height),B=a.selectedShapes.indexOf(e)>=0&&e.selectable,L=e.fontSize/3,{textVerticalResizeEnabled:H}=f,_=m(e.fontFamily),[D]=g(a,e.fontFamily),N=e._editModeEnabled;v(c);const Q=D?e.fontFamily:_!==e.fontFamily?_:"Arial",V=p(e).fill,J=I(e,{fontFamily:Q,color:V});let{width:G,height:K}=function(e,o,n){return t.useMemo(()=>x(e),[e,o.width,n])}(J,e,D);t.useEffect(()=>{if(!D){return}if(!e.height){return void a.history.ignore(()=>{e.set({height:K})})}const{textOverflow:t}=f;if("change-font-size"!==t||k){"resize"===t&&(H&&e.height<K&&!k&&a.history.ignore(()=>{e.set({height:K})}),H||e.height===K||a.history.ignore(()=>{e.set({height:K})}))}else{const t=(t=>{let e=t.fontSize;for(let o=1;o<50;o++){const o=I(Object.assign(Object.assign({},t.toJSON()),{fontSize:e}),{fontFamily:t.fontFamily}),{height:n}=x(o);if(!(t.height&&n>t.height||!f.textSplitAllowed&&!t.curveEnabled&&y({html:o}))){break}e-=.5}return e})(e);t!==e.fontSize?a.history.ignore(()=>{e.set({fontSize:t})}):e.height!==K&&(H&&e.height<K?a.history.ignore(()=>{e.set({height:K})}):H||a.history.ignore(()=>{e.set({height:K})}))}});const U=t.useMemo(()=>{const t={lastArgs:null,lastResult:null};return async function(e){return t.lastArgs&&t.lastResult&&(o=t.lastArgs,n=e,JSON.stringify(o)===JSON.stringify(n))||(t.lastResult=await w(e),t.lastArgs=Object.assign({},e)),t.lastResult;var o,n}},[]),Z=t.useRef(0),tt=t.useRef(null);t.useEffect(()=>{k||N||(async()=>{Z.current++;const t=Z.current;let o=E(`text ${e.id} ${t}`);tt.current&&tt.current(),tt.current=o,T(!0);let n=null;const i=q?5:1;for(let l=0;l<i;l++){const o=l>0?U:w;try{if(n=await o({skipCache:l>0,html:J,width:e.width||1,height:e.height||K||1,fontFamily:Q,padding:L,pixelRatio:a._elementsPixelRatio,font:a.fonts.find(t=>t.fontFamily===Q)||O.globalFonts.find(t=>t.fontFamily===Q)}),t!==Z.current){return}if(q&&Y(n)){await new Promise(t=>setTimeout(t,50*(l+1)));continue}break}catch(r){console.error(r),z(`Error rendering rich text with id ${e.id}`);break}}n?b(n):o?(o(),o=null):console.error("Finish function is called twice!"),T(!1)})()},[J,k,K,N,Q,e.height,a._elementsPixelRatio,D]);const[et,ot]=j(M,300),[nt]=j(k,300,!0),it=nt||et;t.useEffect(()=>{var t;if(!it){return s.autorun(()=>{const t=c.current;d(t,e)})}null===(t=c.current)||void 0===t||t.clearCache()},[h,it,e.shadowColor,e.shadowOffsetX,e.shadowOffsetY,e.shadowOpacity]),t.useEffect(()=>{h&&!M&&tt.current&&(tt.current(),tt.current=null)},[h,M]),t.useLayoutEffect(()=>{if(!D){return}if(!e.curveEnabled){return}const t=new l.TextPath({data:P(e.a.width,e.a.height,e.curvePower,e.a.fontSize),text:$(e.text),letterSpacing:e.letterSpacing*e.a.fontSize,fontSize:e.a.fontSize,fontFamily:e.fontFamily,fontWeight:e.fontWeight,fontStyle:e.fontStyle,align:"center",textBaseline:"middle",fill:e.fill}),o=t.getSelfRect().width;if(o){const t=o-e.a.width,n=e.a.rotation*Math.PI/180,i=-t/2*Math.cos(n),r=-t/2*Math.sin(n);e.set({width:o,x:e.a.x+i,y:e.a.y+r})}t.destroy()},[D,e.curveEnabled,e.curvePower,e.text,e.fontSize,e.fontFamily,e.fontWeight,e.fontStyle,e.letterSpacing]),t.useEffect(()=>()=>{tt.current&&tt.current()},[]),t.useEffect(()=>{B||""!==$(e.text)||!e.removable||e.placeholder||a.deleteElements([e.id])},[B]);let rt=0;"middle"===e.verticalAlign&&(rt=(e.height-K)/2),"bottom"===e.verticalAlign&&(rt=e.height-K);const at=u({fontLoaded:D,fontFamily:e.fontFamily,fontSize:e.fontSize,lineHeight:e.lineHeight}),lt=R(),st=P(e.a.width,K,e.curvePower,e.fontSize),ct=t.useRef(null),ft=t.useRef(null),dt=N&&e.strokeWidth>0&&!e.curveEnabled;return t.createElement(t.Fragment,null,t.createElement(i,{x:e.a.x,y:e.a.y,offsetX:e.backgroundPadding*(e.fontSize*at*.5),offsetY:e.backgroundPadding*(e.fontSize*at*.5),rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*e.a.opacity,fill:e.backgroundColor,width:e.a.width+e.backgroundPadding*(e.fontSize*at),height:e.a.height+e.backgroundPadding*(e.fontSize*at),cornerRadius:e.backgroundCornerRadius*(e.fontSize*at*.5)}),t.createElement(r,{x:e.a.x,y:e.a.y,rotation:e.a.rotation,data:st,stroke:"red",strokeWidth:1,visible:!1}),t.createElement(i,{ref:c,name:"element",x:e.a.x,y:e.a.y,listening:e.selectable,rotation:e.a.rotation,width:e.a.width,height:e.a.height,visible:!it,draggable:lt?e.draggable&&B:e.draggable,preventDefault:!lt||B,opacity:N?0:e.a.opacity,hideInExport:!e.showInExport,onDragMove:t=>{e.set({x:t.target.x(),y:t.target.y()})},onDragEnd:t=>{e.set({x:t.target.x(),y:t.target.y()})},id:e.id,onDblClick:t=>{e.contentEditable&&(ft.current={x:t.evt.clientX,y:t.evt.clientY},e.toggleEditMode(!0))},onDblTap:t=>{var o;if(e.contentEditable){const n=null===(o=t.evt.changedTouches)||void 0===o?void 0:o[0];ft.current=n?{x:n.clientX,y:n.clientY}:null,e.toggleEditMode(!0)}},onTransformStart:t=>{F(!0),A.current=e.height},onTransform:t=>{var o;const n=t.target,i=(null===(o=n.getStage())||void 0===o?void 0:o.findOne("Transformer")).getActiveAnchor(),r="middle-left"===i||"middle-right"===i,a="top-center"===i||"bottom-center"===i,l=n.scaleX();if(r){const t=n.scaleX(),o=n.width()*t,i=e.fontSize;let r=o;if(o<i&&(r=i,ct.current&&n.position(ct.current)),n.width(r),n.scaleX(1),f.textVerticalResizeEnabled){const t=Math.max(K,A.current);e.set({height:t})}e.set({width:n.width(),x:n.x(),y:n.y()})}else if(a){let o="resize"===f.textOverflow?K:e.lineHeight*e.fontSize;const i=Math.max(o,t.target.height()*t.target.scaleY());n.scaleY(1),e.set({x:n.x(),y:n.y(),height:i,rotation:n.rotation()})}else{n.scaleX(1),n.scaleY(1),e.set({fontSize:e.fontSize*l,letterSpacing:e.letterSpacing,width:n.width()*l,x:n.x(),y:n.y(),rotation:n.rotation(),height:n.height()*l})}ct.current=t.target.position()},onTransformEnd:t=>{F(!1),T(!0);const o=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:e.fontSize*o,width:t.target.width()*o,x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),shadowBlur:e.shadowBlur*o,shadowOffsetX:e.shadowOffsetX*o,shadowOffsetY:e.shadowOffsetY*o,strokeWidth:e.strokeWidth*o})}}),t.createElement(o,{ref:c,image:h,x:e.a.x,y:e.a.y,offsetX:L,offsetY:L-rt,listening:!1,rotation:e.a.rotation,width:e.a.width+2*L,height:(e.a.width+2*L)*((null==h?void 0:h.height)/(null==h?void 0:h.width)||1),visible:!it&&!N,opacity:e.a.opacity,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,hideInExport:!e.showInExport,editModeEnabled:e._editModeEnabled||k||it}),(it||dt)&&t.createElement(n,{x:e.a.x,y:e.a.y,rotation:e.a.rotation,offsetY:-rt},t.createElement(S,{divProps:{style:{pointerEvents:"none"}}},t.createElement(W,{dangerouslySetInnerHTML:{__html:J},style:{pointerEvents:"none",opacity:e.a.opacity,textShadow:e.shadowEnabled?`${e.shadowOffsetX}px ${e.shadowOffsetY}px ${e.shadowBlur}px ${e.shadowColor}`:void 0}}))),N&&t.createElement(n,{x:e.a.x,y:e.a.y,rotation:e.a.rotation,offsetY:-rt},t.createElement(S,null,t.createElement(X,{html:J,element:e,onChange:t=>{const o=C({oldText:$(e.text),newText:$(t),element:e});e.set({text:t,fontSize:o})},onBlur:t=>{e.toggleEditMode(!1),ot(!0)},clickCoords:ft.current}))))});export function setCursorFromCoords(t,e){if(!t||!e){return}const{x:o,y:n}=e;try{let e=null;if(document.caretRangeFromPoint){e=document.caretRangeFromPoint(o,n)}else if(document.caretPositionFromPoint){const t=document.caretPositionFromPoint(o,n);t&&(e=document.createRange(),e.setStart(t.offsetNode,t.offset))}if(e){const o=a.find(e.startContainer,!0);if(o){const n=o.offset(t.scroll)+e.startOffset;return void t.setSelection(n,0,"api")}}}catch(i){}t.setSelection(0,0,"api")}
@@ -1 +1 @@
1
- import t from"react";import{observer as e}from"mobx-react-lite";import{Text as n,Group as o,Path as r,TextPath as i}from"react-konva";import{Html as a}from"react-konva-utils";import{autorun as l}from"mobx";import s from"konva";import{parsePath as c,roundCommands as d}from"svg-round-corners";import{useColor as h}from"./use-color.js";import{incrementLoader as u}from"../utils/loader.js";import{isFontLoaded as f}from"../utils/fonts.js";import{flags as g}from"../utils/flags.js";import{removeTags as m}from"../utils/text.js";import{applyFilter as p}from"./apply-filters.js";import{useFadeIn as x}from"./use-fadein.js";import{isTouchDevice as w}from"../utils/screen.js";import{isAlive as y}from"mobx-state-tree";import{getLimitedFontSize as v}from"./text-element/max-font-size.js";import{getOptimalCaretColor as S}from"./text-element/caret-color.js";let E;function b(){return E||(E=document.getElementById("polotno-text-style"),E||(E=document.createElement("style"),E.id="polotno-text-style",document.head.appendChild(E)),E)}s._fixTextRendering=!0;const z={border:"none",padding:"0px",overflow:"hidden",background:"none",outline:"none",resize:"none",overflowWrap:"break-word",whiteSpace:"pre-wrap",userSelect:"text",wordBreak:"normal",textTransform:"none"};function $(t){var e="֑-߿‏‫‮יִ-﷽ﹰ-ﻼ";return new RegExp("^[^"+e+"]*?["+e+"]").test(t)}export function isRTLText(t){t=t.replace(/\s/g,"");let e=0;for(var n=0;n<t.length;n++){$(t[n])&&(e+=1)}return e>t.length/2}export function getDir(t){return isRTLText(t)?"rtl":"ltr"}const O=e(({textNodeRef:e,element:n,onBlur:o,selectAll:r,cursorPosition:i})=>{const[a,l]=t.useState(z),s=e.current;t.useLayoutEffect(()=>{const t={};t.width=s.width()-2*s.padding()+"px",t.height=s.height()-2*s.padding()+s.fontSize()*s.lineHeight()+"px",t.fontSize=s.fontSize()+"px",t.lineHeight=s.lineHeight()+.01,t.fontFamily=s.fontFamily(),t.textAlign=s.align(),t.color=s.fill(),t.fontWeight=n.fontWeight,t.fontStyle=n.fontStyle,t.letterSpacing=n.letterSpacing+"em",t.opacity=Math.max(n.a.opacity,.2),t.textTransform=n.textTransform,t.caretColor=S(n);const e=`\n .polotno-input::placeholder {\n color: ${a.color};\n opacity: 0.6;\n }\n `,o=b();o.innerHTML="",o.appendChild(document.createTextNode(e)),JSON.stringify(t)!==JSON.stringify(a)&&l(t)});const c=t.useRef(null);t.useLayoutEffect(()=>{var t;const e=c.current;if(!e){return}null===(t=c.current)||void 0===t||t.focus();const n=i||e.value.length;e.selectionStart=e.selectionEnd=n,r&&(null==e||e.select(),document.execCommand("selectAll",!1,null))},[]),t.useEffect(()=>{window.addEventListener("blur",o);const t=t=>{var e;(null===(e=c.current)||void 0===e?void 0:e.contains(t.target))||o()};return window.addEventListener("touchstart",t),()=>{window.removeEventListener("blur",o),window.removeEventListener("touchstart",t)}},[]);let d=0;const h=s.textArr.length*s.lineHeight()*s.fontSize();"middle"===n.verticalAlign&&(d=(n.a.height-h)/2),"bottom"===n.verticalAlign&&(d=n.a.height-h);const u=m(n.text);return t.createElement("textarea",{className:"polotno-input",ref:c,dir:getDir(u),style:Object.assign(Object.assign(Object.assign({},z),a),{paddingTop:d+"px"}),value:u,onChange:t=>{const e=v({oldText:n.text,newText:t.target.value,element:n});n.set({text:t.target.value,fontSize:e})},placeholder:n.placeholder,onBlur:o})}),A=e=>t.createElement(a,null,t.createElement(O,Object.assign({},e)));export const useFontLoader=(e,n)=>{const[o,r]=t.useReducer(t=>t+1,0),i=t.useRef(f(n)),a=t.useRef(null);return t.useLayoutEffect(()=>{if(i.current=f(n),i.current){return}let t=!0;return(async()=>{i.current=!1,r();const o=u(`text ${n}`);await e.loadFont(n),t?(a.current=o,i.current=!0,r()):o()})(),()=>{a.current&&(a.current(),a.current=null),t=!1}},[n]),t.useEffect(()=>{i.current&&setTimeout(()=>{a.current&&(a.current(),a.current=null)})},[i.current]),[i.current]};export const getLineHeight=({fontLoaded:e,fontFamily:n,fontSize:o,lineHeight:r})=>t.useMemo(()=>{if("number"==typeof r){return r}const t=document.createElement("div");t.style.fontFamily=n,t.style.fontSize=o+"px",t.style.lineHeight=r,t.innerText="Test text",document.body.appendChild(t);const e=t.offsetHeight;return document.body.removeChild(t),e/o},[e,n,o,r]);export function usePrevious(e){const n=t.useRef(e),o=t.useRef(e);return t.useMemo(()=>{o.current=n.current,n.current=e},[e]),o.current}export function getCurvePath(t,e,n,o){const r=Math.max(-.9999,Math.min(.9999,n));if(Math.abs(r)<1e-4){return`M 0 ${e/2} L ${t} ${e/2}`}const i=5*o/(2*Math.abs(r))-o,a=t/2;if(r>0){const t=2*i+o/2;return[`M ${a} ${t}`,`A ${i} ${i} 0 1 1 ${a} ${t-2*i}`,`A ${i} ${i} 0 1 1 ${a} ${t}`].join(" ")}{const t=-(2*i-Math.round(e))-o/2;return[`M ${a} ${t}`,`A ${i} ${i} 0 1 0 ${a} ${t+2*i}`,`A ${i} ${i} 0 1 0 ${a} ${t}`].join(" ")}}export const TextElement=e(({element:e,store:a})=>{const s=t.useRef(null),u=t.useRef(null),f=t.useRef(null),{editorEnabled:v,selectAll:S}=(e=>{const[n,o]=t.useState(!1),r=t.useRef(!1);return t.useEffect(()=>{var t=!0;return setTimeout(()=>{t&&(e._editModeEnabled&&(r.current=!0),o(!0),setTimeout(()=>{r.current=!1},50))},50),()=>{t=!1}},[]),{editorEnabled:n&&e._editModeEnabled,selectAll:r.current}})(e),[E,b]=t.useState(!1),z=t.useRef(e.a.height),$=a.selectedShapes.indexOf(e)>=0&&e.selectable,{textVerticalResizeEnabled:O}=g,M=usePrevious(e.fontFamily),[k,F]=t.useState([]);t.useEffect(()=>{var t,e;const n=null!==(e=null===(t=s.current)||void 0===t?void 0:t.textArr)&&void 0!==e?e:[];JSON.stringify(n)!==JSON.stringify(k)&&F(n)}),t.useEffect(()=>{if(e.a.width){return}const t=s.current;t.width(600),e.set({width:1.4*t.getTextWidth()})},[]),t.useEffect(()=>{$||""!==e.text||!e.removable||e.placeholder||a.deleteElements([e.id])},[$]),t.useLayoutEffect(()=>l(()=>{const t=s.current;p(t,e)}));const[L]=useFontLoader(a,e.fontFamily);let T=m(e.text);"uppercase"===e.textTransform&&(T=T.toUpperCase());const R=()=>{if(e.curveEnabled){const t=u.current;return t.getSelfRect().height||t.fontSize()}const t=s.current.clone({height:void 0}),n=Math.ceil(t.fontSize()*t.lineHeight()*t.textArr.length+1);return t.destroy(),n};t.useLayoutEffect(()=>{if(!L){return}const{textOverflow:t,textSplitAllowed:n}=g;if(!e.a.height){const t=R();return void a.history.ignore(()=>{e.set({height:t})})}if(!a.isPlaying){if("change-font-size"!==t||E){if("resize"===t){const t=R();O&&e.a.height<t&&!E&&a.history.ignore(()=>{var n;y(e)&&e.set({height:t}),null===(n=s.current)||void 0===n||n.height(t)},!1,!0),O||e.a.height===t||E||a.history.ignore(()=>{var n;y(e)&&e.set({height:t}),null===(n=s.current)||void 0===n||n.height(t)},!1,!0)}}else{const t=function(t,e,n=!1){const o=t.fontSize(),r=t.height(),i=m(e.text);let a=e.a.fontSize;t.height(void 0);const l=Math.round(2*e.a.fontSize)-1;for(let s=1;s<l;s++){const o=e.a.height&&t.height()>e.a.height;let r=i.split("\n").join(" ").split(/[\s-]+/).reduce((t,e)=>/[\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\uFF00-\uFFEF\u4E00-\u9FAF\uAC00-\uD7AF]/.test(e)?t.concat(e.split("")):t.concat(e),[]),l=t.textArr.map(t=>t.text).join(";");const s=r.find(t=>!l.includes(t)||(l=l.replace(t,""),!1));if(!(o||s&&!n)){break}a-=.5,t.fontSize(a)}return t.fontSize(o),t.height(r),a}(s.current,e,n);if(t!==e.a.fontSize){return void a.history.ignore(()=>{e.set({fontSize:t})},!1,!0)}const o=R();e.a.height===o||O||a.history.ignore(()=>{e.set({height:o})},!1,!0)}}}),t.useLayoutEffect(()=>{var t;if(L&&e.curveEnabled){const n=null===(t=u.current)||void 0===t?void 0:t.getSelfRect().width;if(n){const t=n-e.a.width,o=e.a.rotation*Math.PI/180,r=-t/2*Math.cos(o),i=-t/2*Math.sin(o);e.set({width:n,x:e.a.x+r,y:e.a.y+i})}}},[L,e.curveEnabled,e.curvePower,e.text,e.fontSize,e.fontFamily,e.fontWeight,e.fontStyle,e.letterSpacing]),t.useLayoutEffect(()=>{const t=s.current;t&&(t.width(t.width()+1e-8),t.width(t.width()-1e-8),t._setTextData(),p(t,e))},[L]);const j=t.useRef(null),C=t.useRef(0),H=t=>{t.evt.preventDefault();const n=a.selectedShapes.find(t=>t===e);n&&e.contentEditable&&(C.current=function(t){var e;const n=t.target,o=function(t){var e=t.getAbsoluteTransform().copy();e.invert();var n=t.getStage().getPointerPosition();return e.point(n)}(n),r=n.textArr,i=Math.floor(o.y/(n.fontSize()*n.lineHeight())),a=r.slice(0,i).reduce((t,e)=>t+e.text.length,i),l=null!==(e=r[i])&&void 0!==e?e:r[0];let s=0;return"right"===n.align()?s=n.width()-l.width:"center"===n.align()&&(s=n.width()/2-l.width/2),a+Math.round((o.x-s)/l.width*l.text.length)}(t),e.toggleEditMode())},W=!T&&e.placeholder?.6:e.a.opacity;x(s,W);const X=getLineHeight({fontLoaded:L,fontFamily:e.fontFamily,fontSize:e.a.fontSize,lineHeight:e.lineHeight}),Y=e.selectable||"admin"===a.role,P=h(e),B=t.useMemo(()=>e.backgroundEnabled?function({lines:t,lineHeight:e,width:n,align:o="left",padding:r=0,cornerRadius:i=0}){var a;t.forEach((t,e)=>{t.cx=n/2,"right"===o?t.cx=n-t.width/2:"left"===o&&(t.cx=t.width/2),"justify"!==o||t.lastInParagraph||(t.width=n),"justify"===o&&(t.cx=t.width/2)});let l=`M ${null===(a=t[0])||void 0===a?void 0:a.cx} ${-r}`;t.forEach((n,o)=>{const{cx:i}=n,a=t[o-1];a&&a.width>n.width?l+=` L ${i+n.width/2+r} ${o*e+r}`:l+=` L ${i+n.width/2+r} ${o*e-r}`;const s=t[o+1];s&&s.width>n.width?l+=` L ${i+n.width/2+r} ${(o+1)*e-r}`:l+=` L ${i+n.width/2+r} ${(o+1)*e+r}`});for(var s=t.length-1;s>=0;s--){const n=t[s],{cx:o}=n,i=t[s+1];i&&i.width>n.width?l+=` L ${o-n.width/2-r} ${(s+1)*e-r}`:l+=` L ${o-n.width/2-r} ${(s+1)*e+r}`;const a=t[s-1];a&&a.width>n.width?l+=` L ${o-n.width/2-r} ${s*e+r}`:l+=` L ${o-n.width/2-r} ${s*e-r}`}l+=" Z";const h=c(l);return d(h,i).path}({lines:JSON.parse(JSON.stringify(k)),cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*X*.5),lineHeight:X*e.a.fontSize,padding:e.backgroundPadding*(e.a.fontSize*X*.5),width:e.a.width,align:e.align}):"",[e.backgroundEnabled,e.backgroundCornerRadius,e.a.fontSize,X,e.backgroundPadding,e.a.width,e.align,k]),D=w();let N=0;"middle"===e.verticalAlign?N=(e.a.height-k.length*X*e.a.fontSize)/2:"bottom"===e.verticalAlign&&(N=e.a.height-k.length*X*e.a.fontSize);const I=e.curveEnabled?getCurvePath(e.a.width,e.a.height,e.curvePower,e.a.fontSize):"",J=L?'"'+e.fontFamily+'"':M===e.fontFamily?"Arial":'"'+M+'"';return t.createElement(t.Fragment,null,t.createElement(r,{ref:f,x:e.a.x,y:e.a.y,rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*W,data:B,fill:e.backgroundColor,offsetY:-N}),t.createElement(r,{data:I,stroke:"red",strokeWidth:1,x:e.a.x,y:e.a.y,rotation:e.a.rotation,visible:!1}),t.createElement(i,Object.assign({ref:u,visible:e.curveEnabled,data:I,text:T||e.placeholder,listening:!1,align:"center",textBaseline:"middle"},P,{stroke:e.stroke,strokeWidth:e.strokeWidth,lineJoin:"round",fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:`"${e.fontFamily}", "${M}"`,fontStyle:e.fontStyle+" "+e.fontWeight,letterSpacing:e.letterSpacing*e.a.fontSize,x:e.a.x,y:e.a.y,rotation:e.a.rotation,opacity:e._editModeEnabled?.3:W,hideInExport:!e.showInExport,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity})),t.createElement(n,Object.assign({ref:s,id:e.id,name:"element",hideInExport:!e.showInExport,editModeEnabled:e._editModeEnabled,x:e.a.x,y:e.a.y,rotation:e.a.rotation,width:e.a.width,height:e.a.height,text:T||e.placeholder,direction:getDir(T)},P,{stroke:e.stroke,lineJoin:"round",strokeWidth:e.strokeWidth,fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:J,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration,align:e.align,verticalAlign:e.verticalAlign,draggable:D?e.draggable&&$:e.draggable,preventDefault:!D||$,opacity:e.curveEnabled?0:W,visible:!e._editModeEnabled,ellipsis:"ellipsis"===g.textOverflow,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,lineHeight:X,letterSpacing:e.letterSpacing*e.a.fontSize,listening:Y,onDragMove:t=>{e.set({x:t.target.x(),y:t.target.y()})},onDragEnd:t=>{e.set({x:t.target.x(),y:t.target.y()})},onClick:H,onTap:H,onTransformStart:()=>{b(!0),z.current=s.current.height()},onTransform:t=>{var n,o,r;const i=t.target;null===(n=f.current)||void 0===n||n.setAttrs({x:i.x(),y:i.y(),rotation:i.rotation(),scale:i.scale()});const a=(null===(o=i.getStage())||void 0===o?void 0:o.findOne("Transformer")).getActiveAnchor();if("middle-left"===a||"middle-right"===a){const t=i.scaleX(),n=i.width()*t,o=e.a.fontSize;let r=n;n<o&&(r=o,j.current&&i.position(j.current)),i.width(r),i.scaleX(1),i.scaleY(1);const a=R();if("ellipsis"!==g.textOverflow){const t=Math.max(a,z.current);i.height(t),e.set({height:i.height()})}const l=g.textVerticalResizeEnabled?Math.max(a,z.current):R();e.set({x:i.x(),width:i.width(),rotation:i.rotation(),height:l}),p(i,e)}if("top-center"===a||"bottom-center"===a){let n="resize"===g.textOverflow?R():X*e.a.fontSize;t.target.height(Math.max(n,t.target.height()*t.target.scaleY())),t.target.scaleY(1)}j.current=t.target.position();const l=t.target.scaleX();null===(r=f.current)||void 0===r||r.setAttrs({scaleX:1,scaleY:1}),t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:e.a.fontSize*l,width:t.target.width()*l,x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),height:t.target.height()*l,shadowBlur:e.shadowBlur*l,shadowOffsetX:e.shadowOffsetX*l,shadowOffsetY:e.shadowOffsetY*l,strokeWidth:e.strokeWidth*l})},onTransformEnd:t=>{var n;const o=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:Math.round(e.a.fontSize*o),width:Math.ceil(t.target.width()*o),x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),height:t.target.height()*o,shadowBlur:e.shadowBlur*o,shadowOffsetX:e.shadowOffsetX*o,shadowOffsetY:e.shadowOffsetY*o,strokeWidth:e.strokeWidth*o}),null===(n=f.current)||void 0===n||n.setAttrs({scaleX:1,scaleY:1}),b(!1)}})),v&&t.createElement(o,{x:e.a.x,y:e.a.y,rotation:e.a.rotation},t.createElement(A,{textNodeRef:s,element:e,selectAll:S,cursorPosition:C.current,onBlur:()=>{e.toggleEditMode(!1)}})))});
1
+ import t from"react";import{observer as e}from"mobx-react-lite";import{Text as n,Group as o,Path as r,TextPath as i}from"react-konva";import{Html as a}from"react-konva-utils";import{autorun as l}from"mobx";import s from"konva";import{parsePath as c,roundCommands as d}from"svg-round-corners";import{useColor as h}from"./use-color.js";import{incrementLoader as u}from"../utils/loader.js";import{isFontLoaded as f}from"../utils/fonts.js";import{flags as g}from"../utils/flags.js";import{removeTags as m}from"../utils/text.js";import{applyFilter as p}from"./apply-filters.js";import{useFadeIn as x}from"./use-fadein.js";import{isTouchDevice as w}from"../utils/screen.js";import{isAlive as y}from"mobx-state-tree";import{getLimitedFontSize as v}from"./text-element/max-font-size.js";import{getOptimalCaretColor as S}from"./text-element/caret-color.js";let E;function b(){return E||(E=document.getElementById("polotno-text-style"),E||(E=document.createElement("style"),E.id="polotno-text-style",document.head.appendChild(E)),E)}s._fixTextRendering=!0;const z={border:"none",padding:"0px",overflow:"hidden",background:"none",outline:"none",resize:"none",overflowWrap:"break-word",whiteSpace:"pre-wrap",userSelect:"text",wordBreak:"normal",textTransform:"none"};function $(t){var e="֑-߿‏‫‮יִ-﷽ﹰ-ﻼ";return new RegExp("^[^"+e+"]*?["+e+"]").test(t)}export function isRTLText(t){t=t.replace(/\s/g,"");let e=0;for(var n=0;n<t.length;n++){$(t[n])&&(e+=1)}return e>t.length/2}export function getDir(t){return isRTLText(t)?"rtl":"ltr"}const O=e(({textNodeRef:e,element:n,onBlur:o,selectAll:r,cursorPosition:i})=>{const[a,l]=t.useState(z),s=e.current;t.useLayoutEffect(()=>{const t={};t.width=s.width()-2*s.padding()+"px",t.height=s.height()-2*s.padding()+s.fontSize()*s.lineHeight()+"px",t.fontSize=s.fontSize()+"px",t.lineHeight=s.lineHeight()+.01,t.fontFamily=s.fontFamily(),t.textAlign=s.align(),t.color=s.fill(),t.fontWeight=n.fontWeight,t.fontStyle=n.fontStyle,t.letterSpacing=n.letterSpacing+"em",t.opacity=Math.max(n.a.opacity,.2),t.textTransform=n.textTransform,t.caretColor=S(n);const e=`\n .polotno-input::placeholder {\n color: ${a.color};\n opacity: 0.6;\n }\n `,o=b();o.innerHTML="",o.appendChild(document.createTextNode(e)),JSON.stringify(t)!==JSON.stringify(a)&&l(t)});const c=t.useRef(null);t.useLayoutEffect(()=>{var t;const e=c.current;if(!e){return}null===(t=c.current)||void 0===t||t.focus();const n=i||e.value.length;e.selectionStart=e.selectionEnd=n,r&&(null==e||e.select(),document.execCommand("selectAll",!1,null))},[]),t.useEffect(()=>{window.addEventListener("blur",o);const t=t=>{var e;(null===(e=c.current)||void 0===e?void 0:e.contains(t.target))||o()};return window.addEventListener("touchstart",t),()=>{window.removeEventListener("blur",o),window.removeEventListener("touchstart",t)}},[]);let d=0;const h=s.textArr.length*s.lineHeight()*s.fontSize();"middle"===n.verticalAlign&&(d=(n.a.height-h)/2),"bottom"===n.verticalAlign&&(d=n.a.height-h);const u=m(n.text);return t.createElement("textarea",{className:"polotno-input",ref:c,dir:getDir(u),style:Object.assign(Object.assign(Object.assign({},z),a),{paddingTop:d+"px"}),value:u,onChange:t=>{const e=v({oldText:n.text,newText:t.target.value,element:n});n.set({text:t.target.value,fontSize:e})},placeholder:n.placeholder,onBlur:o})}),A=e=>t.createElement(a,null,t.createElement(O,Object.assign({},e)));export const useFontLoader=(e,n)=>{const[o,r]=t.useReducer(t=>t+1,0),i=t.useRef(f(n)),a=t.useRef(null);return t.useLayoutEffect(()=>{if(i.current=f(n),i.current){return}let t=!0;return(async()=>{i.current=!1,r();const o=u(`text ${n}`);await e.loadFont(n),t?(a.current=o,i.current=!0,r()):o()})(),()=>{a.current&&(a.current(),a.current=null),t=!1}},[n]),t.useEffect(()=>{i.current&&setTimeout(()=>{a.current&&(a.current(),a.current=null)},100)},[i.current]),[i.current]};export const getLineHeight=({fontLoaded:e,fontFamily:n,fontSize:o,lineHeight:r})=>t.useMemo(()=>{if("number"==typeof r){return r}const t=document.createElement("div");t.style.fontFamily=n,t.style.fontSize=o+"px",t.style.lineHeight=r,t.innerText="Test text",document.body.appendChild(t);const e=t.offsetHeight;return document.body.removeChild(t),e/o},[e,n,o,r]);export function usePrevious(e){const n=t.useRef(e),o=t.useRef(e);return t.useMemo(()=>{o.current=n.current,n.current=e},[e]),o.current}export function getCurvePath(t,e,n,o){const r=Math.max(-.9999,Math.min(.9999,n));if(Math.abs(r)<1e-4){return`M 0 ${e/2} L ${t} ${e/2}`}const i=5*o/(2*Math.abs(r))-o,a=t/2;if(r>0){const t=2*i+o/2;return[`M ${a} ${t}`,`A ${i} ${i} 0 1 1 ${a} ${t-2*i}`,`A ${i} ${i} 0 1 1 ${a} ${t}`].join(" ")}{const t=-(2*i-Math.round(e))-o/2;return[`M ${a} ${t}`,`A ${i} ${i} 0 1 0 ${a} ${t+2*i}`,`A ${i} ${i} 0 1 0 ${a} ${t}`].join(" ")}}export const TextElement=e(({element:e,store:a})=>{const s=t.useRef(null),u=t.useRef(null),f=t.useRef(null),{editorEnabled:v,selectAll:S}=(e=>{const[n,o]=t.useState(!1),r=t.useRef(!1);return t.useEffect(()=>{var t=!0;return setTimeout(()=>{t&&(e._editModeEnabled&&(r.current=!0),o(!0),setTimeout(()=>{r.current=!1},50))},50),()=>{t=!1}},[]),{editorEnabled:n&&e._editModeEnabled,selectAll:r.current}})(e),[E,b]=t.useState(!1),z=t.useRef(e.a.height),$=a.selectedShapes.indexOf(e)>=0&&e.selectable,{textVerticalResizeEnabled:O}=g,M=usePrevious(e.fontFamily),[k,F]=t.useState([]);t.useEffect(()=>{var t,e;const n=null!==(e=null===(t=s.current)||void 0===t?void 0:t.textArr)&&void 0!==e?e:[];JSON.stringify(n)!==JSON.stringify(k)&&F(n)}),t.useEffect(()=>{if(e.a.width){return}const t=s.current;t.width(600),e.set({width:1.4*t.getTextWidth()})},[]),t.useEffect(()=>{$||""!==e.text||!e.removable||e.placeholder||a.deleteElements([e.id])},[$]),t.useLayoutEffect(()=>l(()=>{const t=s.current;p(t,e)}));const[L]=useFontLoader(a,e.fontFamily);let T=m(e.text);"uppercase"===e.textTransform&&(T=T.toUpperCase());const R=()=>{if(e.curveEnabled){const t=u.current;return t.getSelfRect().height||t.fontSize()}const t=s.current.clone({height:void 0}),n=Math.ceil(t.fontSize()*t.lineHeight()*t.textArr.length+1);return t.destroy(),n};t.useLayoutEffect(()=>{if(!L){return}const{textOverflow:t,textSplitAllowed:n}=g;if(!e.a.height){const t=R();return void a.history.ignore(()=>{e.set({height:t})})}if(!a.isPlaying){if("change-font-size"!==t||E){if("resize"===t){const t=R();O&&e.a.height<t&&!E&&a.history.ignore(()=>{var n;y(e)&&e.set({height:t}),null===(n=s.current)||void 0===n||n.height(t)},!1,!0),O||e.a.height===t||E||a.history.ignore(()=>{var n;y(e)&&e.set({height:t}),null===(n=s.current)||void 0===n||n.height(t)},!1,!0)}}else{const t=function(t,e,n=!1){const o=t.fontSize(),r=t.height(),i=m(e.text);let a=e.a.fontSize;t.height(void 0);const l=Math.round(2*e.a.fontSize)-1;for(let s=1;s<l;s++){const o=e.a.height&&t.height()>e.a.height;let r=i.split("\n").join(" ").split(/[\s-]+/).reduce((t,e)=>/[\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\uFF00-\uFFEF\u4E00-\u9FAF\uAC00-\uD7AF]/.test(e)?t.concat(e.split("")):t.concat(e),[]),l=t.textArr.map(t=>t.text).join(";");const s=r.find(t=>!l.includes(t)||(l=l.replace(t,""),!1));if(!(o||s&&!n)){break}a-=.5,t.fontSize(a)}return t.fontSize(o),t.height(r),a}(s.current,e,n);if(t!==e.a.fontSize){return void a.history.ignore(()=>{e.set({fontSize:t})},!1,!0)}const o=R();e.a.height===o||O||a.history.ignore(()=>{e.set({height:o})},!1,!0)}}}),t.useLayoutEffect(()=>{var t;if(L&&e.curveEnabled){const n=null===(t=u.current)||void 0===t?void 0:t.getSelfRect().width;if(n){const t=n-e.a.width,o=e.a.rotation*Math.PI/180,r=-t/2*Math.cos(o),i=-t/2*Math.sin(o);e.set({width:n,x:e.a.x+r,y:e.a.y+i})}}},[L,e.curveEnabled,e.curvePower,e.text,e.fontSize,e.fontFamily,e.fontWeight,e.fontStyle,e.letterSpacing]),t.useLayoutEffect(()=>{const t=s.current;t&&(t.width(t.width()+1e-8),t.width(t.width()-1e-8),t._setTextData(),p(t,e))},[L]);const j=t.useRef(null),C=t.useRef(0),H=t=>{t.evt.preventDefault();const n=a.selectedShapes.find(t=>t===e);n&&e.contentEditable&&(C.current=function(t){var e;const n=t.target,o=function(t){var e=t.getAbsoluteTransform().copy();e.invert();var n=t.getStage().getPointerPosition();return e.point(n)}(n),r=n.textArr,i=Math.floor(o.y/(n.fontSize()*n.lineHeight())),a=r.slice(0,i).reduce((t,e)=>t+e.text.length,i),l=null!==(e=r[i])&&void 0!==e?e:r[0];let s=0;return"right"===n.align()?s=n.width()-l.width:"center"===n.align()&&(s=n.width()/2-l.width/2),a+Math.round((o.x-s)/l.width*l.text.length)}(t),e.toggleEditMode())},W=!T&&e.placeholder?.6:e.a.opacity;x(s,W);const X=getLineHeight({fontLoaded:L,fontFamily:e.fontFamily,fontSize:e.a.fontSize,lineHeight:e.lineHeight}),Y=e.selectable||"admin"===a.role,P=h(e),B=t.useMemo(()=>e.backgroundEnabled?function({lines:t,lineHeight:e,width:n,align:o="left",padding:r=0,cornerRadius:i=0}){var a;t.forEach((t,e)=>{t.cx=n/2,"right"===o?t.cx=n-t.width/2:"left"===o&&(t.cx=t.width/2),"justify"!==o||t.lastInParagraph||(t.width=n),"justify"===o&&(t.cx=t.width/2)});let l=`M ${null===(a=t[0])||void 0===a?void 0:a.cx} ${-r}`;t.forEach((n,o)=>{const{cx:i}=n,a=t[o-1];a&&a.width>n.width?l+=` L ${i+n.width/2+r} ${o*e+r}`:l+=` L ${i+n.width/2+r} ${o*e-r}`;const s=t[o+1];s&&s.width>n.width?l+=` L ${i+n.width/2+r} ${(o+1)*e-r}`:l+=` L ${i+n.width/2+r} ${(o+1)*e+r}`});for(var s=t.length-1;s>=0;s--){const n=t[s],{cx:o}=n,i=t[s+1];i&&i.width>n.width?l+=` L ${o-n.width/2-r} ${(s+1)*e-r}`:l+=` L ${o-n.width/2-r} ${(s+1)*e+r}`;const a=t[s-1];a&&a.width>n.width?l+=` L ${o-n.width/2-r} ${s*e+r}`:l+=` L ${o-n.width/2-r} ${s*e-r}`}l+=" Z";const h=c(l);return d(h,i).path}({lines:JSON.parse(JSON.stringify(k)),cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*X*.5),lineHeight:X*e.a.fontSize,padding:e.backgroundPadding*(e.a.fontSize*X*.5),width:e.a.width,align:e.align}):"",[e.backgroundEnabled,e.backgroundCornerRadius,e.a.fontSize,X,e.backgroundPadding,e.a.width,e.align,k]),D=w();let N=0;"middle"===e.verticalAlign?N=(e.a.height-k.length*X*e.a.fontSize)/2:"bottom"===e.verticalAlign&&(N=e.a.height-k.length*X*e.a.fontSize);const I=e.curveEnabled?getCurvePath(e.a.width,e.a.height,e.curvePower,e.a.fontSize):"",J=L?'"'+e.fontFamily+'"':M===e.fontFamily?"Arial":'"'+M+'"';return t.createElement(t.Fragment,null,t.createElement(r,{ref:f,x:e.a.x,y:e.a.y,rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*W,data:B,fill:e.backgroundColor,offsetY:-N}),t.createElement(r,{data:I,stroke:"red",strokeWidth:1,x:e.a.x,y:e.a.y,rotation:e.a.rotation,visible:!1}),t.createElement(i,Object.assign({ref:u,visible:e.curveEnabled,data:I,text:T||e.placeholder,listening:!1,align:"center",textBaseline:"middle"},P,{stroke:e.stroke,strokeWidth:e.strokeWidth,lineJoin:"round",fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:`"${e.fontFamily}", "${M}"`,fontStyle:e.fontStyle+" "+e.fontWeight,letterSpacing:e.letterSpacing*e.a.fontSize,x:e.a.x,y:e.a.y,rotation:e.a.rotation,opacity:e._editModeEnabled?.3:W,hideInExport:!e.showInExport,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity})),t.createElement(n,Object.assign({ref:s,id:e.id,name:"element",hideInExport:!e.showInExport,editModeEnabled:e._editModeEnabled,x:e.a.x,y:e.a.y,rotation:e.a.rotation,width:e.a.width,height:e.a.height,text:T||e.placeholder,direction:getDir(T)},P,{stroke:e.stroke,lineJoin:"round",strokeWidth:e.strokeWidth,fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:J,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration,align:e.align,verticalAlign:e.verticalAlign,draggable:D?e.draggable&&$:e.draggable,preventDefault:!D||$,opacity:e.curveEnabled?0:W,visible:!e._editModeEnabled,ellipsis:"ellipsis"===g.textOverflow,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,lineHeight:X,letterSpacing:e.letterSpacing*e.a.fontSize,listening:Y,onDragMove:t=>{e.set({x:t.target.x(),y:t.target.y()})},onDragEnd:t=>{e.set({x:t.target.x(),y:t.target.y()})},onClick:H,onTap:H,onTransformStart:()=>{b(!0),z.current=s.current.height()},onTransform:t=>{var n,o,r;const i=t.target;null===(n=f.current)||void 0===n||n.setAttrs({x:i.x(),y:i.y(),rotation:i.rotation(),scale:i.scale()});const a=(null===(o=i.getStage())||void 0===o?void 0:o.findOne("Transformer")).getActiveAnchor();if("middle-left"===a||"middle-right"===a){const t=i.scaleX(),n=i.width()*t,o=e.a.fontSize;let r=n;n<o&&(r=o,j.current&&i.position(j.current)),i.width(r),i.scaleX(1),i.scaleY(1);const a=R();if("ellipsis"!==g.textOverflow){const t=Math.max(a,z.current);i.height(t),e.set({height:i.height()})}const l=g.textVerticalResizeEnabled?Math.max(a,z.current):R();e.set({x:i.x(),width:i.width(),rotation:i.rotation(),height:l}),p(i,e)}if("top-center"===a||"bottom-center"===a){let n="resize"===g.textOverflow?R():X*e.a.fontSize;t.target.height(Math.max(n,t.target.height()*t.target.scaleY())),t.target.scaleY(1)}j.current=t.target.position();const l=t.target.scaleX();null===(r=f.current)||void 0===r||r.setAttrs({scaleX:1,scaleY:1}),t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:e.a.fontSize*l,width:t.target.width()*l,x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),height:t.target.height()*l,shadowBlur:e.shadowBlur*l,shadowOffsetX:e.shadowOffsetX*l,shadowOffsetY:e.shadowOffsetY*l,strokeWidth:e.strokeWidth*l})},onTransformEnd:t=>{var n;const o=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:Math.round(e.a.fontSize*o),width:Math.ceil(t.target.width()*o),x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),height:t.target.height()*o,shadowBlur:e.shadowBlur*o,shadowOffsetX:e.shadowOffsetX*o,shadowOffsetY:e.shadowOffsetY*o,strokeWidth:e.strokeWidth*o}),null===(n=f.current)||void 0===n||n.setAttrs({scaleX:1,scaleY:1}),b(!1)}})),v&&t.createElement(o,{x:e.a.x,y:e.a.y,rotation:e.a.rotation},t.createElement(A,{textNodeRef:s,element:e,selectAll:S,cursorPosition:C.current,onBlur:()=>{e.toggleEditMode(!1)}})))});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polotno",
3
- "version": "2.29.0",
3
+ "version": "2.29.1",
4
4
  "description": "Design Editor Framework",
5
5
  "author": "Anton Lavrenov",
6
6
  "keywords": [