polotno 2.28.3 → 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.
package/canvas/hotkeys.js CHANGED
@@ -1 +1 @@
1
- import{copy as e,cut as t,paste as o}from"../utils/clipboard.js";export function handleHotkey(l,n){var a,r,c,d;if("INPUT"===(null===(a=document.activeElement)||void 0===a?void 0:a.tagName)||"TEXTAREA"===(null===(r=document.activeElement)||void 0===r?void 0:r.tagName)||"true"===(null===(c=document.activeElement)||void 0===c?void 0:c.contentEditable)){return}const i=document.querySelector(".polotno-workspace-container");if(document.activeElement!==i&&!(null==i?void 0:i.contains(document.activeElement))){const e=window.getSelection();if(e&&e.toString().length>0){return}}const s=n.selectedElements.filter(e=>e.removable).map(e=>e.id);46!==l.keyCode&&8!==l.keyCode||n.deleteElements(s);const u=l.ctrlKey||l.metaKey,v=l.shiftKey;if(!u||v||"z"!==l.key.toLowerCase()&&"y"!==l.key.toLowerCase()||(l.preventDefault(),n.history.undo()),u&&v&&("z"===l.key.toLowerCase()||"y"===l.key.toLowerCase())&&(l.preventDefault(),n.history.redo()),u&&"KeyA"===l.code){l.preventDefault();const e=null===(d=n.activePage)||void 0===d?void 0:d.children.filter(e=>e.selectable),t=(null==e?void 0:e.map(e=>e.id))||[];n.selectElements(t)}u&&"KeyC"===l.code&&(l.preventDefault(),e(n)),u&&"KeyX"===l.code&&(l.preventDefault(),t(n)),u&&"KeyV"===l.code&&(l.preventDefault(),o(n)),"ArrowDown"===l.code&&(l.preventDefault(),n.selectedShapes.forEach(e=>{e.draggable&&e.set({y:e.y+1})})),"ArrowUp"===l.code&&(l.preventDefault(),n.selectedShapes.forEach(e=>{e.draggable&&e.set({y:e.y-1})})),"ArrowLeft"===l.code&&(l.preventDefault(),n.selectedShapes.forEach(e=>{e.draggable&&e.set({x:e.x-1})})),"ArrowRight"===l.code&&(l.preventDefault(),n.selectedShapes.forEach(e=>{e.draggable&&e.set({x:e.x+1})}))}
1
+ import{copy as e,cut as t,paste as o}from"../utils/clipboard.js";import{duplicateElements as l}from"../utils/duplicate.js";import{alignBottom as a,alignCenter as c,alignLeft as n,alignMiddle as d,alignRight as i,alignTop as r}from"../utils/alignment.js";const s="rgba(191, 191, 191, 100)";export function handleHotkey(u,v){var p,f,m,y;if("INPUT"===(null===(p=document.activeElement)||void 0===p?void 0:p.tagName)||"TEXTAREA"===(null===(f=document.activeElement)||void 0===f?void 0:f.tagName)||"true"===(null===(m=document.activeElement)||void 0===m?void 0:m.contentEditable)){return}const h=document.querySelector(".polotno-workspace-container");if(document.activeElement!==h&&!(null==h?void 0:h.contains(document.activeElement))){const e=window.getSelection();if(e&&e.toString().length>0){return}}const g=v.selectedElements.filter(e=>e.removable).map(e=>e.id);46!==u.keyCode&&8!==u.keyCode||v.deleteElements(g);const E=u.ctrlKey||u.metaKey,D=u.shiftKey,w=u.altKey;if(!E||D||"z"!==u.key.toLowerCase()&&"y"!==u.key.toLowerCase()||(u.preventDefault(),v.history.undo()),E&&D&&("z"===u.key.toLowerCase()||"y"===u.key.toLowerCase())&&(u.preventDefault(),v.history.redo()),E&&"KeyA"===u.code){u.preventDefault();const e=null===(y=v.activePage)||void 0===y?void 0:y.children.filter(e=>e.selectable),t=(null==e?void 0:e.map(e=>e.id))||[];v.selectElements(t)}if(E&&"KeyC"===u.code&&(u.preventDefault(),e(v)),E&&"KeyX"===u.code&&(u.preventDefault(),t(v)),E&&"KeyV"===u.code&&(u.preventDefault(),o(v)),"ArrowDown"===u.code&&(u.preventDefault(),v.selectedShapes.forEach(e=>{e.draggable&&e.set({y:e.y+1})})),"ArrowUp"===u.code&&(u.preventDefault(),v.selectedShapes.forEach(e=>{e.draggable&&e.set({y:e.y-1})})),"ArrowLeft"===u.code&&(u.preventDefault(),v.selectedShapes.forEach(e=>{e.draggable&&e.set({x:e.x-1})})),"ArrowRight"===u.code&&(u.preventDefault(),v.selectedShapes.forEach(e=>{e.draggable&&e.set({x:e.x+1})})),E&&"KeyG"===u.code){u.preventDefault();const e=v.selectedElements[0];if(e&&"group"===e.type){const t=e;v.ungroupElements([t.id])}else{v.groupElements(v.selectedElements.map(e=>e.id))}}if(E&&"KeyD"===u.code&&(u.preventDefault(),l(v.selectedElements,v)),"KeyT"===u.code&&!E){u.preventDefault();const e=30,t=v.width/2,o=v.width/2-t/2,l=v.height/2-e/2,a=2160,c=(v.width+v.height)/a;v.activePage.addElement({type:"text",x:o,y:l,width:t,fontSize:e*c,text:"Sample Text",fontFamily:"Roboto"})}if("KeyR"===u.code&&!E){u.preventDefault();const e={type:"figure",x:v.width/4,y:v.height/4,width:300,height:300,fill:s,stroke:"#0c0c0c",strokeWidth:0,subType:"rect"};v.activePage.addElement(e)}if("KeyL"===u.code&&!E){u.preventDefault();const e=v.activePage.computedWidth/3,t={type:"line",x:v.activePage.computedWidth/2-e/2,y:v.activePage.computedHeight/2,width:e,color:s};v.activePage.addElement(t)}if("KeyO"===u.code&&!E){u.preventDefault(),u.preventDefault();const e={type:"figure",x:v.width/4,y:v.height/4,width:300,height:300,fill:s,stroke:"#0c0c0c",strokeWidth:0,subType:"circle"};v.activePage.addElement(e)}E&&"Equal"===u.code&&(u.preventDefault(),v.setScale(v.scale+.1)),E&&"Minus"===u.code&&(u.preventDefault(),v.setScale(v.scale-.1)),w&&("KeyA"===u.code&&(u.preventDefault(),n(v)),"KeyD"===u.code&&(u.preventDefault(),i(v)),"KeyS"===u.code&&(u.preventDefault(),a(v)),"KeyW"===u.code&&(u.preventDefault(),r(v)),"KeyV"===u.code&&(u.preventDefault(),d(v)),"KeyH"===u.code&&(u.preventDefault(),c(v))),"BracketRight"===u.code&&(u.preventDefault(),E?v.activePage.moveElementsUp(v.selectedElementsIds):v.activePage.moveElementsTop(v.selectedElementsIds)),"BracketLeft"===u.code&&(u.preventDefault(),E?v.activePage.moveElementsDown(v.selectedElementsIds):v.activePage.moveElementsBottom(v.selectedElementsIds))}
@@ -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 e from"react";import{observer as t}from"mobx-react-lite";import{Button as n,Tooltip as l}from"@blueprintjs/core";import{ChevronUp as a,ChevronDown as i,Duplicate as o,Trash as c,Insert as r}from"@blueprintjs/icons";import{t as m}from"../utils/l10n.js";export const PageControls=t(({store:t,page:d,xPadding:s,yPadding:p})=>{const g=t.pages.length>1,u=t.pages.indexOf(d);return e.createElement("div",{style:{position:"absolute",top:p-40+"px",right:s+"px"}},g&&e.createElement(l,{content:m("workspace.moveUp"),disabled:0===u},e.createElement(n,{icon:e.createElement(a,null),minimal:!0,disabled:0===u,onClick:()=>{d.setZIndex(u-1)}})),g&&e.createElement(l,{content:m("workspace.moveDown"),disabled:u===t.pages.length-1},e.createElement(n,{icon:e.createElement(i,null),minimal:!0,disabled:u===t.pages.length-1,onClick:()=>{const e=t.pages.indexOf(d);d.setZIndex(e+1)}})),e.createElement(l,{content:m("workspace.duplicatePage")},e.createElement(n,{icon:e.createElement(o,null),minimal:!0,onClick:()=>{d.clone()}})),g&&e.createElement(l,{content:m("workspace.removePage")},e.createElement(n,{icon:e.createElement(c,null),minimal:!0,onClick:()=>{t.deletePages([d.id])}})),e.createElement(l,{content:m("workspace.addPage")},e.createElement(n,{icon:e.createElement(r,null),minimal:!0,onClick:()=>{var e,n,l;const a=t.addPage({bleed:(null===(e=t.activePage)||void 0===e?void 0:e.bleed)||0,width:(null===(n=t.activePage)||void 0===n?void 0:n.width)||"auto",height:(null===(l=t.activePage)||void 0===l?void 0:l.height)||"auto"}),i=t.pages.indexOf(d);a.setZIndex(i+1)}})))});
1
+ import e from"react";import{observer as a}from"mobx-react-lite";import{Button as t,Tooltip as n}from"@blueprintjs/core";import{ChevronUp as l,ChevronDown as o,Duplicate as i,Trash as c,Insert as r}from"@blueprintjs/icons";import{t as m}from"../utils/l10n.js";export const PageControls=a(({store:a,page:d,xPadding:s,yPadding:p})=>{const g=a.pages.length>1,u=a.pages.indexOf(d);return e.createElement("div",{style:{position:"absolute",top:p-40+"px",right:s+"px"}},g&&e.createElement(n,{content:m("workspace.moveUp"),disabled:0===u},e.createElement(t,{icon:e.createElement(l,null),minimal:!0,disabled:0===u,onClick:()=>{d.setZIndex(u-1)},"aria-label":m("workspace.moveUp")})),g&&e.createElement(n,{content:m("workspace.moveDown"),disabled:u===a.pages.length-1},e.createElement(t,{icon:e.createElement(o,null),"aria-label":m("workspace.moveDown"),minimal:!0,disabled:u===a.pages.length-1,onClick:()=>{const e=a.pages.indexOf(d);d.setZIndex(e+1)}})),e.createElement(n,{content:m("workspace.duplicatePage")},e.createElement(t,{icon:e.createElement(i,null),minimal:!0,"aria-label":m("workspace.duplicatePage"),onClick:()=>{d.clone()}})),g&&e.createElement(n,{content:m("workspace.removePage")},e.createElement(t,{icon:e.createElement(c,null),"aria-label":m("workspace.removePage"),minimal:!0,onClick:()=>{a.deletePages([d.id])}})),e.createElement(n,{content:m("workspace.addPage")},e.createElement(t,{icon:e.createElement(r,null),minimal:!0,"aria-label":m("workspace.addPage"),onClick:()=>{var e,t,n;const l=a.addPage({bleed:(null===(e=a.activePage)||void 0===e?void 0:e.bleed)||0,width:(null===(t=a.activePage)||void 0===t?void 0:t.width)||"auto",height:(null===(n=a.activePage)||void 0===n?void 0:n.height)||"auto"}),o=a.pages.indexOf(d);l.setZIndex(o+1)}})))});
@@ -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)}})))});
@@ -1 +1 @@
1
- import{types as e,detach as t,getParentOfType as n,getSnapshot as o}from"mobx-state-tree";import{nanoid as i}from"nanoid";import{ElementTypes as r}from"./group-model.js";import{Store as d}from"./store.js";import{forEveryChild as s,TYPES_MAP as c}from"./group-model.js";import{getTotalClientRect as a}from"../utils/math.js";export const Page=e.model("Page",{id:e.identifier,children:e.array(e.late(()=>r)),width:e.optional(e.union(e.number,e.literal("auto")),"auto"),height:e.optional(e.union(e.number,e.literal("auto")),"auto"),background:"white",bleed:0,custom:e.frozen(),duration:5e3,_exporting:!1,_rendering:!1,_forceMount:!1}).postProcessSnapshot(e=>{const t=Object.assign({},e),n={};for(var o in t){"_"!==o[0]&&(n[o]=e[o])}return n}).views(e=>({get store(){return n(e,d)}})).views(e=>({get startTime(){let t=0;for(const n of e.store.pages){if(n.id===e.id){return t}t+=n.duration}return t},get _exportingOrRendering(){return e._exporting||e._rendering}})).views(e=>({get computedWidth(){return"auto"===e.width?e.store.width:e.width},get computedHeight(){return"auto"===e.height?e.store.height:e.height}})).actions(e=>({toJSON:()=>JSON.parse(JSON.stringify(o(e))),_forEachElementUp(t,n){const o=t.map(t=>({id:t,index:e.children.findIndex(e=>e.id===t)}));o.sort((e,t)=>t.index-e.index);for(const{index:i}of o){if(-1==i){continue}const o=i<e.children.length-1&&e.children[i+1],r=t.indexOf(null==o?void 0:o.id)>=0;i===e.children.length-1||r||n(i)}},_forEachElementDown(t,n){const o=t.map(t=>({id:t,index:e.children.findIndex(e=>e.id===t)}));o.sort((e,t)=>e.index-t.index);for(const{index:i}of o){if(-1==i){continue}const o=i>0&&e.children[i-1],r=t.indexOf(null==o?void 0:o.id)>=0;0===i||r||n(i)}return!1}})).actions(e=>({clone(t={}){const n=e.toJSON();n.children.forEach(e=>{e.id=i(10),s(e,e=>{e.id=i(10)})});const o=Object.assign(Object.assign(Object.assign({},n),{id:i(10)}),t),r=e.store.addPage(o),d=e.store.pages.indexOf(e);return r.setZIndex(d+1),r.select(),r},setZIndex(t){e.store.setPageZIndex(e.id,t)},set(t){Object.assign(e,t)},select(){e.store.selectPage(e.id)},addElement(t,{skipSelect:n=!1}={}){const o=c[t.type];if(!o){return void console.error("Can not find model with type "+t.type)}"children"in t&&Array.isArray(t.children)&&s(t,e=>{e.id=e.id||i(10)});const r=o.create(Object.assign({id:i(10)},t));return e.children.push(r),r.selectable&&!n&&e.store.selectElements([r.id]),r},canMoveElementsUp(t){let n=!1;return e._forEachElementUp(t,()=>{n=n||!0}),n},moveElementsUp(n){e._forEachElementUp(n,n=>{const o=e.children[n];t(o),e.children.splice(n+1,0,o)})},canMoveElementsTop(e){return this.canMoveElementsUp(e)},moveElementsTop(t){const n=[],o=[];e.children.forEach(e=>{t.indexOf(e.id)>=0?n.push(e):o.push(e)}),e.children.replace(o.concat(n))},canMoveElementsDown(t){let n=!1;return e._forEachElementDown(t,()=>{n=n||!0}),n},moveElementsDown(n){e._forEachElementDown(n,n=>{const o=e.children[n];t(o),e.children.splice(n-1,0,o)})},canMoveElementsBottom(e){return this.canMoveElementsDown(e)},moveElementsBottom(t){const n=[],o=[];e.children.forEach(e=>{t.indexOf(e.id)>=0?n.push(e):o.push(e)}),e.children.replace(n.concat(o))},setElementZIndex(n,o){const i=e.children.find(e=>e.id===n);i&&(t(i),e.children.remove(i),e.children.splice(o,0,i))},setSize({width:t,height:n,useMagic:o,softChange:i}){if(o){const o=[],i=t=>"image"===t.type&&t.x<1&&t.y<1&&t.width>=e.computedWidth-2&&t.height>=e.computedHeight-2;s(e,e=>{"group"!==e.type&&(i(e)||o.push(e))});const r=o.length?a(o):{x:0,y:0,width:e.computedWidth,height:e.computedHeight},d=1/4,c=Math.max(0,Math.min(r.x,e.computedWidth-r.x-r.width)),m=e.computedWidth*d,h=Math.max(0,c-m),l=Math.max(0,Math.min(r.y,e.computedHeight-r.y-r.height)),p=e.computedHeight*d,g=Math.max(0,l-p),u=e.computedWidth-2*h,f=e.computedHeight-2*g,E=t/u,x=n/f,v=Math.min(E,x),w=(t-u*v)/2-h*v,y=(n-f*v)/2-g*v;s(e,e=>{"group"!==e.type&&(i(e)?e.set({x:e.x*v,y:e.y*v,width:e.width*E,height:e.height*x,cropX:0,cropY:0,cropWidth:1,cropHeight:1}):(e.set({x:w+e.x*v,y:y+e.y*v,width:e.width*v,height:e.height*v}),"text"===e.type?e.set({fontSize:e.fontSize*v}):"figure"===e.type&&e.set({strokeWidth:e.strokeWidth*v})))})}i||(e.width=t),i||(e.height=n)}})).actions(e=>({moveElementUp(t){console.warn("page.moveElementUp(id) is deprecated. Please use page.moveElementsUp([id1, id2]) instead."),e.moveElementsUp([t])},moveElementDown(t){console.warn("page.moveElementDown(id) is deprecated. Please use page.moveElementsDown([id1, id2]) instead."),e.moveElementsDown([t])},moveElementTop(t){console.warn("page.moveElementTop(id) is deprecated. Please use page.moveElementsTop([id1, id2]) instead."),e.moveElementsTop([t])},moveElementBottom(t){console.warn("page.moveElementBottom(id) is deprecated. Please use page.moveElementsBottom([id1, id2]) instead."),e.moveElementsBottom([t])},play(){e.store.play({startTime:e.startTime,endTime:e.startTime+e.duration})}}));
1
+ import{detach as e,getParentOfType as t,getSnapshot as n,types as i}from"mobx-state-tree";import{nanoid as o}from"nanoid";import{ElementTypes as r,forEveryChild as d,TYPES_MAP as s}from"./group-model.js";import{Store as c}from"./store.js";import{getTotalClientRect as a}from"../utils/math.js";export const Page=i.model("Page",{id:i.identifier,children:i.array(i.late(()=>r)),width:i.optional(i.union(i.number,i.literal("auto")),"auto"),height:i.optional(i.union(i.number,i.literal("auto")),"auto"),background:"white",bleed:0,custom:i.frozen(),duration:5e3,_exporting:!1,_rendering:!1,_forceMount:!1}).postProcessSnapshot(e=>{const t=Object.assign({},e),n={};for(var i in t){"_"!==i[0]&&(n[i]=e[i])}return n}).views(e=>({get store(){return t(e,c)}})).views(e=>({get startTime(){let t=0;for(const n of e.store.pages){if(n.id===e.id){return t}t+=n.duration}return t},get _exportingOrRendering(){return e._exporting||e._rendering}})).views(e=>({get computedWidth(){return"auto"===e.width?e.store.width:e.width},get computedHeight(){return"auto"===e.height?e.store.height:e.height}})).actions(e=>({toJSON:()=>JSON.parse(JSON.stringify(n(e))),_forEachElementUp(t,n){const i=t.map(t=>({id:t,index:e.children.findIndex(e=>e.id===t)}));i.sort((e,t)=>t.index-e.index);for(const{index:o}of i){if(-1==o){continue}const i=o<e.children.length-1&&e.children[o+1],r=t.indexOf(null==i?void 0:i.id)>=0;o===e.children.length-1||r||n(o)}},_forEachElementDown(t,n){const i=t.map(t=>({id:t,index:e.children.findIndex(e=>e.id===t)}));i.sort((e,t)=>e.index-t.index);for(const{index:o}of i){if(-1==o){continue}const i=o>0&&e.children[o-1],r=t.indexOf(null==i?void 0:i.id)>=0;0===o||r||n(o)}return!1}})).actions(t=>({clone(e={}){const n=t.toJSON();n.children.forEach(e=>{e.id=o(10),d(e,e=>{e.id=o(10)})});const i=Object.assign(Object.assign(Object.assign({},n),{id:o(10)}),e),r=t.store.addPage(i),s=t.store.pages.indexOf(t);return r.setZIndex(s+1),r.select(),r},setZIndex(e){t.store.setPageZIndex(t.id,e)},set(e){Object.assign(t,e)},select(){t.store.selectPage(t.id)},addElement(e,{skipSelect:n=!1}={}){const i=s[e.type];if(!i){return void console.error("Can not find model with type "+e.type)}"children"in e&&Array.isArray(e.children)&&d(e,e=>{e.id=e.id||o(10)});const r=t.children.reduce((t,n)=>{if("group"===n.type){const i=n.children.reduce((t,n)=>{var i;const o=null===(i=n.name)||void 0===i?void 0:i.match(new RegExp(`${e.type}-(\\d+)`));if(o){const e=parseInt(o[1],10);return Math.max(t,e||0)}},0);return Math.max(t,i||0)}{const i=n.name.match(new RegExp(`${e.type}-(\\d+)`));if(i){const e=parseInt(i[1],10);return Math.max(t,e||0)}}return t},0),c=i.create(Object.assign({id:o(10),name:`${e.type}-${r+1}`},e));return t.children.push(c),c.selectable&&!n&&t.store.selectElements([c.id]),c},canMoveElementsUp(e){let n=!1;return t._forEachElementUp(e,()=>{n=n||!0}),n},moveElementsUp(n){t._forEachElementUp(n,n=>{const i=t.children[n];e(i),t.children.splice(n+1,0,i)})},canMoveElementsTop(e){return this.canMoveElementsUp(e)},moveElementsTop(e){const n=[],i=[];t.children.forEach(t=>{e.indexOf(t.id)>=0?n.push(t):i.push(t)}),t.children.replace(i.concat(n))},canMoveElementsDown(e){let n=!1;return t._forEachElementDown(e,()=>{n=n||!0}),n},moveElementsDown(n){t._forEachElementDown(n,n=>{const i=t.children[n];e(i),t.children.splice(n-1,0,i)})},canMoveElementsBottom(e){return this.canMoveElementsDown(e)},moveElementsBottom(e){const n=[],i=[];t.children.forEach(t=>{e.indexOf(t.id)>=0?n.push(t):i.push(t)}),t.children.replace(n.concat(i))},setElementZIndex(n,i){const o=t.children.find(e=>e.id===n);o&&(e(o),t.children.remove(o),t.children.splice(i,0,o))},setSize({width:e,height:n,useMagic:i,softChange:o}){if(i){const i=[],o=e=>"image"===e.type&&e.x<1&&e.y<1&&e.width>=t.computedWidth-2&&e.height>=t.computedHeight-2;d(t,e=>{"group"!==e.type&&(o(e)||i.push(e))});const r=i.length?a(i):{x:0,y:0,width:t.computedWidth,height:t.computedHeight},s=1/4,c=Math.max(0,Math.min(r.x,t.computedWidth-r.x-r.width)),h=t.computedWidth*s,m=Math.max(0,c-h),l=Math.max(0,Math.min(r.y,t.computedHeight-r.y-r.height)),p=t.computedHeight*s,u=Math.max(0,l-p),g=t.computedWidth-2*m,f=t.computedHeight-2*u,E=e/g,x=n/f,v=Math.min(E,x),w=(e-g*v)/2-m*v,y=(n-f*v)/2-u*v;d(t,e=>{"group"!==e.type&&(o(e)?e.set({x:e.x*v,y:e.y*v,width:e.width*E,height:e.height*x,cropX:0,cropY:0,cropWidth:1,cropHeight:1}):(e.set({x:w+e.x*v,y:y+e.y*v,width:e.width*v,height:e.height*v}),"text"===e.type?e.set({fontSize:e.fontSize*v}):"figure"===e.type&&e.set({strokeWidth:e.strokeWidth*v})))})}o||(t.width=e),o||(t.height=n)}})).actions(e=>({moveElementUp(t){console.warn("page.moveElementUp(id) is deprecated. Please use page.moveElementsUp([id1, id2]) instead."),e.moveElementsUp([t])},moveElementDown(t){console.warn("page.moveElementDown(id) is deprecated. Please use page.moveElementsDown([id1, id2]) instead."),e.moveElementsDown([t])},moveElementTop(t){console.warn("page.moveElementTop(id) is deprecated. Please use page.moveElementsTop([id1, id2]) instead."),e.moveElementsTop([t])},moveElementBottom(t){console.warn("page.moveElementBottom(id) is deprecated. Please use page.moveElementsBottom([id1, id2]) instead."),e.moveElementsBottom([t])},play(){e.store.play({startTime:e.startTime,endTime:e.startTime+e.duration})}}));
package/model/store.d.ts CHANGED
@@ -949,13 +949,14 @@ export declare const Store: import("mobx-state-tree").IModelType<{
949
949
  toHTML({ elementHook }?: {
950
950
  elementHook: any;
951
951
  }): Promise<string>;
952
- saveAsHTML({ fileName }?: {
952
+ saveAsHTML({ fileName, elementHook, }?: {
953
953
  fileName?: string;
954
+ elementHook?: Function;
954
955
  }): Promise<void>;
955
- toSVG({ elementHook, pageId, fontEmbedding }?: {
956
- elementHook: any;
957
- pageId: any;
958
- fontEmbedding?: string;
956
+ toSVG({ elementHook, pageId, fontEmbedding, }?: {
957
+ elementHook?: Function;
958
+ pageId?: string;
959
+ fontEmbedding?: "none" | "inline";
959
960
  }): Promise<string>;
960
961
  saveAsSVG({ fileName, elementHook, pageId, fontEmbedding, }?: {
961
962
  fileName?: string;
package/model/store.js CHANGED
@@ -1 +1 @@
1
- var e=this&&this.__rest||function(e,t){var i={};for(var o in e){Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(i[o]=e[o])}if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(e);n<o.length;n++){t.indexOf(o[n])<0&&Object.prototype.propertyIsEnumerable.call(e,o[n])&&(i[o[n]]=e[o[n]])}}return i};import{types as t,onSnapshot as i,applySnapshot as o,detach as n,getSnapshot as a,cast as s,destroy as r,setLivelinessChecking as l}from"mobx-state-tree";import{UndoManager as d}from"./history.js";import{nanoid as c}from"nanoid";import p from"konva";import{computed as g}from"mobx";import{downloadFile as m}from"../utils/download.js";import{getJsPDF as u}from"../utils/pdf.js";import{createGIF as f}from"../utils/gif-lib.js";import{validateKey as h}from"../utils/validate-key.js";import*as y from"../utils/fonts.js";import{flags as b}from"../utils/flags.js";import{whenLoaded as v}from"../utils/loader.js";import{pxToUnit as w}from"../utils/unit.js";import{deepEqual as P}from"../utils/deep-equal.js";import{waitTillAvailable as E}from"../utils/wait.js";import{jsonToHTML as x}from"../utils/to-html.js";import{jsonToSVG as _}from"../utils/to-svg.js";import{Page as I}from"./page-model.js";import{forEveryChild as k}from"./group-model.js";import{Audio as S}from"./audio-model.js";l("ignore");export const Font=t.model("Font",{fontFamily:t.string,url:t.optional(t.string,""),styles:t.frozen()}).preProcessSnapshot(e=>Object.assign(Object.assign({},e),{fontFamily:e.fontFamily||e.name}));export const Store=t.model("Store",{role:"",pages:t.array(I),fonts:t.array(Font),audios:t.array(S),width:1080,height:1080,currentTime:0,isPlaying:!1,scale:1,scaleToFit:1,unit:"px",dpi:72,schemaVersion:2,bleedVisible:!1,rulesVisible:!1,openedSidePanel:"",previousOpenedSidePanel:"",custom:t.frozen(),selectedElementsIds:t.array(t.string),animatedElementsIds:t.array(t.string),history:t.optional(d,{targetPath:"../pages"}),_elementsPixelRatio:Math.min(2,"undefined"!=typeof window&&window.devicePixelRatio||1),_activePageId:"",_selectedPagesIds:t.array(t.string),_forceShowCredit:!1,_key:"",_validated:!1}).views(e=>{const t=g(()=>{const t={};return k({children:e.pages},e=>(t[e.id]=e,!1)),t},{keepAlive:!0});return{get _idsMap(){return t.get()}}}).views(e=>({get _bleedVisible(){return console.warn("store._bleedVisible is deprecated. Please use store.bleedVisible instead."),e.bleedVisible},get selectedElements(){return e.selectedElementsIds.map(t=>{for(const i of e.pages){for(const e of i.children){if(e.id===t){return e}}}}).filter(e=>!!e)},get children(){return e.pages},get selectedShapes(){const t=[];return k({children:e.selectedElements},e=>{"group"!==e.type&&t.push(e)}),t},get activePage(){return e.pages.slice().find(t=>t.id===e._activePageId)||(e.pages.length?e.pages[0]:null)},get selectedPages(){return e._selectedPagesIds.map(t=>e.pages.find(e=>e.id===t))},get duration(){let t=0;return e.pages.forEach(e=>{t+=e.duration}),t},get _hasCroppedImages(){return e.find(e=>"image"===e.type&&e._cropModeEnabled)},find(t){let i;return k({children:e.pages},e=>{if(!i&&t(e)){return i=e,!0}}),i},getElementById:t=>e._idsMap[t]})).actions(e=>{let t=0,i=null,o=!1;return{afterCreate(){e.history.canUndo},setCurrentTime(t){e.currentTime=t},_togglePlaying(t=!e.isPlaying){e.isPlaying=t},play({animatedElementsIds:n=[],startTime:a=0,currentTime:r=0,endTime:l=e.duration,repeat:d=!1}={}){r&&(console.warn("currentTime property of store.play() is deprecated. Please use startTime instead."),a=r),e.animatedElementsIds=s(n),e.currentTime=a,e.isPlaying=!0,t=Date.now(),i=l,o=d,requestAnimationFrame(e.seek)},checkActivePage(){let t=0;for(const i of e.pages){if(e.currentTime>=i.startTime&&e.currentTime<i.startTime+i.duration){e.selectPage(i.id);break}t+=i.duration}},seek(){if(!e.isPlaying){return}const n=Date.now(),a=n-t;t=n,e.currentTime+=a,e.checkActivePage();const s=i||e.duration;e.isPlaying&&e.currentTime<s?requestAnimationFrame(e.seek):e.isPlaying&&o?(e.currentTime=0,requestAnimationFrame(e.seek)):e.stop()},stop(){e.isPlaying=!1,e.currentTime=0,e.animatedElementsIds=s([]),e.checkActivePage()}}}).actions(t=>({__(){t._validated||(h(t._key,t._forceShowCredit),t._validated=!0)},set(e){Object.assign(t,e)},setUnit({unit:e,dpi:i}){t.unit=e||t.unit,t.dpi=i||t.dpi},setRole(e){t.role=e},addPage(e){const i=I.create(Object.assign({id:c(10)},e));return t.pages.push(i),t._activePageId=i.id,i},selectPage(e){t._activePageId=e,1===t._selectedPagesIds.length&&(t._selectedPagesIds=s([e]))},selectPages(e){t._selectedPagesIds=s(e),1===t._selectedPagesIds.length&&(t._activePageId=t._selectedPagesIds[0])},selectElements(e){const i=e.map(e=>t.getElementById(e)).sort((e,t)=>e.page.children.indexOf(e)-e.page.children.indexOf(t)).filter(e=>!!e).map(e=>e.id);t.selectedElementsIds=s(i)},toggleBleed(e){t.bleedVisible=null!=e?e:!t.bleedVisible},toggleRulers(e){t.rulesVisible=null!=e?e:!t.rulesVisible},openSidePanel(e){t.openedSidePanel!==e&&(t.previousOpenedSidePanel=t.openedSidePanel,t.openedSidePanel=e)},setScale(e){t.scale=e},_setScaleToFit(e){t.scaleToFit=e},setElementsPixelRatio(e){t._elementsPixelRatio=e},setSize(e,i,o){t.pages.forEach(t=>{t.setSize({width:e,height:i,useMagic:o,softChange:!0})}),t.width=e,t.height=i},setPageZIndex(e,i){const o=t.pages.find(t=>t.id===e);o&&(n(o),t.pages.remove(o),t.pages.splice(i,0,o))},deletePages(e){const i=t.pages.indexOf(t.activePage);e.forEach(e=>{const i=t.pages.find(t=>t.id===e);r(i)});const o=Math.min(t.pages.length-1,i),n=t.pages[o];n&&(t._activePageId=n.id),t.selectedElementsIds=s(t.selectedElementsIds.filter(e=>t.getElementById(e)))},groupElements(e,i={}){const o=e.map(e=>t.getElementById(e)),a=o[0].page;if(o.forEach(e=>{e&&n(e)}),!o.length){return}const r=Object.assign({id:c(10),children:o,type:"group"},i);return a.children.push(r),t.selectedElementsIds=s([r.id]),a.children.find(e=>e.id===r.id)},ungroupElements(e){const i=e.map(e=>t.getElementById(e)),o=[];i.forEach(e=>{if(e&&"group"===e.type){const t=e.page,i=t.children.indexOf(e);e.children.forEach(e=>{o.push(e.id)}),e.children.forEach(e=>{n(e),t.children.push(e)}),t.children.splice(i,1)}}),t.selectedElementsIds=s(o)},deleteElements(e){const i=[];t.find(t=>(e.includes(t.id)&&i.push(t),!1)),i.forEach(e=>{r(e)}),t.selectedElementsIds=s(t.selectedElementsIds.filter(e=>t.getElementById(e)))},on(e,o){if("change"===e){let e=t.toJSON();return i(t,i=>{const n=t.toJSON();!P(e,n)&&(e=n,o(n))})}},async _toCanvas({pixelRatio:e,ignoreBackground:i,pageId:o,mimeType:n,includeBleed:a,_skipTimeout:s,quickMode:r=!1}={}){var l;const d=e||1;o=o||(null===(l=t.pages[0])||void 0===l?void 0:l.id);const c=t.pages.find(e=>e.id===o);if(!c){throw new Error(`No page for export with id ${o}`)}const g=t._elementsPixelRatio;d>t._elementsPixelRatio&&t.setElementsPixelRatio(d),r?null==c||c.set({_forceMount:!0}):null==c||c.set({_exporting:!0});const m=await E(()=>{const e=p.stages.filter(e=>e.getAttr("pageId")===o);return 0===e.length?null:e});if(!m){throw null==c||c.set({_forceMount:!1,_exporting:!1}),t.setElementsPixelRatio(g),new Error(`Export is failed. Can not find stage for page ${o}. Looks like <Workspace /> component is not mounted, but it is required in order to process the export.`)}m.length>1&&console.error(`Polotno error: Detected several canvas elements for page "${o}" in the document. This is not supported and will lead to incorrect export. Make sure to use unique ids for all pages and make sure you unmount <Workspace /> when it is not needed.`);const u=m[0];await t.waitLoading({_skipTimeout:s});const f=u.findOne(".page-container");if(!f){throw t.setElementsPixelRatio(g),null==c||c.set({_forceMount:!1,_exporting:!1}),new Error("Export is failed. Canvas was unmounted.")}const h=u.position();u.position({x:0,y:0}),u.find("Transformer").forEach(e=>{e.setAttr("oldVisible",e.visible()),e.visible(!1)}),f.find(".page-background").forEach(e=>e.shadowEnabled(!1)),f.find(".page-background").forEach(e=>e.strokeEnabled(!1)),f.find(".highlighter").forEach(e=>e.visible(!1));const y=f.findOne(".page-background-group"),b=y.clip();y.clip({x:null,y:null,width:null,height:null});const v=f.findOne(".elements-container"),w=v.clip();v.clip({x:null,y:null,width:null,height:null});const P=f.find(e=>!e.visible()&&e.getAttr("editModeEnabled")&&!e.getAttr("hideInExport"));P.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.show()});const x=f.find(e=>e.getAttr("hideInExport"));x.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.hide()}),i&&f.find(".page-background").forEach(e=>e.hide());const _=a?c.bleed:0;let I=_;!t.bleedVisible&&a||(t.bleedVisible||a?t.bleedVisible&&a?I=0:t.bleedVisible&&!a&&(I=-c.bleed):I=0);const k=document.createElement("canvas");k.width=Math.round((c.computedWidth+2*_)*d),k.height=Math.round((c.computedHeight+2*_)*d);const S=k.getContext("2d");"image/jpeg"===n&&(S.fillStyle="white",S.fillRect(0,0,k.width,k.height));const O=f.scale();f.scale({x:1,y:1});const j=f.toCanvas({x:f.x()-I,y:f.y()-I,width:c.computedWidth+2*_,height:c.computedHeight+2*_,pixelRatio:d});return f.scale(O),S.drawImage(j,0,0,k.width,k.height),p.Util.releaseCanvas(j),i&&f.find(".page-background").forEach(e=>e.show()),x.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),P.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),f.find(".page-background").forEach(e=>e.shadowEnabled(!0)),f.find(".page-background").forEach(e=>e.strokeEnabled(!0)),u.find("Transformer").forEach(e=>{e.visible(e.getAttr("oldVisible"))}),f.find(".highlighter").forEach(e=>e.visible(!0)),y.clip(b),v.clip(w),u.position(h),null==c||c.set({_exporting:!1,_forceMount:!1}),await new Promise(e=>setTimeout(e)),t.setElementsPixelRatio(g),k},async toDataURL(i={}){var{mimeType:o,quality:n}=i,a=e(i,["mimeType","quality"]);const s=await t._toCanvas(Object.assign({mimeType:o},a)),r=s.toDataURL(o,n);return p.Util.releaseCanvas(s),r},async toBlob(i={}){var{mimeType:o,quality:n}=i,a=e(i,["mimeType","quality"]);const s=await t._toCanvas(Object.assign({mimeType:o},a)),r=await new Promise(e=>{s.toBlob(e,o,n)});return p.Util.releaseCanvas(s),r},async saveAsImage(i={}){var{fileName:o}=i,n=e(i,["fileName"]);const a=n.mimeType||"image/png",s=a.split("/")[1];m(await t.toDataURL(n),o||"polotno."+s,a)},async _toPDF(e){const i=e.dpi||t.dpi,o=e.parallel||1,n=e.unit||("px"===t.unit?"mm":t.unit),a=e.pixelRatio||1,s=e.pageIds||t.pages.map(e=>e.id),r=t.pages.filter(e=>s.includes(e.id)),l=await u(),d=e=>w({px:e,unit:n,dpi:i}),c=e.cropMarkSize||0,p=d(c),g=r[0]||{},m=e.includeBleed?g.bleed:0,f=d(g.computedWidth+2*m+2*p),h=d(g.computedHeight+2*m+2*p);var y=new l({unit:n,orientation:f>h?"landscape":"portrait",format:[f,h],compress:!0,putOnlyUsedFonts:!0});y.deletePage(1);const b=((e,t)=>{for(var i=[],o=0;o<e.length;o+=t){i.push(e.slice(o,o+t))}return i})(r,o);let v=0;for(const u of b){const i=u.map(async i=>{const o=e.includeBleed?i.bleed:0,n=i.computedWidth+2*o+2*c,r=i.computedHeight+2*o+2*c,l=d(n),p=d(r);let g=0,m=a;for(;g<10;){g+=1,2===g&&console.error("Polotno can not export PDF with current settings. Quality is automatically reduced.");const o=await t.toDataURL(Object.assign(Object.assign({},e),{pageId:i.id,pixelRatio:m}));if(o.length>20){return e.onProgress&&e.onProgress(++v/s.length*.9),{url:o,width:l,height:p,widthPx:n,heightPx:r}}m*=.8}});(await Promise.all(i)).forEach(({url:e,width:t,height:i,widthPx:o,heightPx:a})=>{y.addPage([t,i],t>i?"landscape":"portrait");const s=y.getCurrentPageInfo();var r;switch(n){case"pt":r=1;break;case"mm":r=72/25.4;break;case"cm":r=72/2.54;break;case"in":r=72;break;case"px":r=.75;break;case"pc":case"em":r=12;break;case"ex":r=6;break;default:throw"Invalid unit: "+n}if(s.pageContext.cropBox={bottomLeftX:0,bottomLeftY:0,topRightX:t*r,topRightY:i*r},s.pageContext.artBox={bottomLeftX:d(c+m)*r,bottomLeftY:d(c+m)*r,topRightX:d(o-c-m)*r,topRightY:d(a-c-m)*r},s.pageContext.bleedBox={bottomLeftX:d(c+m)*r,bottomLeftY:d(c+m)*r,topRightX:d(o-c-m)*r,topRightY:d(a-c-m)*r},p){y.setLineWidth(d(1));const e=p+d(m);y.line(e,0,e,p),y.line(0,e,p,e),y.line(t-e,0,t-e,p),y.line(t,e,t-p,e),y.line(0,i-e,p,i-e),y.line(e,i,e,i-p),y.line(t,i-e,t-p,i-e),y.line(t-e,i,t-e,i-p)}y.addImage(e,p,p,t-2*p,i-2*p,void 0,"FAST")})}return y},toPDFDataURL:async e=>(await t._toPDF(Object.assign({mimeType:"image/jpeg"},e))).output("datauristring"),async toGIFDataURL(e={}){const i=e.pixelRatio||1,o=await f({width:t.width*i,height:t.height*i}),n=1e3/(e.fps||10),a=t.duration/n;for(let s=0;s<a-1;s++){const e=s*n||1;t.setCurrentTime(e);let a=0,r="";for(const i of t.pages){if(a+=i.duration,i.set({_rendering:a>e}),a>e){r=i.id;break}}const l=await t._toCanvas({pixelRatio:i,pageId:r,_skipTimeout:!0});o.addFrame(l.getContext("2d"),{delay:n,copy:!0})}for(const s of t.pages){s.set({_rendering:!1})}return t.stop(),o.render(),new Promise(e=>{o.on("finished",function(t){!function(e,t){var i=new FileReader;i.onload=function(e){t(e.target.result)},i.readAsDataURL(e)}(t,e)})})},async saveAsGIF(i={}){var{fileName:o}=i,n=e(i,["fileName"]);const a=await t.toGIFDataURL(n);m(a,o||"polotno.gif")},async toHTML({elementHook:e}={elementHook:void 0}){const i=t.toJSON();return x({json:i,elementHook:e})},async saveAsHTML({fileName:e}={}){const i=await t.toHTML(),o="data:text/html;base64,"+window.btoa(unescape(encodeURIComponent(i)));m(o,e||"polotno.html")},async toSVG({elementHook:e,pageId:i,fontEmbedding:o="inline"}={elementHook:void 0,pageId:void 0,fontEmbedding:"inline"}){var n;const a=t.toJSON();i=i||(null===(n=a.pages[0])||void 0===n?void 0:n.id);const s=a.pages.find(e=>e.id===i);return _({json:Object.assign(Object.assign({},a),{pages:s?[s]:[]}),elementHook:e,fontEmbedding:o})},async saveAsSVG({fileName:e,elementHook:i,pageId:o,fontEmbedding:n="inline"}={}){const a=await t.toSVG({elementHook:i,pageId:o,fontEmbedding:n}),s="data:text/svg;base64,"+window.btoa(unescape(encodeURIComponent(a)));m(s,e||"polotno.svg")},async saveAsPDF(i={}){var{fileName:o}=i,n=e(i,["fileName"]);(await t._toPDF(Object.assign({mimeType:"image/jpeg"},n))).save(o||"polotno.pdf")},async waitLoading({_skipTimeout:e=!1}={}){e||await new Promise(e=>setTimeout(e,50)),await v()},toJSON:()=>({width:t.width,height:t.height,fonts:a(t.fonts),pages:a(t.pages),audios:a(t.audios),unit:t.unit,dpi:t.dpi,custom:t.custom,schemaVersion:t.schemaVersion}),loadJSON(e,i=!1){var n;const s=JSON.parse(JSON.stringify(e)),r=s.schemaVersion||0;r<1&&b.htmlRenderEnabled&&k({children:s.pages},e=>{if("text"===e.type){const t=16,i=e.letterSpacing*t;e.letterSpacing=i/e.fontSize}}),r<2&&k({children:s.pages},e=>{e.filters&&Object.keys(e.filters).forEach(t=>{if(["warm","cold","natural"].includes(t)){return}const i=e.filters[t];i&&"number"==typeof i.intensity&&(i.intensity=i.intensity/100)})}),delete s.schemaVersion;const l=t.pages.indexOf(t.activePage);let d=null===(n=s.pages[l]||s.pages[0])||void 0===n?void 0:n.id;s._activePageId=d;const c=Object.assign({},a(t));Object.assign(c,s),c.history=i?t.history.toJSON():{history:[],undoIdx:-1},o(t,c)},clear({keepHistory:e=!1}={}){const i=t.pages.map(e=>e.id);t.deletePages(i),t.custom=null,e||t.history.clear()},addFont(e){t.removeFont(e.fontFamily),t.fonts.push(e),t.loadFont(e.fontFamily)},removeFont(e){t.fonts.filter(t=>t.fontFamily===e).forEach(e=>r(e))},addAudio(e){const i=S.create(Object.assign({id:c(10)},e));t.audios.push(i)},removeAudio(e){const i=t.audios.find(t=>t.id===e);i&&t.audios.remove(i)},async loadFont(e){const i=t.fonts.find(t=>t.fontFamily===e)||y.globalFonts.find(t=>t.fontFamily===e);let o=[{fontStyle:"normal",fontWeight:"normal"},{fontStyle:"normal",fontWeight:"bold"}];return i?(i.styles&&(o=i.styles.map(e=>({fontStyle:e.fontStyle||"normal",fontWeight:e.fontWeight||"normal"}))),y.injectCustomFont(i)):y.injectGoogleFont(e),Promise.all(o.map(t=>y.loadFont(e,t.fontStyle,t.fontWeight)))},validate:e=>Store.validate(e,[{path:"",type:Store}]).map(e=>({path:"store"+e.context.map(e=>e.path).join("."),message:e.message}))}));export function createStore({key:e,showCredit:t}={key:"",showCredit:!1}){return Store.create({_forceShowCredit:t,_key:e})}export default createStore;
1
+ var e=this&&this.__rest||function(e,t){var i={};for(var o in e){Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(i[o]=e[o])}if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(e);n<o.length;n++){t.indexOf(o[n])<0&&Object.prototype.propertyIsEnumerable.call(e,o[n])&&(i[o[n]]=e[o[n]])}}return i};import{applySnapshot as t,cast as i,destroy as o,detach as n,getSnapshot as a,onSnapshot as s,setLivelinessChecking as r,types as l}from"mobx-state-tree";import{UndoManager as d}from"./history.js";import{nanoid as c}from"nanoid";import p from"konva";import{computed as g}from"mobx";import{downloadFile as m}from"../utils/download.js";import{getJsPDF as u}from"../utils/pdf.js";import{createGIF as f}from"../utils/gif-lib.js";import{validateKey as h}from"../utils/validate-key.js";import*as y from"../utils/fonts.js";import{flags as b}from"../utils/flags.js";import{whenLoaded as w}from"../utils/loader.js";import{pxToUnit as v}from"../utils/unit.js";import{deepEqual as P}from"../utils/deep-equal.js";import{waitTillAvailable as E}from"../utils/wait.js";import{jsonToHTML as x}from"../utils/to-html.js";import{jsonToSVG as _}from"../utils/to-svg.js";import{Page as I}from"./page-model.js";import{forEveryChild as k}from"./group-model.js";import{Audio as S}from"./audio-model.js";r("ignore");export const Font=l.model("Font",{fontFamily:l.string,url:l.optional(l.string,""),styles:l.frozen()}).preProcessSnapshot(e=>Object.assign(Object.assign({},e),{fontFamily:e.fontFamily||e.name}));export const Store=l.model("Store",{role:"",pages:l.array(I),fonts:l.array(Font),audios:l.array(S),width:1080,height:1080,currentTime:0,isPlaying:!1,scale:1,scaleToFit:1,unit:"px",dpi:72,schemaVersion:2,bleedVisible:!1,rulesVisible:!1,openedSidePanel:"",previousOpenedSidePanel:"",custom:l.frozen(),selectedElementsIds:l.array(l.string),animatedElementsIds:l.array(l.string),history:l.optional(d,{targetPath:"../pages"}),_elementsPixelRatio:Math.min(2,"undefined"!=typeof window&&window.devicePixelRatio||1),_activePageId:"",_selectedPagesIds:l.array(l.string),_forceShowCredit:!1,_key:"",_validated:!1}).views(e=>{const t=g(()=>{const t={};return k({children:e.pages},e=>(t[e.id]=e,!1)),t},{keepAlive:!0});return{get _idsMap(){return t.get()}}}).views(e=>({get _bleedVisible(){return console.warn("store._bleedVisible is deprecated. Please use store.bleedVisible instead."),e.bleedVisible},get selectedElements(){return e.selectedElementsIds.map(t=>{for(const i of e.pages){for(const e of i.children){if(e.id===t){return e}}}}).filter(e=>!!e)},get children(){return e.pages},get selectedShapes(){const t=[];return k({children:e.selectedElements},e=>{"group"!==e.type&&t.push(e)}),t},get activePage(){return e.pages.slice().find(t=>t.id===e._activePageId)||(e.pages.length?e.pages[0]:null)},get selectedPages(){return e._selectedPagesIds.map(t=>e.pages.find(e=>e.id===t))},get duration(){let t=0;return e.pages.forEach(e=>{t+=e.duration}),t},get _hasCroppedImages(){return e.find(e=>"image"===e.type&&e._cropModeEnabled)},find(t){let i;return k({children:e.pages},e=>{if(!i&&t(e)){return i=e,!0}}),i},getElementById:t=>e._idsMap[t]})).actions(e=>{let t=0,o=null,n=!1;return{afterCreate(){e.history.canUndo},setCurrentTime(t){e.currentTime=t},_togglePlaying(t=!e.isPlaying){e.isPlaying=t},play({animatedElementsIds:a=[],startTime:s=0,currentTime:r=0,endTime:l=e.duration,repeat:d=!1}={}){r&&(console.warn("currentTime property of store.play() is deprecated. Please use startTime instead."),s=r),e.animatedElementsIds=i(a),e.currentTime=s,e.isPlaying=!0,t=Date.now(),o=l,n=d,requestAnimationFrame(e.seek)},checkActivePage(){let t=0;for(const i of e.pages){if(e.currentTime>=i.startTime&&e.currentTime<i.startTime+i.duration){e.selectPage(i.id);break}t+=i.duration}},seek(){if(!e.isPlaying){return}const i=Date.now(),a=i-t;t=i,e.currentTime+=a,e.checkActivePage();const s=o||e.duration;e.isPlaying&&e.currentTime<s?requestAnimationFrame(e.seek):e.isPlaying&&n?(e.currentTime=0,requestAnimationFrame(e.seek)):e.stop()},stop(){e.isPlaying=!1,e.currentTime=0,e.animatedElementsIds=i([]),e.checkActivePage()}}}).actions(r=>({__(){r._validated||(h(r._key,r._forceShowCredit),r._validated=!0)},set(e){Object.assign(r,e)},setUnit({unit:e,dpi:t}){r.unit=e||r.unit,r.dpi=t||r.dpi},setRole(e){r.role=e},addPage(e){const t=I.create(Object.assign({id:c(10)},e));return r.pages.push(t),r._activePageId=t.id,t},selectPage(e){r._activePageId=e,1===r._selectedPagesIds.length&&(r._selectedPagesIds=i([e]))},selectPages(e){r._selectedPagesIds=i(e),1===r._selectedPagesIds.length&&(r._activePageId=r._selectedPagesIds[0])},selectElements(e){const t=e.map(e=>r.getElementById(e)).sort((e,t)=>e.page.children.indexOf(e)-e.page.children.indexOf(t)).filter(e=>!!e).map(e=>e.id);r.selectedElementsIds=i(t)},toggleBleed(e){r.bleedVisible=null!=e?e:!r.bleedVisible},toggleRulers(e){r.rulesVisible=null!=e?e:!r.rulesVisible},openSidePanel(e){r.openedSidePanel!==e&&(r.previousOpenedSidePanel=r.openedSidePanel,r.openedSidePanel=e)},setScale(e){r.scale=e},_setScaleToFit(e){r.scaleToFit=e},setElementsPixelRatio(e){r._elementsPixelRatio=e},setSize(e,t,i){r.pages.forEach(o=>{o.setSize({width:e,height:t,useMagic:i,softChange:!0})}),r.width=e,r.height=t},setPageZIndex(e,t){const i=r.pages.find(t=>t.id===e);i&&(n(i),r.pages.remove(i),r.pages.splice(t,0,i))},deletePages(e){const t=r.pages.indexOf(r.activePage);e.forEach(e=>{const t=r.pages.find(t=>t.id===e);o(t)});const n=Math.min(r.pages.length-1,t),a=r.pages[n];a&&(r._activePageId=a.id),r.selectedElementsIds=i(r.selectedElementsIds.filter(e=>r.getElementById(e)))},groupElements(e,t={}){const o=e.map(e=>r.getElementById(e)),a=o[0].page;if(o.forEach(e=>{e&&n(e)}),!o.length){return}const s=a.children.reduce((e,t)=>{if("group"===t.type){const i=t.name.match(/group-(\d+)/);if(i){const t=parseInt(i[1],10);return Math.max(e,t)}}return e},0),l=Object.assign({id:c(10),name:`group-${s+1}`,children:o,type:"group"},t);return a.children.push(l),r.selectedElementsIds=i([l.id]),a.children.find(e=>e.id===l.id)},ungroupElements(e){const t=e.map(e=>r.getElementById(e)),o=[];t.forEach(e=>{if(e&&"group"===e.type){const t=e.page,i=t.children.indexOf(e);e.children.forEach(e=>{o.push(e.id)}),e.children.forEach(e=>{n(e),t.children.push(e)}),t.children.splice(i,1)}}),r.selectedElementsIds=i(o)},deleteElements(e){const t=[];r.find(i=>(e.includes(i.id)&&t.push(i),!1)),t.forEach(e=>{o(e)}),r.selectedElementsIds=i(r.selectedElementsIds.filter(e=>r.getElementById(e)))},on(e,t){if("change"===e){let e=r.toJSON();return s(r,i=>{const o=r.toJSON();!P(e,o)&&(e=o,t(o))})}},async _toCanvas({pixelRatio:e,ignoreBackground:t,pageId:i,mimeType:o,includeBleed:n,_skipTimeout:a,quickMode:s=!1}={}){var l;const d=e||1;i=i||(null===(l=r.pages[0])||void 0===l?void 0:l.id);const c=r.pages.find(e=>e.id===i);if(!c){throw new Error(`No page for export with id ${i}`)}const g=r._elementsPixelRatio;d>r._elementsPixelRatio&&r.setElementsPixelRatio(d),s?null==c||c.set({_forceMount:!0}):null==c||c.set({_exporting:!0});const m=await E(()=>{const e=p.stages.filter(e=>e.getAttr("pageId")===i);return 0===e.length?null:e});if(!m){throw null==c||c.set({_forceMount:!1,_exporting:!1}),r.setElementsPixelRatio(g),new Error(`Export is failed. Can not find stage for page ${i}. Looks like <Workspace /> component is not mounted, but it is required in order to process the export.`)}m.length>1&&console.error(`Polotno error: Detected several canvas elements for page "${i}" in the document. This is not supported and will lead to incorrect export. Make sure to use unique ids for all pages and make sure you unmount <Workspace /> when it is not needed.`);const u=m[0];await r.waitLoading({_skipTimeout:a});const f=u.findOne(".page-container");if(!f){throw r.setElementsPixelRatio(g),null==c||c.set({_forceMount:!1,_exporting:!1}),new Error("Export is failed. Canvas was unmounted.")}const h=u.position();u.position({x:0,y:0}),u.find("Transformer").forEach(e=>{e.setAttr("oldVisible",e.visible()),e.visible(!1)}),f.find(".page-background").forEach(e=>e.shadowEnabled(!1)),f.find(".page-background").forEach(e=>e.strokeEnabled(!1)),f.find(".highlighter").forEach(e=>e.visible(!1));const y=f.findOne(".page-background-group"),b=y.clip();y.clip({x:null,y:null,width:null,height:null});const w=f.findOne(".elements-container"),v=w.clip();w.clip({x:null,y:null,width:null,height:null});const P=f.find(e=>!e.visible()&&e.getAttr("editModeEnabled")&&!e.getAttr("hideInExport"));P.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.show()});const x=f.find(e=>e.getAttr("hideInExport"));x.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.hide()}),t&&f.find(".page-background").forEach(e=>e.hide());const _=n?c.bleed:0;let I=_;!r.bleedVisible&&n||(r.bleedVisible||n?r.bleedVisible&&n?I=0:r.bleedVisible&&!n&&(I=-c.bleed):I=0);const k=document.createElement("canvas");k.width=Math.round((c.computedWidth+2*_)*d),k.height=Math.round((c.computedHeight+2*_)*d);const S=k.getContext("2d");"image/jpeg"===o&&(S.fillStyle="white",S.fillRect(0,0,k.width,k.height));const O=f.scale();f.scale({x:1,y:1});const j=f.toCanvas({x:f.x()-I,y:f.y()-I,width:c.computedWidth+2*_,height:c.computedHeight+2*_,pixelRatio:d});return f.scale(O),S.drawImage(j,0,0,k.width,k.height),p.Util.releaseCanvas(j),t&&f.find(".page-background").forEach(e=>e.show()),x.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),P.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),f.find(".page-background").forEach(e=>e.shadowEnabled(!0)),f.find(".page-background").forEach(e=>e.strokeEnabled(!0)),u.find("Transformer").forEach(e=>{e.visible(e.getAttr("oldVisible"))}),f.find(".highlighter").forEach(e=>e.visible(!0)),y.clip(b),w.clip(v),u.position(h),null==c||c.set({_exporting:!1,_forceMount:!1}),await new Promise(e=>setTimeout(e)),r.setElementsPixelRatio(g),k},async toDataURL(t={}){var{mimeType:i,quality:o}=t,n=e(t,["mimeType","quality"]);const a=await r._toCanvas(Object.assign({mimeType:i},n)),s=a.toDataURL(i,o);return p.Util.releaseCanvas(a),s},async toBlob(t={}){var{mimeType:i,quality:o}=t,n=e(t,["mimeType","quality"]);const a=await r._toCanvas(Object.assign({mimeType:i},n)),s=await new Promise(e=>{a.toBlob(e,i,o)});return p.Util.releaseCanvas(a),s},async saveAsImage(t={}){var{fileName:i}=t,o=e(t,["fileName"]);const n=o.mimeType||"image/png",a=n.split("/")[1];m(await r.toDataURL(o),i||"polotno."+a,n)},async _toPDF(e){const t=e.dpi||r.dpi,i=e.parallel||1,o=e.unit||("px"===r.unit?"mm":r.unit),n=e.pixelRatio||1,a=e.pageIds||r.pages.map(e=>e.id),s=r.pages.filter(e=>a.includes(e.id)),l=await u(),d=e=>v({px:e,unit:o,dpi:t}),c=e.cropMarkSize||0,p=d(c),g=s[0]||{},m=e.includeBleed?g.bleed:0,f=d(g.computedWidth+2*m+2*p),h=d(g.computedHeight+2*m+2*p);var y=new l({unit:o,orientation:f>h?"landscape":"portrait",format:[f,h],compress:!0,putOnlyUsedFonts:!0});y.deletePage(1);const b=((e,t)=>{for(var i=[],o=0;o<e.length;o+=t){i.push(e.slice(o,o+t))}return i})(s,i);let w=0;for(const u of b){const t=u.map(async t=>{const i=e.includeBleed?t.bleed:0,o=t.computedWidth+2*i+2*c,s=t.computedHeight+2*i+2*c,l=d(o),p=d(s);let g=0,m=n;for(;g<10;){g+=1,2===g&&console.error("Polotno can not export PDF with current settings. Quality is automatically reduced.");const i=await r.toDataURL(Object.assign(Object.assign({},e),{pageId:t.id,pixelRatio:m}));if(i.length>20){return e.onProgress&&e.onProgress(++w/a.length*.9),{url:i,width:l,height:p,widthPx:o,heightPx:s}}m*=.8}});(await Promise.all(t)).forEach(({url:e,width:t,height:i,widthPx:n,heightPx:a})=>{y.addPage([t,i],t>i?"landscape":"portrait");const s=y.getCurrentPageInfo();var r;switch(o){case"pt":r=1;break;case"mm":r=72/25.4;break;case"cm":r=72/2.54;break;case"in":r=72;break;case"px":r=.75;break;case"pc":case"em":r=12;break;case"ex":r=6;break;default:throw"Invalid unit: "+o}if(s.pageContext.cropBox={bottomLeftX:0,bottomLeftY:0,topRightX:t*r,topRightY:i*r},s.pageContext.artBox={bottomLeftX:d(c+m)*r,bottomLeftY:d(c+m)*r,topRightX:d(n-c-m)*r,topRightY:d(a-c-m)*r},s.pageContext.bleedBox={bottomLeftX:d(c+m)*r,bottomLeftY:d(c+m)*r,topRightX:d(n-c-m)*r,topRightY:d(a-c-m)*r},p){y.setLineWidth(d(1));const e=p+d(m);y.line(e,0,e,p),y.line(0,e,p,e),y.line(t-e,0,t-e,p),y.line(t,e,t-p,e),y.line(0,i-e,p,i-e),y.line(e,i,e,i-p),y.line(t,i-e,t-p,i-e),y.line(t-e,i,t-e,i-p)}y.addImage(e,p,p,t-2*p,i-2*p,void 0,"FAST")})}return y},toPDFDataURL:async e=>(await r._toPDF(Object.assign({mimeType:"image/jpeg"},e))).output("datauristring"),async toGIFDataURL(e={}){const t=e.pixelRatio||1,i=await f({width:r.width*t,height:r.height*t}),o=1e3/(e.fps||10),n=r.duration/o;for(let a=0;a<n-1;a++){const e=a*o||1;r.setCurrentTime(e);let n=0,s="";for(const t of r.pages){if(n+=t.duration,t.set({_rendering:n>e}),n>e){s=t.id;break}}const l=await r._toCanvas({pixelRatio:t,pageId:s,_skipTimeout:!0});i.addFrame(l.getContext("2d"),{delay:o,copy:!0})}for(const a of r.pages){a.set({_rendering:!1})}return r.stop(),i.render(),new Promise(e=>{i.on("finished",function(t){!function(e,t){var i=new FileReader;i.onload=function(e){t(e.target.result)},i.readAsDataURL(e)}(t,e)})})},async saveAsGIF(t={}){var{fileName:i}=t,o=e(t,["fileName"]);const n=await r.toGIFDataURL(o);m(n,i||"polotno.gif")},async toHTML({elementHook:e}={elementHook:void 0}){const t=r.toJSON();return x({json:t,elementHook:e})},async saveAsHTML({fileName:e,elementHook:t}={}){const i=await r.toHTML({elementHook:t}),o="data:text/html;base64,"+window.btoa(unescape(encodeURIComponent(i)));m(o,e||"polotno.html")},async toSVG({elementHook:e,pageId:t,fontEmbedding:i="inline"}={fontEmbedding:"inline"}){var o;const n=r.toJSON();t=t||(null===(o=n.pages[0])||void 0===o?void 0:o.id);const a=n.pages.find(e=>e.id===t);return _({json:Object.assign(Object.assign({},n),{pages:a?[a]:[]}),elementHook:e,fontEmbedding:i})},async saveAsSVG({fileName:e,elementHook:t,pageId:i,fontEmbedding:o="inline"}={}){const n=await r.toSVG({elementHook:t,pageId:i,fontEmbedding:o}),a="data:text/svg;base64,"+window.btoa(unescape(encodeURIComponent(n)));m(a,e||"polotno.svg")},async saveAsPDF(t={}){var{fileName:i}=t,o=e(t,["fileName"]);(await r._toPDF(Object.assign({mimeType:"image/jpeg"},o))).save(i||"polotno.pdf")},async waitLoading({_skipTimeout:e=!1}={}){e||await new Promise(e=>setTimeout(e,50)),await w()},toJSON:()=>({width:r.width,height:r.height,fonts:a(r.fonts),pages:a(r.pages),audios:a(r.audios),unit:r.unit,dpi:r.dpi,custom:r.custom,schemaVersion:r.schemaVersion}),loadJSON(e,i=!1){var o;const n=JSON.parse(JSON.stringify(e)),s=n.schemaVersion||0;s<1&&b.htmlRenderEnabled&&k({children:n.pages},e=>{if("text"===e.type){const t=16,i=e.letterSpacing*t;e.letterSpacing=i/e.fontSize}}),s<2&&k({children:n.pages},e=>{e.filters&&Object.keys(e.filters).forEach(t=>{if(["warm","cold","natural"].includes(t)){return}const i=e.filters[t];i&&"number"==typeof i.intensity&&(i.intensity=i.intensity/100)})}),delete n.schemaVersion;const l=r.pages.indexOf(r.activePage);let d=null===(o=n.pages[l]||n.pages[0])||void 0===o?void 0:o.id;n._activePageId=d;const c=Object.assign({},a(r));Object.assign(c,n),c.history=i?r.history.toJSON():{history:[],undoIdx:-1},t(r,c)},clear({keepHistory:e=!1}={}){const t=r.pages.map(e=>e.id);r.deletePages(t),r.custom=null,e||r.history.clear()},addFont(e){r.removeFont(e.fontFamily),r.fonts.push(e),r.loadFont(e.fontFamily)},removeFont(e){r.fonts.filter(t=>t.fontFamily===e).forEach(e=>o(e))},addAudio(e){const t=S.create(Object.assign({id:c(10)},e));r.audios.push(t)},removeAudio(e){const t=r.audios.find(t=>t.id===e);t&&r.audios.remove(t)},async loadFont(e){const t=r.fonts.find(t=>t.fontFamily===e)||y.globalFonts.find(t=>t.fontFamily===e);let i=[{fontStyle:"normal",fontWeight:"normal"},{fontStyle:"normal",fontWeight:"bold"}];return t?(t.styles&&(i=t.styles.map(e=>({fontStyle:e.fontStyle||"normal",fontWeight:e.fontWeight||"normal"}))),y.injectCustomFont(t)):y.injectGoogleFont(e),Promise.all(i.map(t=>y.loadFont(e,t.fontStyle,t.fontWeight)))},validate:e=>Store.validate(e,[{path:"",type:Store}]).map(e=>({path:"store"+e.context.map(e=>e.path).join("."),message:e.message}))}));export function createStore({key:e,showCredit:t}={key:"",showCredit:!1}){return Store.create({_forceShowCredit:t,_key:e})}export default createStore;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polotno",
3
- "version": "2.28.3",
3
+ "version": "2.29.1",
4
4
  "description": "Design Editor Framework",
5
5
  "author": "Anton Lavrenov",
6
6
  "keywords": [
@@ -58,6 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@blueprintjs/core": "5.19.0",
61
+ "@blueprintjs/icons": "^5.23.0",
61
62
  "@blueprintjs/select": "5.3.20",
62
63
  "@meronex/icons": "^4.0.0",
63
64
  "cssom": "^0.5.0",
@@ -114,6 +115,7 @@
114
115
  "devDependencies": {
115
116
  "@canvas/image": "^2.0.0",
116
117
  "@size-limit/preset-big-lib": "^11.2.0",
118
+ "@testing-library/dom": "^10.4.1",
117
119
  "@testing-library/jest-dom": "^6.6.3",
118
120
  "@testing-library/react": "^16.3.0",
119
121
  "@types/jest": "^29",
@@ -135,11 +137,8 @@
135
137
  "process": "^0.11.10",
136
138
  "punycode": "^2.3.1",
137
139
  "querystring-es3": "^0.2.1",
138
- "react": "^18.3.1",
139
- "react-dom": "^18.3.1",
140
140
  "size-limit": "^11.2.0",
141
141
  "skia-canvas": "^2.0.2",
142
- "svg-path-bounds": "^1.0.2",
143
142
  "terser": "^5.43.1",
144
143
  "ts-jest": "^29",
145
144
  "typescript": "^5.8.3",
package/polotno-app.d.ts CHANGED
@@ -1171,13 +1171,14 @@ export declare function createPolotnoApp({ container, key, showCredit, sections
1171
1171
  toHTML({ elementHook }?: {
1172
1172
  elementHook: any;
1173
1173
  }): Promise<string>;
1174
- saveAsHTML({ fileName }?: {
1174
+ saveAsHTML({ fileName, elementHook, }?: {
1175
1175
  fileName?: string;
1176
+ elementHook?: Function;
1176
1177
  }): Promise<void>;
1177
- toSVG({ elementHook, pageId, fontEmbedding }?: {
1178
- elementHook: any;
1179
- pageId: any;
1180
- fontEmbedding?: string;
1178
+ toSVG({ elementHook, pageId, fontEmbedding, }?: {
1179
+ elementHook?: Function;
1180
+ pageId?: string;
1181
+ fontEmbedding?: "none" | "inline";
1181
1182
  }): Promise<string>;
1182
1183
  saveAsSVG({ fileName, elementHook, pageId, fontEmbedding, }?: {
1183
1184
  fileName?: string;
@@ -2386,13 +2387,14 @@ export declare function createPolotnoApp({ container, key, showCredit, sections
2386
2387
  toHTML({ elementHook }?: {
2387
2388
  elementHook: any;
2388
2389
  }): Promise<string>;
2389
- saveAsHTML({ fileName }?: {
2390
+ saveAsHTML({ fileName, elementHook, }?: {
2390
2391
  fileName?: string;
2392
+ elementHook?: Function;
2391
2393
  }): Promise<void>;
2392
- toSVG({ elementHook, pageId, fontEmbedding }?: {
2393
- elementHook: any;
2394
- pageId: any;
2395
- fontEmbedding?: string;
2394
+ toSVG({ elementHook, pageId, fontEmbedding, }?: {
2395
+ elementHook?: Function;
2396
+ pageId?: string;
2397
+ fontEmbedding?: "none" | "inline";
2396
2398
  }): Promise<string>;
2397
2399
  saveAsSVG({ fileName, elementHook, pageId, fontEmbedding, }?: {
2398
2400
  fileName?: string;