polotno 2.32.2 → 2.32.4

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.
@@ -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 v}from"mobx-state-tree";import{getLimitedFontSize as y}from"./text-element/max-font-size.js";import{getOptimalCaretColor as E}from"./text-element/caret-color.js";let S;function b(){return S||(S=document.getElementById("polotno-text-style"),S||(S=document.createElement("style"),S.id="polotno-text-style",document.head.appendChild(S)),S)}s._fixTextRendering=!0;const $={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 z(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++){z(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($),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=E(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({},$),a),{paddingTop:d+"px"}),value:u,onChange:t=>{const e=y({oldText:n.text,newText:t.target.value,element:n});n.set({text:t.target.value,fontSize:e})},placeholder:n.placeholder,onBlur:o})}),M=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),f=t.useRef(null),y=t.useRef(null),{editorEnabled:E,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),[b,$]=t.useState(!1),z=t.useRef(e.a.height),O=a.selectedShapes.indexOf(e)>=0&&e.selectable,k=usePrevious(O),{textVerticalResizeEnabled:A}=g,L=g.autoDeleteEmptyText,F=usePrevious(e.fontFamily),[R,T]=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(R)&&T(n)}),t.useEffect(()=>{if(e.a.width){return}const t=s.current;t.width(600),e.set({width:1.4*t.getTextWidth()})},[]),t.useEffect(()=>{k&&!O&&L&&""===e.text&&e.removable&&!e.placeholder&&a.deleteElements([e.id])},[L,e.placeholder,e.removable,e.text,O,k]),t.useLayoutEffect(()=>l(()=>{const t=s.current;p(t,e)}));const[j]=useFontLoader(a,e.fontFamily);let C=m(e.text);"uppercase"===e.textTransform&&(C=C.toUpperCase());const H=()=>{if(e.curveEnabled){const t=f.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(!j){return}const{textOverflow:t,textSplitAllowed:n}=g,o=(t,...n)=>{const o=u(`text ${e.id} before ignore`);a.history.ignore(t,...n).then(()=>{o()})};if(!e.a.height){const t=H();return void o(()=>{e.set({height:t})})}if(!a.isPlaying){if("change-font-size"!==t||b){if("resize"===t){const t=H();A&&e.a.height<t&&!b&&o(()=>{var n;v(e)&&e.set({height:t}),null===(n=s.current)||void 0===n||n.height(t)},!1,!0),A||e.a.height===t||b||o(()=>{var n;v(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)=>(e=e.toLowerCase(),/[\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.toLowerCase()).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 o(()=>{e.set({fontSize:t})},!1,!0)}const r=H();e.a.height===r||A||o(()=>{e.set({height:r})},!1,!0)}}}),t.useLayoutEffect(()=>{var t;if(j&&e.curveEnabled){const n=null===(t=f.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})}}},[j,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))},[j]);const P=t.useRef(null),W=t.useRef(0),X=t=>{t.evt.preventDefault();const n=a.selectedShapes.find(t=>t===e);n&&e.contentEditable&&(W.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())},Y=!C&&e.placeholder?.6:e.a.opacity;x(s,Y);const B=getLineHeight({fontLoaded:j,fontFamily:e.fontFamily,fontSize:e.a.fontSize,lineHeight:e.lineHeight}),D=e.selectable||"admin"===a.role,N=h(e),I=t.useMemo(()=>e.backgroundEnabled?e.curveEnabled?function({width:t,height:e,padding:n=0,cornerRadius:o=0}){const r=-n,i=-n,a=t+n,l=e+n,s=c(`M ${r} ${i} L ${a} ${i} L ${a} ${l} L ${r} ${l} Z`);return d(s,o).path}({width:e.a.width,height:e.a.height,cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*B*.5),padding:e.backgroundPadding*(e.a.fontSize*B*.5)}):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(R)),cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*B*.5),lineHeight:B*e.a.fontSize,padding:e.backgroundPadding*(e.a.fontSize*B*.5),width:e.a.width,align:e.align}):"",[e.backgroundEnabled,e.curveEnabled,e.backgroundCornerRadius,e.a.fontSize,e.a.height,B,e.backgroundPadding,e.a.width,e.align,R]),J=w();let _=0;e.curveEnabled||("middle"===e.verticalAlign?_=(e.a.height-R.length*B*e.a.fontSize)/2:"bottom"===e.verticalAlign&&(_=e.a.height-R.length*B*e.a.fontSize));const V=e.curveEnabled?getCurvePath(e.a.width,e.a.height,e.curvePower,e.a.fontSize):"",Z=j?'"'+e.fontFamily+'"':F===e.fontFamily?"Arial":'"'+F+'"';return t.createElement(t.Fragment,null,t.createElement(r,{ref:y,x:e.a.x,y:e.a.y,rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*Y,data:I,fill:e.backgroundColor,offsetY:-_}),t.createElement(r,{data:V,stroke:"red",strokeWidth:1,x:e.a.x,y:e.a.y,rotation:e.a.rotation,visible:!1}),t.createElement(i,Object.assign({ref:f,visible:e.curveEnabled,data:V,text:C||e.placeholder,listening:!1,align:"center",textBaseline:"middle"},N,{stroke:e.stroke,strokeWidth:e.strokeWidth,lineJoin:"round",fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:`"${e.fontFamily}", "${F}"`,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration.trim(),letterSpacing:e.letterSpacing*e.a.fontSize,x:e.a.x,y:e.a.y,rotation:e.a.rotation,opacity:e._editModeEnabled?.3:Y,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:C||e.placeholder,direction:getDir(C)},N,{stroke:e.stroke,lineJoin:"round",strokeWidth:e.strokeWidth,fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:Z,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration,align:e.align,verticalAlign:e.verticalAlign,draggable:J?e.draggable&&O:e.draggable,preventDefault:!J||O,opacity:e.curveEnabled?0:Y,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:B,letterSpacing:e.letterSpacing*e.a.fontSize,listening:D,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:X,onTap:X,onTransformStart:()=>{$(!0),z.current=s.current.height()},onTransform:t=>{var n,o,r;const i=t.target;null===(n=y.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,P.current&&i.position(P.current)),i.width(r),i.scaleX(1),i.scaleY(1);const a=H();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):H();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?H():B*e.a.fontSize;t.target.height(Math.max(n,t.target.height()*t.target.scaleY())),t.target.scaleY(1)}P.current=t.target.position();const l=t.target.scaleX();null===(r=y.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=y.current)||void 0===n||n.setAttrs({scaleX:1,scaleY:1}),$(!1)}})),E&&t.createElement(o,{x:e.a.x,y:e.a.y,rotation:e.a.rotation},t.createElement(M,{textNodeRef:s,element:e,selectAll:S,cursorPosition:W.current,onBlur:()=>{e.toggleEditMode(!1)}})))});
1
+ import t from"react";import{observer as e}from"mobx-react-lite";import{Group as n,Path as o,Text 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 v}from"mobx-state-tree";import{getLimitedFontSize as y}from"./text-element/max-font-size.js";import{getOptimalCaretColor as E}from"./text-element/caret-color.js";let S;function b(){return S||(S=document.getElementById("polotno-text-style"),S||(S=document.createElement("style"),S.id="polotno-text-style",document.head.appendChild(S)),S)}s._fixTextRendering=!0;const $={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 z(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++){z(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($),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=E(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);if(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)}},[]),!s){return null}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({},$),a),{paddingTop:d+"px"}),value:u,onChange:t=>{const e=y({oldText:n.text,newText:t.target.value,element:n});n.set({text:t.target.value,fontSize:e})},placeholder:n.placeholder,onBlur:o})}),M=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),f=t.useRef(null),y=t.useRef(null),{editorEnabled:E,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),[b,$]=t.useState(!1),z=t.useRef(e.a.height),O=a.selectedShapes.indexOf(e)>=0&&e.selectable,k=usePrevious(O),{textVerticalResizeEnabled:A}=g,L=g.autoDeleteEmptyText,F=usePrevious(e.fontFamily),[R,T]=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(R)&&T(n)}),t.useEffect(()=>{if(e.a.width){return}const t=s.current;t.width(600),e.set({width:1.4*t.getTextWidth()})},[]),t.useEffect(()=>{k&&!O&&L&&""===e.text&&e.removable&&!e.placeholder&&a.deleteElements([e.id])},[L,e.placeholder,e.removable,e.text,O,k]),t.useLayoutEffect(()=>l(()=>{const t=s.current;p(t,e)}));const[j]=useFontLoader(a,e.fontFamily);let C=m(e.text);"uppercase"===e.textTransform&&(C=C.toUpperCase());const H=()=>{if(e.curveEnabled){const t=f.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(!j){return}const{textOverflow:t,textSplitAllowed:n}=g,o=(t,...n)=>{const o=u(`text ${e.id} before ignore`);a.history.ignore(t,...n).then(()=>{o()})};if(!e.a.height){const t=H();return void o(()=>{e.set({height:t})})}if(!a.isPlaying){if("change-font-size"!==t||b){if("resize"===t){const t=H();A&&e.a.height<t&&!b&&o(()=>{var n;v(e)&&e.set({height:t}),null===(n=s.current)||void 0===n||n.height(t)},!1,!0),A||e.a.height===t||b||o(()=>{var n;v(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)=>(e=e.toLowerCase(),/[\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.toLowerCase()).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 o(()=>{e.set({fontSize:t})},!1,!0)}const r=H();e.a.height===r||A||o(()=>{e.set({height:r})},!1,!0)}}}),t.useLayoutEffect(()=>{var t;if(j&&e.curveEnabled){const n=null===(t=f.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})}}},[j,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))},[j]);const P=t.useRef(null),W=t.useRef(0),X=t=>{t.evt.preventDefault();const n=a.selectedShapes.find(t=>t===e);n&&e.contentEditable&&(W.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())},Y=!C&&e.placeholder?.6:e.a.opacity;x(s,Y);const B=getLineHeight({fontLoaded:j,fontFamily:e.fontFamily,fontSize:e.a.fontSize,lineHeight:e.lineHeight}),D=e.selectable||"admin"===a.role,N=h(e),I=t.useMemo(()=>e.backgroundEnabled?e.curveEnabled?function({width:t,height:e,padding:n=0,cornerRadius:o=0}){const r=-n,i=-n,a=t+n,l=e+n,s=c(`M ${r} ${i} L ${a} ${i} L ${a} ${l} L ${r} ${l} Z`);return d(s,o).path}({width:e.a.width,height:e.a.height,cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*B*.5),padding:e.backgroundPadding*(e.a.fontSize*B*.5)}):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(R)),cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*B*.5),lineHeight:B*e.a.fontSize,padding:e.backgroundPadding*(e.a.fontSize*B*.5),width:e.a.width,align:e.align}):"",[e.backgroundEnabled,e.curveEnabled,e.backgroundCornerRadius,e.a.fontSize,e.a.height,B,e.backgroundPadding,e.a.width,e.align,R]),J=w();let _=0;e.curveEnabled||("middle"===e.verticalAlign?_=(e.a.height-R.length*B*e.a.fontSize)/2:"bottom"===e.verticalAlign&&(_=e.a.height-R.length*B*e.a.fontSize));const V=e.curveEnabled?getCurvePath(e.a.width,e.a.height,e.curvePower,e.a.fontSize):"",Z=j?'"'+e.fontFamily+'"':F===e.fontFamily?"Arial":'"'+F+'"';return t.createElement(t.Fragment,null,t.createElement(o,{ref:y,x:e.a.x,y:e.a.y,rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*Y,data:I,fill:e.backgroundColor,offsetY:-_}),t.createElement(o,{data:V,stroke:"red",strokeWidth:1,x:e.a.x,y:e.a.y,rotation:e.a.rotation,visible:!1}),t.createElement(i,Object.assign({ref:f,visible:e.curveEnabled,data:V,text:C||e.placeholder,listening:!1,align:"center",textBaseline:"middle"},N,{stroke:e.stroke,strokeWidth:e.strokeWidth,lineJoin:"round",fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:`"${e.fontFamily}", "${F}"`,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration.trim(),letterSpacing:e.letterSpacing*e.a.fontSize,x:e.a.x,y:e.a.y,rotation:e.a.rotation,opacity:e._editModeEnabled?.3:Y,hideInExport:!e.showInExport,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity})),t.createElement(r,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:C||e.placeholder,direction:getDir(C)},N,{stroke:e.stroke,lineJoin:"round",strokeWidth:e.strokeWidth,fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:Z,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration,align:e.align,verticalAlign:e.verticalAlign,draggable:J?e.draggable&&O:e.draggable,preventDefault:!J||O,opacity:e.curveEnabled?0:Y,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:B,letterSpacing:e.letterSpacing*e.a.fontSize,listening:D,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:X,onTap:X,onTransformStart:()=>{$(!0),z.current=s.current.height()},onTransform:t=>{var n,o,r;const i=t.target;null===(n=y.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,P.current&&i.position(P.current)),i.width(r),i.scaleX(1),i.scaleY(1);const a=H();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):H();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?H():B*e.a.fontSize;t.target.height(Math.max(n,t.target.height()*t.target.scaleY())),t.target.scaleY(1)}P.current=t.target.position();const l=t.target.scaleX();null===(r=y.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=y.current)||void 0===n||n.setAttrs({scaleX:1,scaleY:1}),$(!1)}})),E&&t.createElement(n,{x:e.a.x,y:e.a.y,rotation:e.a.rotation},t.createElement(M,{textNodeRef:s,element:e,selectAll:S,cursorPosition:W.current,onBlur:()=>{e.toggleEditMode(!1)}})))});
@@ -1 +1 @@
1
- var e=this&&this.__rest||function(e,t){var r={};for(var o in e){Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o])}if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(o=Object.getOwnPropertySymbols(e);i<o.length;i++){t.indexOf(o[i])<0&&Object.prototype.propertyIsEnumerable.call(e,o[i])&&(r[o[i]]=e[o[i]])}}return r};import{types as t,detach as r}from"mobx-state-tree";import{nanoid as o}from"nanoid";import{Node as i}from"./node-model.js";import{Shape as l}from"./shape-model.js";import{TextElement as n}from"./text-model.js";import{ImageElement as d}from"./image-model.js";import{VideoElement as s}from"./video-model.js";import{LineElement as a}from"./line-model.js";import{SVGElement as p}from"./svg-model.js";import{FigureElement as m}from"./figure-model.js";import{GifElement as c}from"./gif-model.js";export const forEveryChild=(e,t)=>{if(e.children){for(const r of e.children){if(!0===t(r)){break}forEveryChild(r,t)}}};const f=[...new Array(20)].map((e,r)=>t.late(()=>y[r]));export const ElementTypes=t.union({dispatcher:e=>{const t=TYPES_MAP[e.type];if(!t){throw new Error(`Unknown element type: "${e.type}"`)}return t}},p,n,d,a,s,m,c,t.late(()=>GroupElement),...f);export const GroupElement=i.named("Group").props({type:"group",children:t.array(ElementTypes)}).views(e=>({get draggable(){let t=!0;return forEveryChild(e,e=>{e.draggable||(t=!1)}),t},get resizable(){let t=!0;return forEveryChild(e,e=>{e.resizable||(t=!1)}),t},get contentEditable(){let t=!0;return forEveryChild(e,e=>{e.contentEditable||(t=!1)}),t},get styleEditable(){let t=!0;return forEveryChild(e,e=>{e.styleEditable||(t=!1)}),t},get locked(){let t=!0;return forEveryChild(e,e=>{e.locked||(t=!1)}),t}})).actions(t=>({set(r){var{draggable:o,contentEditable:i,styleEditable:l,resizable:n}=r,d=e(r,["draggable","contentEditable","styleEditable","resizable"]);void 0!==o&&forEveryChild(t,e=>{e.set({draggable:o})}),void 0!==i&&forEveryChild(t,e=>{e.set({contentEditable:i})}),void 0!==l&&forEveryChild(t,e=>{e.set({styleEditable:l})}),void 0!==n&&forEveryChild(t,e=>{e.set({resizable:n})}),Object.assign(t,d)},addElement(e,{skipSelect:r=!1}={}){const i=TYPES_MAP[e.type];if(!i){return void console.error("Can not find model with type "+e.type)}e.children&&e.children.forEach(e=>{e.id=e.id||o(10)});const l=i.create(Object.assign({id:o(10)},e));return t.children.push(l),l.selectable&&!r&&t.store.selectElements([l.id]),l},setElementZIndex(e,o){const i=t.children.find(t=>t.id===e);i&&(r(i),t.children.remove(i),t.children.splice(o,0,i))}}));const y=[];export const TYPES_MAP={svg:p,text:n,image:d,group:GroupElement,line:a,video:s,figure:m,gif:c};export function registerShapeModel(e,t){const r=e.type;if(!r){throw new Error('You must pass "type" attribute to custom model.')}let o=l.named(r).props(e);t&&(o=t(o)),TYPES_MAP[r]=o,y.push(o)}
1
+ var e=this&&this.__rest||function(e,t){var r={};for(var o in e){Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o])}if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(o=Object.getOwnPropertySymbols(e);i<o.length;i++){t.indexOf(o[i])<0&&Object.prototype.propertyIsEnumerable.call(e,o[i])&&(r[o[i]]=e[o[i]])}}return r};import{detach as t,types as r}from"mobx-state-tree";import{nanoid as o}from"nanoid";import{Node as i}from"./node-model.js";import{Shape as l}from"./shape-model.js";import{TextElement as n}from"./text-model.js";import{ImageElement as s}from"./image-model.js";import{VideoElement as d}from"./video-model.js";import{LineElement as a}from"./line-model.js";import{SVGElement as m}from"./svg-model.js";import{FigureElement as p}from"./figure-model.js";import{GifElement as c}from"./gif-model.js";export const forEveryChild=(e,t)=>{if(e.children){for(const r of e.children){if(!0===t(r)){break}forEveryChild(r,t)}}};const f=[...new Array(20)].map((e,t)=>r.late(()=>y[t]));export const ElementTypes=r.union({dispatcher:e=>{const t=TYPES_MAP[e.type];if(!t){throw new Error(`Unknown element type: "${e.type}"`)}return t}},m,n,s,a,d,p,c,r.late(()=>GroupElement),...f);export const GroupElement=i.named("Group").props({type:"group",children:r.array(ElementTypes)}).views(e=>({get draggable(){let t=!0;return forEveryChild(e,e=>{e.draggable||(t=!1)}),t},get resizable(){let t=!0;return forEveryChild(e,e=>{e.resizable||(t=!1)}),t},get contentEditable(){let t=!0;return forEveryChild(e,e=>{e.contentEditable||(t=!1)}),t},get styleEditable(){let t=!0;return forEveryChild(e,e=>{e.styleEditable||(t=!1)}),t},get locked(){let t=!0;return forEveryChild(e,e=>{e.locked||(t=!1)}),t}})).actions(r=>({set(t){var{draggable:o,contentEditable:i,styleEditable:l,resizable:n}=t,s=e(t,["draggable","contentEditable","styleEditable","resizable"]);void 0!==o&&forEveryChild(r,e=>{e.set({draggable:o})}),void 0!==i&&forEveryChild(r,e=>{e.set({contentEditable:i})}),void 0!==l&&forEveryChild(r,e=>{e.set({styleEditable:l})}),void 0!==n&&forEveryChild(r,e=>{e.set({resizable:n})}),Object.assign(r,s)},addElement(e,{skipSelect:t=!1}={}){const i=TYPES_MAP[e.type];if(!i){return void console.error("Can not find model with type "+e.type)}e.children&&e.children.forEach(e=>{e.id=e.id||o(10)});const l=i.create(Object.assign({id:o(10)},e));return r.children.push(l),l.selectable&&!t&&r.store.selectElements([l.id]),l},setElementZIndex(e,o){const i=r.children.find(t=>t.id===e);i&&(t(i),r.children.remove(i),r.children.splice(o,0,i))},setAnimation(e,t){forEveryChild(r,r=>{r.setAnimation(e,t)})}}));const y=[];export const TYPES_MAP={svg:m,text:n,image:s,group:GroupElement,line:a,video:d,figure:p,gif:c};export function registerShapeModel(e,t){const r=e.type;if(!r){throw new Error('You must pass "type" attribute to custom model.')}let o=l.named(r).props(e);t&&(o=t(o)),TYPES_MAP[r]=o,y.push(o)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polotno",
3
- "version": "2.32.2",
3
+ "version": "2.32.4",
4
4
  "description": "Design Editor Framework",
5
5
  "author": "Anton Lavrenov",
6
6
  "keywords": [
@@ -66,7 +66,7 @@
66
66
  "functions-have-names": "^1.2.3",
67
67
  "gifuct-js": "^2.1.2",
68
68
  "gradient-parser": "^1.1.1",
69
- "konva": "^10.0.8",
69
+ "konva": "^10.0.9",
70
70
  "mensch": "^0.3.4",
71
71
  "mobx": "6.15.0",
72
72
  "mobx-react-lite": "^4.1.1",
@@ -74,9 +74,7 @@
74
74
  "nanoid": "^3.3.11",
75
75
  "quill": "^1.3.7",
76
76
  "rasterizehtml": "^1.3.1",
77
- "react": "^18.2.0",
78
77
  "react-color": "^2.19.3",
79
- "react-dom": "^18.2.0",
80
78
  "react-konva": "^18.2.14",
81
79
  "react-konva-utils": "^2.0.0",
82
80
  "react-sortablejs": "6.1.4",
@@ -113,6 +111,8 @@
113
111
  }
114
112
  ],
115
113
  "devDependencies": {
114
+ "react": "^18.3.1",
115
+ "react-dom": "^18.3.1",
116
116
  "@canvas/image": "^2.0.0",
117
117
  "@size-limit/preset-big-lib": "^11.2.0",
118
118
  "@testing-library/dom": "^10.4.1",