polotno 2.9.2 → 2.9.3
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/html-element/quill-paste-smart.d.ts +9 -0
- package/canvas/html-element/quill-paste-smart.js +1 -0
- package/canvas/html-element.js +2 -2
- package/canvas/text-element/max-font-size.d.ts +6 -0
- package/canvas/text-element/max-font-size.js +1 -0
- package/canvas/text-element.js +1 -1
- package/package.json +5 -5
- package/polotno.bundle.js +73 -65
- package/utils/html.js +1 -1
- package/utils/html2canvas.d.ts +1 -1
- package/utils/html2canvas.js +1 -1
- package/utils/use-api.d.ts +7 -6
- package/utils/use-api.js +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const Clipboard: any;
|
|
2
|
+
declare class QuillPasteSmart extends Clipboard {
|
|
3
|
+
constructor(quill: any, options: any);
|
|
4
|
+
onCapturePaste(e: any): void;
|
|
5
|
+
getDOMPurifyOptions(): {};
|
|
6
|
+
substitute(html: any, DOMPurifyOptions: any): HTMLBodyElement;
|
|
7
|
+
isURL(str: any): boolean;
|
|
8
|
+
}
|
|
9
|
+
export default QuillPasteSmart;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const quill_1=__importDefault(require("quill")),dompurify_1=__importDefault(require("dompurify")),Clipboard=quill_1.default.import("modules/clipboard"),Delta=quill_1.default.import("delta");class QuillPasteSmart extends Clipboard{constructor(e,t){super(e,t),this.allowed=t.allowed,this.keepSelection=t.keepSelection,this.substituteBlockElements=t.substituteBlockElements,this.magicPasteLinks=t.magicPasteLinks,this.hooks=t.hooks}onCapturePaste(e){var t,i,o,a,s,l,n,u,d,r,h;e.preventDefault();const f=this.quill.getSelection();let p,c,L;e.clipboardData&&e.clipboardData.getData||!window.clipboardData||!window.clipboardData.getData?(p=e.clipboardData.getData("text/plain"),c=e.clipboardData.getData("text/html"),L=null===(i=null===(t=e.clipboardData)||void 0===t?void 0:t.items)||void 0===i?void 0:i[0]):p=window.clipboardData.getData("Text");let A=(new Delta).retain(f.index).delete(f.length);const S=this.getDOMPurifyOptions();let _=!1,T=p;if(!c&&S.ALLOWED_TAGS.includes("a")&&this.isURL(p)&&f.length>0&&this.magicPasteLinks)T=this.quill.getText(f.index,f.length),A=A.insert(T,{link:p});else if(!c&&S.ALLOWED_TAGS.includes("img")&&L&&"file"===L.kind&&L.type.match(/^image\//i)){const e=L.getAsFile(),t=new FileReader;t.onload=e=>{this.quill.insertEmbed(f.index,"image",e.target.result),this.keepSelection||this.quill.setSelection(f.index+1)},t.readAsDataURL(e)}else c||(_=!0,c=T),"function"==typeof(null===(o=this.hooks)||void 0===o?void 0:o.beforeSanitizeElements)&&dompurify_1.default.addHook("beforeSanitizeElements",this.hooks.beforeSanitizeElements),"function"==typeof(null===(a=this.hooks)||void 0===a?void 0:a.uponSanitizeElement)&&dompurify_1.default.addHook("uponSanitizeElement",this.hooks.uponSanitizeElement),"function"==typeof(null===(s=this.hooks)||void 0===s?void 0:s.afterSanitizeElements)&&dompurify_1.default.addHook("afterSanitizeElements",this.hooks.afterSanitizeElements),"function"==typeof(null===(l=this.hooks)||void 0===l?void 0:l.beforeSanitizeAttributes)&&dompurify_1.default.addHook("beforeSanitizeAttributes",this.hooks.beforeSanitizeAttributes),"function"==typeof(null===(n=this.hooks)||void 0===n?void 0:n.uponSanitizeAttribute)&&dompurify_1.default.addHook("uponSanitizeAttribute",this.hooks.uponSanitizeAttribute),"function"==typeof(null===(u=this.hooks)||void 0===u?void 0:u.afterSanitizeAttributes)&&dompurify_1.default.addHook("afterSanitizeAttributes",this.hooks.afterSanitizeAttributes),"function"==typeof(null===(d=this.hooks)||void 0===d?void 0:d.beforeSanitizeShadowDOM)&&dompurify_1.default.addHook("beforeSanitizeShadowDOM",this.hooks.beforeSanitizeShadowDOM),"function"==typeof(null===(r=this.hooks)||void 0===r?void 0:r.uponSanitizeShadowNode)&&dompurify_1.default.addHook("uponSanitizeShadowNode",this.hooks.uponSanitizeShadowNode),"function"==typeof(null===(h=this.hooks)||void 0===h?void 0:h.afterSanitizeShadowDOM)&&dompurify_1.default.addHook("afterSanitizeShadowDOM",this.hooks.afterSanitizeShadowDOM),_?(T=dompurify_1.default.sanitize(c,S),A=A.insert(T)):(!1!==this.substituteBlockElements?(c=this.substitute(c,S),T=c.innerHTML):T=dompurify_1.default.sanitize(c,S),A=A.concat(this.convert({html:T})));this.quill.updateContents(A,quill_1.default.sources.USER),_||(A=this.convert({html:T})),this.keepSelection?this.quill.setSelection(f.index,A.length(),quill_1.default.sources.SILENT):this.quill.setSelection(f.index+A.length(),quill_1.default.sources.SILENT),this.quill.scrollSelectionIntoView(),dompurify_1.default.removeAllHooks()}getDOMPurifyOptions(){var e,t,i;let o={};if((null===(e=this.allowed)||void 0===e?void 0:e.tags)&&(o.ALLOWED_TAGS=this.allowed.tags),(null===(t=this.allowed)||void 0===t?void 0:t.attributes)&&(o.ALLOWED_ATTR=this.allowed.attributes),void 0===o.ALLOWED_TAGS||void 0===o.ALLOWED_ATTR){let e=!1;void 0===o.ALLOWED_TAGS&&(e=!0,o.ALLOWED_TAGS=["p","br","span"]);let t=!1;void 0===o.ALLOWED_ATTR&&(t=!0,o.ALLOWED_ATTR=["class"]);const a=this.quill.getModule("toolbar");null===(i=null==a?void 0:a.controls)||void 0===i||i.forEach((i=>{switch(i[0]){case"bold":e&&(o.ALLOWED_TAGS.push("b"),o.ALLOWED_TAGS.push("strong"));break;case"italic":e&&(o.ALLOWED_TAGS.push("i"),o.ALLOWED_TAGS.push("em"));break;case"underline":e&&o.ALLOWED_TAGS.push("u");break;case"strike":e&&o.ALLOWED_TAGS.push("s");break;case"color":case"background":t&&o.ALLOWED_ATTR.push("style");break;case"script":e&&("super"===i[1].value?o.ALLOWED_TAGS.push("sup"):"sub"===i[1].value&&o.ALLOWED_TAGS.push("sub"));break;case"header":if(e){const e=e=>{"1"===e?o.ALLOWED_TAGS.push("h1"):"2"===e?o.ALLOWED_TAGS.push("h2"):"3"===e?o.ALLOWED_TAGS.push("h3"):"4"===e?o.ALLOWED_TAGS.push("h4"):"5"===e?o.ALLOWED_TAGS.push("h5"):"6"===e&&o.ALLOWED_TAGS.push("h6")};i[1].value?e(i[1].value):i[1].options&&i[1].options.length&&[].forEach.call(i[1].options,(t=>{t.value&&e(t.value)}))}break;case"code-block":e&&o.ALLOWED_TAGS.push("pre"),t&&o.ALLOWED_ATTR.push("spellcheck");break;case"list":e&&("ordered"===i[1].value?o.ALLOWED_TAGS.push("ol"):"bullet"===i[1].value&&o.ALLOWED_TAGS.push("ul"),o.ALLOWED_TAGS.push("li"));break;case"link":e&&o.ALLOWED_TAGS.push("a"),t&&(o.ALLOWED_ATTR.push("href"),o.ALLOWED_ATTR.push("target"),o.ALLOWED_ATTR.push("rel"));break;case"image":e&&o.ALLOWED_TAGS.push("img"),t&&(o.ALLOWED_ATTR.push("src"),o.ALLOWED_ATTR.push("title"),o.ALLOWED_ATTR.push("alt"));break;case"video":e&&o.ALLOWED_TAGS.push("iframe"),t&&(o.ALLOWED_ATTR.push("frameborder"),o.ALLOWED_ATTR.push("allowfullscreen"),o.ALLOWED_ATTR.push("src"));break;case"blockquote":e&&o.ALLOWED_TAGS.push(i[0])}}))}return o}substitute(e,t){let i;const o=["h1","h2","h3","h4","h5","h6"],a=["p","div","section","article","fieldset","address","aside","blockquote","canvas","dl","figcaption","figure","footer","form","header","main","nav","noscript","ol","pre","table","tfoot","ul","video"],s=["li","dt","dd","hr"];dompurify_1.default.addHook("uponSanitizeElement",((e,l,n)=>{let u=0;for(;!i&&u<3;)t.ALLOWED_TAGS.includes(a[u])&&(i=a[u]),++u;if(i&&e.tagName&&!t.ALLOWED_TAGS.includes(e.tagName.toLowerCase())){const t=e.tagName.toLowerCase();o.includes(t)?e.innerHTML=`<${i}><b>${e.innerHTML}</b></${i}>`:a.includes(t)?e.innerHTML=`<${i}>${e.innerHTML}</${i}>`:s.includes(t)&&(e.innerHTML=`${e.innerHTML}<br>`)}})),e=dompurify_1.default.sanitize(e,Object.assign(Object.assign({},t),{RETURN_DOM:!0,WHOLE_DOCUMENT:!1})),dompurify_1.default.removeAllHooks();const l=e=>{const t=document.createElement(e.tagName.toLowerCase()),i=e.attributes;return i.length&&Array.from(i).forEach((e=>t.setAttribute(e.nodeName,e.value))),t};let n=0;const u=(e,t)=>{for(t(e,n),e=n<=1?e.firstChild:void 0;e;)++n,u(e,t),e=e.nextSibling;--n};let d;const r=document.createElement("body");return u(e,((e,t)=>{if(1===t)if(e.tagName&&a.includes(e.tagName.toLowerCase())){d&&(d=void 0);const t=l(e);t.innerHTML=e.innerHTML,r.appendChild(t)}else if(void 0===d&&(d=document.createElement(i),r.appendChild(d)),e.tagName){const t=l(e);e.innerHTML&&(t.innerHTML=e.innerHTML),d.appendChild(t)}else{const t=document.createTextNode(e.textContent);d.appendChild(t)}})),r}isURL(e){return!!/^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/isu.test(e)}}quill_1.default.register("modules/clipboard",QuillPasteSmart,!0),exports.default=QuillPasteSmart;
|
package/canvas/html-element.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,r){void 0===r&&(r=i);var a=Object.getOwnPropertyDescriptor(t,i);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,r,a)}:function(e,t,i,r){void 0===r&&(r=i),e[r]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.HTMLElement=exports.createQuill=exports.quillRef=void 0;const react_1=__importDefault(require("react")),mobx_react_lite_1=require("mobx-react-lite"),react_konva_1=require("react-konva"),quill_1=__importDefault(require("quill/dist/quill"));require("quill-paste-smart");const konva_1=__importDefault(require("konva")),mobx=__importStar(require("mobx")),flags_1=require("../utils/flags"),apply_filters_1=require("./apply-filters"),text_element_1=require("./text-element"),use_color_1=require("./use-color"),html2canvas_1=require("../utils/html2canvas"),use_fadein_1=require("./use-fadein"),highlighter_1=require("./highlighter"),react_konva_utils_1=require("react-konva-utils"),styled_1=__importDefault(require("../utils/styled")),loader_1=require("../utils/loader"),text_1=require("../utils/text"),fonts=__importStar(require("../utils/fonts")),screen_1=require("../utils/screen");exports.quillRef=mobx.observable({enabled:!1,currentFormat:{},editor:mobx.observable.object({instance:null},{},{deep:!1})});const RichTextContainer=(0,styled_1.default)("div",react_1.default.forwardRef)`
|
|
1
|
+
"use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,r){void 0===r&&(r=i);var a=Object.getOwnPropertyDescriptor(t,i);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[i]}}),Object.defineProperty(e,r,a)}:function(e,t,i,r){void 0===r&&(r=i),e[r]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.HTMLElement=exports.createQuill=exports.quillRef=void 0;const react_1=__importDefault(require("react")),mobx_react_lite_1=require("mobx-react-lite"),react_konva_1=require("react-konva"),quill_1=__importDefault(require("quill/dist/quill"));require("quill-paste-smart");const konva_1=__importDefault(require("konva")),mobx=__importStar(require("mobx")),flags_1=require("../utils/flags"),apply_filters_1=require("./apply-filters"),text_element_1=require("./text-element"),use_color_1=require("./use-color"),html2canvas_1=require("../utils/html2canvas"),use_fadein_1=require("./use-fadein"),highlighter_1=require("./highlighter"),react_konva_utils_1=require("react-konva-utils"),styled_1=__importDefault(require("../utils/styled")),loader_1=require("../utils/loader"),text_1=require("../utils/text"),fonts=__importStar(require("../utils/fonts")),screen_1=require("../utils/screen"),max_font_size_1=require("./text-element/max-font-size");exports.quillRef=mobx.observable({enabled:!1,currentFormat:{},editor:mobx.observable.object({instance:null},{},{deep:!1})});const RichTextContainer=(0,styled_1.default)("div",react_1.default.forwardRef)`
|
|
2
2
|
.ql-editor {
|
|
3
3
|
outline: none;
|
|
4
4
|
}
|
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
.ql-direction-rtl {
|
|
10
10
|
direction: rtl;
|
|
11
11
|
}
|
|
12
|
-
`,createQuill=e=>new quill_1.default(e,{toolbar:!1,keyboard:!1,clipboard:{matchVisual:!1},formats:["background","bold","color","font","italic","size","strike","underline","indent","list","
|
|
12
|
+
`,createQuill=e=>new quill_1.default(e,{toolbar:!1,keyboard:!1,clipboard:{matchVisual:!1},formats:["background","bold","color","font","italic","size","strike","underline","indent","list","direction"]});exports.createQuill=createQuill;const RichEditor=({html:e,onBlur:t,onChange:i,element:r})=>{const a=react_1.default.useRef(null);react_1.default.useEffect((()=>{if(!a.current)return;const e=(0,exports.createQuill)(a.current);return exports.quillRef.editor.instance=e,window.__polotnoQuill=e,e.on("text-change",(()=>{e.getSelection()&&(exports.quillRef.currentFormat=e.getFormat()),setTimeout((()=>{var e;i(null===(e=a.current)||void 0===e?void 0:e.childNodes[0].innerHTML)}),10)})),e.setSelection(0,0,"api"),e.on("selection-change",(i=>{i||t(),i&&(exports.quillRef.currentFormat=e.getFormat())})),a.current.childNodes[0].addEventListener("blur",(e=>{var i;(null===(i=e.relatedTarget)||void 0===i?void 0:i.classList.contains("ql-clipboard"))||t()})),()=>{exports.quillRef.editor.instance=null,exports.quillRef.currentFormat={},delete window.__polotnoQuill}}),[]),react_1.default.useEffect((()=>{var t;const i=exports.quillRef.editor.instance;if(!i)return;const n=i.getSelection();if(!((null===(t=a.current)||void 0===t?void 0:t.childNodes[0].innerHTML)===r.text)){var o=i.clipboard.convert("<div class='ql-editor' style='outline: none;'>"+e+"<p><br></p></div>");i.setContents(o),i.history.clear(),n&&(i.setSelection(n.index,n.length),exports.quillRef.currentFormat=i.getFormat())}}),[r.text]);const n={color:r.fill};return r.fill.indexOf("gradient")>=0&&(n["background-color"]=r.fill,n["background-image"]=r.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"),react_1.default.createElement(RichTextContainer,{ref:a,style:Object.assign(Object.assign({},n),{fontSize:r.fontSize,width:r.a.width,fontFamily:r.fontFamily,lineHeight:r.lineHeight,letterSpacing:r.letterSpacing+"rem",textAlign:r.align}),dir:(0,text_element_1.getDir)((0,text_1.removeTags)(r.text))})};function useHtmlSize(e,t,i){return react_1.default.useMemo((()=>(0,html2canvas_1.detectSize)(e)),[e,t.width,i])}function hasNonTransparentPixel(e){const t=e.getContext("2d").getImageData(0,0,e.width,e.height).data;for(let e=0;e<t.length;e+=4)if(0!==t[e+3])return!0;return!1}function isCanvasBlank(e){return!hasNonTransparentPixel(e)}function getHtml(e,{fontFamily:t="",color:i="black"}={}){let r=`color: ${i||e.fill}`;return e.fill.indexOf("gradient")>=0&&(r=`\n background-color: ${i};\n background-image: ${e.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 `),`<div style="white-space: unset; width: ${Math.round(e.width||100)}px; ${r}; font-size: ${e.fontSize}px; font-family: '${t}'; text-decoration: ${e.textDecoration}; text-align: ${e.align}; line-height: ${e.lineHeight}; letter-spacing: ${e.letterSpacing}rem; font-style: ${e.fontStyle}; font-weight: ${e.fontWeight}; -webkit-text-stroke: ${e.strokeWidth}px ${e.stroke};" contentEditable dir="${(0,text_element_1.getDir)((0,text_1.removeTags)(e.text))}">${e.text.replaceAll("\n","</br>")}</div>`}const findFitFontSize=e=>{let t=e.fontSize;for(let i=1;i<50;i++){const i=getHtml(Object.assign(Object.assign({},e.toJSON()),{fontSize:t}),{fontFamily:e.fontFamily}),{height:r}=(0,html2canvas_1.detectSize)(i);if(!(e.height&&r>e.height))break;t-=.5}return t},isSafari=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);exports.HTMLElement=(0,mobx_react_lite_1.observer)((({element:e,store:t})=>{const i=react_1.default.useRef(null),[r,a]=react_1.default.useState(),[n,o]=react_1.default.useState(!1),[l,s]=react_1.default.useState(!0),[c,d]=react_1.default.useState(!1),f=react_1.default.useRef(e.height),u=t.selectedElements.indexOf(e)>=0,h=e.fontSize/3,{textVerticalResizeEnabled:g}=flags_1.flags,_=(0,text_element_1.usePrevious)(e.fontFamily),[m]=(0,text_element_1.useFontLoader)(t,e.fontFamily),x=e._editModeEnabled;(0,use_fadein_1.useFadeIn)(i);const p=m?e.fontFamily:_!==e.fontFamily?_:"Arial",b=(0,use_color_1.useColor)(e).fill,y=getHtml(e,{fontFamily:p,color:b}),{width:v,height:w}=useHtmlSize(y,e,m);react_1.default.useEffect((()=>{if(!m)return;if(!e.height)return void e.set({height:w});const{textOverflow:i}=flags_1.flags;if("change-font-size"!==i||n)"resize"===i&&(g&&e.height<w&&t.history.ignore((()=>{e.set({height:w})})),g||e.height===w||t.history.ignore((()=>{e.set({height:w})})));else{const i=findFitFontSize(e);i!==e.fontSize?t.history.ignore((()=>{e.set({fontSize:i})})):e.height!==w&&(g&&e.height<w?t.history.ignore((()=>{e.set({height:w})})):g||t.history.ignore((()=>{e.set({height:w})})))}}));const k=react_1.default.useRef(0);react_1.default.useEffect((()=>{n||x||(async()=>{k.current++;const i=k.current,r=(0,loader_1.incrementLoader)(`text ${e.id}`);s(!0);let n=null;const o=isSafari?5:1;for(let a=0;a<o;a++){if(n=await(0,html2canvas_1.htmlToCanvas)({html:y,width:e.width||1,height:e.height||w||1,fontFamily:p,padding:h,pixelRatio:t._elementsPixelRatio,font:t.fonts.find((e=>e.fontFamily===p))||fonts.globalFonts.find((e=>e.fontFamily===p))}),i!==k.current)return void r();isCanvasBlank(n)&&isSafari&&await new Promise((e=>setTimeout(e,50*(a+1))))}n?(a(n),s(!1),konva_1.default.Util.requestAnimFrame(r)):r()})()}),[y,n,w,x,p,e.height,t._elementsPixelRatio]);const S=n||l;react_1.default.useEffect((()=>mobx.autorun((()=>{const t=i.current;(0,apply_filters_1.applyFilter)(t,e)}))),[r,S,e.shadowColor,e.shadowOffsetX,e.shadowOffsetY,e.shadowOpacity]);let E=0;"middle"===e.verticalAlign&&(E=(e.height-w)/2),"bottom"===e.verticalAlign&&(E=e.height-w);const z=(0,text_element_1.getLineHeight)({fontLoaded:m,fontFamily:e.fontFamily,fontSize:e.fontSize,lineHeight:e.lineHeight}),q=(0,screen_1.useMobile)();return react_1.default.createElement(react_1.default.Fragment,null,react_1.default.createElement(react_konva_1.Rect,{x:e.a.x,y:e.a.y,offsetX:e.backgroundPadding*(e.fontSize*z*.5),offsetY:e.backgroundPadding*(e.fontSize*z*.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*z),height:e.a.height+e.backgroundPadding*(e.fontSize*z),cornerRadius:e.backgroundCornerRadius*(e.fontSize*z*.5)}),react_1.default.createElement(react_konva_1.Rect,{ref:i,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:!S,draggable:q?e.draggable&&u:e.draggable,preventDefault:!q||u,opacity:x?0:e.a.opacity,hideInExport:!e.showInExport,onMouseEnter:()=>{d(!0)},onMouseLeave:()=>{d(!1)},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:()=>{e.contentEditable&&e.toggleEditMode(!0)},onDblTap:()=>{e.contentEditable&&e.toggleEditMode(!0)},onTransformStart:t=>{o(!0),f.current=e.height},onTransform:t=>{var i;const r=t.target,a=(null===(i=r.getStage())||void 0===i?void 0:i.findOne("Transformer")).getActiveAnchor(),n="middle-left"===a||"middle-right"===a,o="top-center"===a||"bottom-center"===a,l=r.scaleX();if(n){const t=r.scaleX(),i=Math.max(r.width()*t,e.fontSize);if(r.width(i),r.scaleX(1),flags_1.flags.textVerticalResizeEnabled){const t=Math.max(w,f.current);e.set({height:t})}e.set({width:i,x:r.x(),y:r.y()})}else if(o){let i="resize"===flags_1.flags.textOverflow?w:e.lineHeight*e.fontSize;const a=Math.max(i,t.target.height()*t.target.scaleY());r.scaleY(1),e.set({x:r.x(),y:r.y(),height:a,rotation:r.rotation()})}else r.scaleX(1),r.scaleY(1),e.set({fontSize:e.fontSize*l,width:r.width()*l,x:r.x(),y:r.y(),rotation:r.rotation(),height:r.height()*l})},onTransformEnd:t=>{o(!1),s(!0);const i=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:e.fontSize*i,width:t.target.width()*i,x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),shadowBlur:e.shadowBlur*i,shadowOffsetX:e.shadowOffsetX*i,shadowOffsetY:e.shadowOffsetY*i,strokeWidth:e.strokeWidth*i})}}),react_1.default.createElement(react_konva_1.Image,{ref:i,image:r,x:e.a.x,y:e.a.y,offsetX:h,offsetY:h-E,listening:!1,rotation:e.rotation,width:e.a.width+2*h,height:e.a.height+2*h,visible:!S,opacity:x?0:e.a.opacity,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,hideInExport:!e.showInExport}),S&&react_1.default.createElement(react_konva_1.Group,{x:e.a.x,y:e.a.y,rotation:e.rotation,offsetY:-E},react_1.default.createElement(react_konva_utils_1.Html,{divProps:{style:{pointerEvents:"none"}}},react_1.default.createElement(RichTextContainer,{dangerouslySetInnerHTML:{__html:y},style:{pointerEvents:"none",display:"inline-block"}}))),x&&react_1.default.createElement(react_konva_1.Group,{x:e.a.x,y:e.a.y,rotation:e.rotation,offsetY:-E},react_1.default.createElement(react_konva_utils_1.Html,null,react_1.default.createElement(RichEditor,{html:y,element:e,onChange:t=>{const i=(0,max_font_size_1.getLimitedFontSize)({oldText:(0,text_1.removeTags)(e.text),newText:(0,text_1.removeTags)(t),element:e});e.set({text:t,fontSize:i})},onBlur:t=>{e.toggleEditMode(!1)}}))),(u||c)&&react_1.default.createElement(highlighter_1.Highlighter,{element:e}))}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function getLimitedFontSize({oldText:t,newText:e,element:i}){if(!(e.length/Math.max(20,t.length)>=4))return i.fontSize;const n=i.width*i.page.computedHeight/e.length,o=1.5*Math.sqrt(n),r=i.fontSize;return Math.min(r,Math.max(5,Math.round(o)))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getLimitedFontSize=void 0,exports.getLimitedFontSize=getLimitedFontSize;
|
package/canvas/text-element.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.TextElement=exports.usePrevious=exports.getLineHeight=exports.useFontLoader=exports.getDir=exports.isRTLText=void 0;const react_1=__importDefault(require("react")),mobx_react_lite_1=require("mobx-react-lite"),react_konva_1=require("react-konva"),react_konva_utils_1=require("react-konva-utils"),mobx_1=require("mobx"),konva_1=__importDefault(require("konva")),svg_round_corners_1=require("svg-round-corners"),use_color_1=require("./use-color"),loader_1=require("../utils/loader"),fonts_1=require("../utils/fonts"),flags_1=require("../utils/flags"),text_1=require("../utils/text"),apply_filters_1=require("./apply-filters"),use_fadein_1=require("./use-fadein"),highlighter_1=require("./highlighter"),screen_1=require("../utils/screen"),mobx_state_tree_1=require("mobx-state-tree");konva_1.default._fixTextRendering=!0;const styleNode=document.createElement("style");styleNode.type="text/css",document.head.appendChild(styleNode);const initialStyles={border:"none",padding:"0px",overflow:"hidden",background:"none",outline:"none",resize:"none",overflowWrap:"break-word",whiteSpace:"pre-wrap",userSelect:"text",wordBreak:"normal"};function isRTL(e){var t="֑-߿יִ-﷽ﹰ-ﻼ";return new RegExp("^[^"+t+"]*?["+t+"]").test(e)}function isRTLText(e){e=e.replace(/\s/g,"");let t=0;for(var r=0;r<e.length;r++){isRTL(e[r])&&(t+=1)}return t>e.length/2}function getDir(e){return isRTLText(e)?"rtl":"ltr"}exports.isRTLText=isRTLText,exports.getDir=getDir;const TextInput=(0,mobx_react_lite_1.observer)((({textNodeRef:e,element:t,onBlur:r,selectAll:n,cursorPosition:i})=>{const[o,a]=react_1.default.useState(initialStyles),l=e.current;react_1.default.useLayoutEffect((()=>{const e={};e.width=l.width()-2*l.padding()+"px",e.height=l.height()-2*l.padding()+l.fontSize()*l.lineHeight()+"px",e.fontSize=l.fontSize()+"px",e.lineHeight=l.lineHeight()+.01,e.fontFamily=l.fontFamily(),e.textAlign=l.align(),e.color=l.fill(),e.fontWeight=t.fontWeight,e.fontStyle=t.fontStyle,e.letterSpacing=t.letterSpacing+"em";const r=`\n .polotno-input::placeholder {\n color: ${o.color};\n opacity: 0.6;\n }\n `;styleNode.innerHTML="",styleNode.appendChild(document.createTextNode(r)),JSON.stringify(e)!==JSON.stringify(o)&&a(e)}));const s=react_1.default.useRef(null);react_1.default.useEffect((()=>{const e=setTimeout((()=>{var e;const t=s.current;if(!t)return;null===(e=s.current)||void 0===e||e.focus();const r=i||t.value.length;t.selectionStart=t.selectionEnd=r,n&&(null==t||t.select(),document.execCommand("selectAll",!1,null))}));return()=>{clearTimeout(e)}}),[]),react_1.default.useEffect((()=>{window.addEventListener("blur",r);const e=e=>{var t;(null===(t=s.current)||void 0===t?void 0:t.contains(e.target))||r()};return window.addEventListener("touchstart",e),()=>{window.removeEventListener("blur",r),window.removeEventListener("touchstart",e)}}),[]);let u=0;const d=l.textArr.length*l.lineHeight()*l.fontSize();"middle"===t.verticalAlign&&(u=(t.a.height-d)/2),"bottom"===t.verticalAlign&&(u=t.a.height-d);const c=(0,text_1.removeTags)(t.text);return react_1.default.createElement(react_konva_utils_1.Html,null,react_1.default.createElement("textarea",{className:"polotno-input",ref:s,dir:getDir(c),style:Object.assign(Object.assign(Object.assign({},initialStyles),o),{paddingTop:u+"px"}),value:c,onChange:e=>{t.set({text:e.target.value})},placeholder:t.placeholder,onBlur:r}))})),useEditor=e=>{const[t,r]=react_1.default.useState(!1),n=react_1.default.useRef(!1);return react_1.default.useEffect((()=>{var t=!0;return setTimeout((()=>{t&&(e._editModeEnabled&&(n.current=!0),r(!0),setTimeout((()=>{n.current=!1}),50))}),50),()=>{t=!1}}),[]),{editorEnabled:t&&e._editModeEnabled,selectAll:n.current}},useFontLoader=(e,t)=>{const[r,n]=react_1.default.useReducer((e=>e+1),0),i=react_1.default.useRef((0,fonts_1.isFontLoaded)(t));return react_1.default.useLayoutEffect((()=>{if(i.current=(0,fonts_1.isFontLoaded)(t),i.current)return;let r=!0;return(async()=>{i.current=!1,n();const o=(0,loader_1.incrementLoader)(`text ${t}`);await e.loadFont(t),setTimeout(o,100),r&&(i.current=!0,n())})(),()=>{r=!1}}),[t]),[i.current]};exports.useFontLoader=useFontLoader;const getLineHeight=({fontLoaded:e,fontFamily:t,fontSize:r,lineHeight:n})=>react_1.default.useMemo((()=>{if("number"==typeof n)return n;const e=document.createElement("div");e.style.fontFamily=t,e.style.fontSize=r+"px",e.style.lineHeight=n,e.innerText="Test text",document.body.appendChild(e);const i=e.offsetHeight;return document.body.removeChild(e),i/r}),[e,t,r,n]);function getRelativePointerPosition(e){var t=e.getAbsoluteTransform().copy();t.invert();var r=e.getStage().getPointerPosition();return t.point(r)}function getCursorPosition(e){var t;const r=e.target,n=getRelativePointerPosition(r),i=r.textArr,o=Math.floor(n.y/(r.fontSize()*r.lineHeight())),a=i.slice(0,o).reduce(((e,t)=>e+t.text.length),o),l=null!==(t=i[o])&&void 0!==t?t:i[0];let s=0;"right"===r.align()?s=r.width()-l.width:"center"===r.align()&&(s=r.width()/2-l.width/2);return a+Math.round((n.x-s)/l.width*l.text.length)}function usePrevious(e){const t=react_1.default.useRef(e),r=react_1.default.useRef(e);return react_1.default.useMemo((()=>{r.current=t.current,t.current=e}),[e]),r.current}function isNonSpaceSeparatedLanguage(e){return/[\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\uFF00-\uFFEF\u4E00-\u9FAF\uAC00-\uD7AF]/.test(e)}function findFitFontSize(e,t){const r=e.fontSize(),n=e.height(),i=(0,text_1.removeTags)(t.text);let o=t.a.fontSize;e.height(void 0);const a=Math.round(2*t.a.fontSize)-1;for(let r=1;r<a;r++){const r=t.a.height&&e.height()>t.a.height;let n=i.split("\n").join(" ").split(/[\s-]+/).reduce(((e,t)=>isNonSpaceSeparatedLanguage(t)?e.concat(t.split("")):e.concat(t)),[]),a=e.textArr.map((e=>e.text)).join(";");const l=n.find((e=>!a.includes(e)||(a=a.replace(e,""),!1)));if(!(r||l))break;o-=.5,e.fontSize(o)}return e.fontSize(r),e.height(n),o}function generateBackgroundShape({lines:e,lineHeight:t,width:r,align:n="left",padding:i=0,cornerRadius:o=0}){var a;e.forEach(((e,t)=>{e.cx=r/2,"right"===n?e.cx=r-e.width/2:"left"===n&&(e.cx=e.width/2),"justify"!==n||e.lastInParagraph||(e.width=r),"justify"===n&&(e.cx=e.width/2)}));let l=`M ${null===(a=e[0])||void 0===a?void 0:a.cx} ${-i}`;e.forEach(((r,n)=>{const{cx:o}=r,a=e[n-1];a&&a.width>r.width?l+=` L ${o+r.width/2+i} ${n*t+i}`:l+=` L ${o+r.width/2+i} ${n*t-i}`;const s=e[n+1];s&&s.width>r.width?l+=` L ${o+r.width/2+i} ${(n+1)*t-i}`:l+=` L ${o+r.width/2+i} ${(n+1)*t+i}`}));for(var s=e.length-1;s>=0;s--){const r=e[s],{cx:n}=r,o=e[s+1];o&&o.width>r.width?l+=` L ${n-r.width/2-i} ${(s+1)*t-i}`:l+=` L ${n-r.width/2-i} ${(s+1)*t+i}`;const a=e[s-1];a&&a.width>r.width?l+=` L ${n-r.width/2-i} ${s*t+i}`:l+=` L ${n-r.width/2-i} ${s*t-i}`}l+=" Z";const u=(0,svg_round_corners_1.parsePath)(l);return(0,svg_round_corners_1.roundCommands)(u,o).path}exports.getLineHeight=getLineHeight,exports.usePrevious=usePrevious,exports.TextElement=(0,mobx_react_lite_1.observer)((({element:e,store:t})=>{const r=react_1.default.useRef(null),n=react_1.default.useRef(null),{editorEnabled:i,selectAll:o}=useEditor(e),[a,l]=react_1.default.useState(!1),[s,u]=react_1.default.useState(!1),d=react_1.default.useRef(e.a.height),c=t.selectedElements.indexOf(e)>=0,{textVerticalResizeEnabled:f}=flags_1.flags,h=usePrevious(e.fontFamily),[g,_]=react_1.default.useState([]);react_1.default.useEffect((()=>{var e,t;const n=null!==(t=null===(e=r.current)||void 0===e?void 0:e.textArr)&&void 0!==t?t:[];JSON.stringify(n)!==JSON.stringify(g)&&_(n)})),react_1.default.useEffect((()=>{if(e.a.width)return;const t=r.current;t.width(600),e.set({width:1.4*t.getTextWidth()})}),[]),react_1.default.useLayoutEffect((()=>(0,mobx_1.autorun)((()=>{const t=r.current;(0,apply_filters_1.applyFilter)(t,e)}))));const[p]=(0,exports.useFontLoader)(t,e.fontFamily),x=(0,text_1.removeTags)(e.text),v=()=>{const e=r.current.clone({height:void 0}),t=Math.ceil(e.fontSize()*e.lineHeight()*e.textArr.length+1);return e.destroy(),t};react_1.default.useLayoutEffect((()=>{if(!p)return;const{textOverflow:n}=flags_1.flags;if(e.a.height)if("change-font-size"!==n||s||t.isPlaying){if("resize"===n){const n=v();f&&e.a.height<n&&t.history.ignore((()=>{var t;(0,mobx_state_tree_1.isAlive)(e)&&e.set({height:n}),null===(t=r.current)||void 0===t||t.height(n)}),!1,!0),f||e.a.height===n||t.history.ignore((()=>{var t;(0,mobx_state_tree_1.isAlive)(e)&&e.set({height:n}),null===(t=r.current)||void 0===t||t.height(n)}),!1,!0)}}else{const n=findFitFontSize(r.current,e);if(n!==e.a.fontSize)return void t.history.ignore((()=>{e.set({fontSize:n})}),!1,!0);const i=v();e.a.height===i||f||t.history.ignore((()=>{e.set({height:i})}),!1,!0)}else{const r=v();t.history.ignore((()=>{e.set({height:r})}),!1,!0)}})),react_1.default.useLayoutEffect((()=>{const t=r.current;t&&(t.width(t.width()+1e-8),t._setTextData(),(0,apply_filters_1.applyFilter)(t,e))}),[p]);const m=react_1.default.useRef(null),y=react_1.default.useRef(0),w=r=>{r.evt.preventDefault();const n=t.selectedShapes.find((t=>t===e));n&&e.contentEditable&&(y.current=getCursorPosition(r),e.toggleEditMode())},S=!x&&e.placeholder?.6:e.a.opacity;(0,use_fadein_1.useFadeIn)(r,S);const b=(0,exports.getLineHeight)({fontLoaded:p,fontFamily:e.fontFamily,fontSize:e.a.fontSize,lineHeight:e.lineHeight}),E=e.selectable||"admin"===t.role,L=(0,use_color_1.useColor)(e),F=react_1.default.useMemo((()=>e.backgroundEnabled?generateBackgroundShape({lines:JSON.parse(JSON.stringify(g)),cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*b*.5),lineHeight:b*e.a.fontSize,padding:e.backgroundPadding*(e.a.fontSize*b*.5),width:e.a.width,align:e.align}):""),[e.backgroundEnabled,e.backgroundCornerRadius,e.a.fontSize,b,e.backgroundPadding,e.a.width,e.align,g]),T=(0,screen_1.useMobile)();let z=0;return"middle"===e.verticalAlign?z=(e.a.height-g.length*b*e.a.fontSize)/2:"bottom"===e.verticalAlign&&(z=e.a.height-g.length*b*e.a.fontSize),react_1.default.createElement(react_1.default.Fragment,null,react_1.default.createElement(react_konva_1.Path,{ref:n,x:e.a.x,y:e.a.y,rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*S,data:F,fill:e.backgroundColor,offsetY:-z}),react_1.default.createElement(react_konva_1.Text,Object.assign({ref:r,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:x||e.placeholder},L,{stroke:e.stroke,lineJoin:"round",strokeWidth:e.strokeWidth,fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:`"${e.fontFamily}", "${h}"`,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration,align:e.align,verticalAlign:e.verticalAlign,draggable:T?e.draggable&&c:e.draggable,preventDefault:!T||c,opacity:S,visible:!e._editModeEnabled,ellipsis:"ellipsis"===flags_1.flags.textOverflow,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,lineHeight:b,letterSpacing:e.letterSpacing*e.a.fontSize,listening:E,onDragMove:t=>{e.set({x:t.target.x(),y:t.target.y()})},onDragEnd:t=>{e.set({x:t.target.x(),y:t.target.y()})},onMouseEnter:()=>{l(!0)},onMouseLeave:()=>{l(!1)},onClick:w,onTap:w,onTransformStart:()=>{u(!0),d.current=r.current.height()},onTransform:t=>{var r,i;const o=t.target;null===(r=n.current)||void 0===r||r.setAttrs({x:o.x(),y:o.y(),rotation:o.rotation(),scale:o.scale()});const a=(null===(i=o.getStage())||void 0===i?void 0:i.findOne("Transformer")).getActiveAnchor();if("middle-left"===a||"middle-right"===a){const t=o.scaleX(),r=o.width()*t,n=e.a.fontSize;let i=r;r<n&&(i=n,m.current&&o.position(m.current)),o.width(i),o.scaleX(1),o.scaleY(1);const a=v();if("ellipsis"!==flags_1.flags.textOverflow){const t=Math.max(a,d.current);o.height(t),e.set({height:o.height()})}e.set({x:o.x(),y:o.y(),width:o.width(),rotation:o.rotation()}),(0,apply_filters_1.applyFilter)(o,e)}if("top-center"===a||"bottom-center"===a){let r="resize"===flags_1.flags.textOverflow?v():b*e.a.fontSize;t.target.height(Math.max(r,t.target.height()*t.target.scaleY())),t.target.scaleY(1)}m.current=t.target.position()},onTransformEnd:t=>{var r;const i=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:Math.round(e.a.fontSize*i),width:Math.ceil(t.target.width()*i),x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),height:t.target.height()*i,shadowBlur:e.shadowBlur*i,shadowOffsetX:e.shadowOffsetX*i,shadowOffsetY:e.shadowOffsetY*i,strokeWidth:e.strokeWidth*i}),null===(r=n.current)||void 0===r||r.setAttrs({scaleX:1,scaleY:1}),u(!1)}})),i&&react_1.default.createElement(react_konva_1.Group,{x:e.a.x,y:e.a.y,rotation:e.a.rotation},react_1.default.createElement(TextInput,{textNodeRef:r,element:e,selectAll:o,cursorPosition:y.current,onBlur:()=>{e.toggleEditMode(!1)}})),!s&&(a||c)&&react_1.default.createElement(highlighter_1.Highlighter,{element:e}))}));
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.TextElement=exports.usePrevious=exports.getLineHeight=exports.useFontLoader=exports.getDir=exports.isRTLText=void 0;const react_1=__importDefault(require("react")),mobx_react_lite_1=require("mobx-react-lite"),react_konva_1=require("react-konva"),react_konva_utils_1=require("react-konva-utils"),mobx_1=require("mobx"),konva_1=__importDefault(require("konva")),svg_round_corners_1=require("svg-round-corners"),use_color_1=require("./use-color"),loader_1=require("../utils/loader"),fonts_1=require("../utils/fonts"),flags_1=require("../utils/flags"),text_1=require("../utils/text"),apply_filters_1=require("./apply-filters"),use_fadein_1=require("./use-fadein"),highlighter_1=require("./highlighter"),screen_1=require("../utils/screen"),mobx_state_tree_1=require("mobx-state-tree"),max_font_size_1=require("./text-element/max-font-size");konva_1.default._fixTextRendering=!0;const styleNode=document.createElement("style");styleNode.type="text/css",document.head.appendChild(styleNode);const initialStyles={border:"none",padding:"0px",overflow:"hidden",background:"none",outline:"none",resize:"none",overflowWrap:"break-word",whiteSpace:"pre-wrap",userSelect:"text",wordBreak:"normal"};function isRTL(e){var t="֑-߿יִ-﷽ﹰ-ﻼ";return new RegExp("^[^"+t+"]*?["+t+"]").test(e)}function isRTLText(e){e=e.replace(/\s/g,"");let t=0;for(var r=0;r<e.length;r++){isRTL(e[r])&&(t+=1)}return t>e.length/2}function getDir(e){return isRTLText(e)?"rtl":"ltr"}exports.isRTLText=isRTLText,exports.getDir=getDir;const TextInput=(0,mobx_react_lite_1.observer)((({textNodeRef:e,element:t,onBlur:r,selectAll:n,cursorPosition:i})=>{const[o,a]=react_1.default.useState(initialStyles),l=e.current;react_1.default.useLayoutEffect((()=>{const e={};e.width=l.width()-2*l.padding()+"px",e.height=l.height()-2*l.padding()+l.fontSize()*l.lineHeight()+"px",e.fontSize=l.fontSize()+"px",e.lineHeight=l.lineHeight()+.01,e.fontFamily=l.fontFamily(),e.textAlign=l.align(),e.color=l.fill(),e.fontWeight=t.fontWeight,e.fontStyle=t.fontStyle,e.letterSpacing=t.letterSpacing+"em";const r=`\n .polotno-input::placeholder {\n color: ${o.color};\n opacity: 0.6;\n }\n `;styleNode.innerHTML="",styleNode.appendChild(document.createTextNode(r)),JSON.stringify(e)!==JSON.stringify(o)&&a(e)}));const s=react_1.default.useRef(null);react_1.default.useEffect((()=>{const e=setTimeout((()=>{var e;const t=s.current;if(!t)return;null===(e=s.current)||void 0===e||e.focus();const r=i||t.value.length;t.selectionStart=t.selectionEnd=r,n&&(null==t||t.select(),document.execCommand("selectAll",!1,null))}));return()=>{clearTimeout(e)}}),[]),react_1.default.useEffect((()=>{window.addEventListener("blur",r);const e=e=>{var t;(null===(t=s.current)||void 0===t?void 0:t.contains(e.target))||r()};return window.addEventListener("touchstart",e),()=>{window.removeEventListener("blur",r),window.removeEventListener("touchstart",e)}}),[]);let u=0;const d=l.textArr.length*l.lineHeight()*l.fontSize();"middle"===t.verticalAlign&&(u=(t.a.height-d)/2),"bottom"===t.verticalAlign&&(u=t.a.height-d);const c=(0,text_1.removeTags)(t.text);return react_1.default.createElement(react_konva_utils_1.Html,null,react_1.default.createElement("textarea",{className:"polotno-input",ref:s,dir:getDir(c),style:Object.assign(Object.assign(Object.assign({},initialStyles),o),{paddingTop:u+"px"}),value:c,onChange:e=>{const r=(0,max_font_size_1.getLimitedFontSize)({oldText:t.text,newText:e.target.value,element:t});t.set({text:e.target.value,fontSize:r})},placeholder:t.placeholder,onBlur:r}))})),useEditor=e=>{const[t,r]=react_1.default.useState(!1),n=react_1.default.useRef(!1);return react_1.default.useEffect((()=>{var t=!0;return setTimeout((()=>{t&&(e._editModeEnabled&&(n.current=!0),r(!0),setTimeout((()=>{n.current=!1}),50))}),50),()=>{t=!1}}),[]),{editorEnabled:t&&e._editModeEnabled,selectAll:n.current}},useFontLoader=(e,t)=>{const[r,n]=react_1.default.useReducer((e=>e+1),0),i=react_1.default.useRef((0,fonts_1.isFontLoaded)(t));return react_1.default.useLayoutEffect((()=>{if(i.current=(0,fonts_1.isFontLoaded)(t),i.current)return;let r=!0;return(async()=>{i.current=!1,n();const o=(0,loader_1.incrementLoader)(`text ${t}`);await e.loadFont(t),setTimeout(o,100),r&&(i.current=!0,n())})(),()=>{r=!1}}),[t]),[i.current]};exports.useFontLoader=useFontLoader;const getLineHeight=({fontLoaded:e,fontFamily:t,fontSize:r,lineHeight:n})=>react_1.default.useMemo((()=>{if("number"==typeof n)return n;const e=document.createElement("div");e.style.fontFamily=t,e.style.fontSize=r+"px",e.style.lineHeight=n,e.innerText="Test text",document.body.appendChild(e);const i=e.offsetHeight;return document.body.removeChild(e),i/r}),[e,t,r,n]);function getRelativePointerPosition(e){var t=e.getAbsoluteTransform().copy();t.invert();var r=e.getStage().getPointerPosition();return t.point(r)}function getCursorPosition(e){var t;const r=e.target,n=getRelativePointerPosition(r),i=r.textArr,o=Math.floor(n.y/(r.fontSize()*r.lineHeight())),a=i.slice(0,o).reduce(((e,t)=>e+t.text.length),o),l=null!==(t=i[o])&&void 0!==t?t:i[0];let s=0;"right"===r.align()?s=r.width()-l.width:"center"===r.align()&&(s=r.width()/2-l.width/2);return a+Math.round((n.x-s)/l.width*l.text.length)}function usePrevious(e){const t=react_1.default.useRef(e),r=react_1.default.useRef(e);return react_1.default.useMemo((()=>{r.current=t.current,t.current=e}),[e]),r.current}function isNonSpaceSeparatedLanguage(e){return/[\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\uFF00-\uFFEF\u4E00-\u9FAF\uAC00-\uD7AF]/.test(e)}function findFitFontSize(e,t){const r=e.fontSize(),n=e.height(),i=(0,text_1.removeTags)(t.text);let o=t.a.fontSize;e.height(void 0);const a=Math.round(2*t.a.fontSize)-1;for(let r=1;r<a;r++){const r=t.a.height&&e.height()>t.a.height;let n=i.split("\n").join(" ").split(/[\s-]+/).reduce(((e,t)=>isNonSpaceSeparatedLanguage(t)?e.concat(t.split("")):e.concat(t)),[]),a=e.textArr.map((e=>e.text)).join(";");const l=n.find((e=>!a.includes(e)||(a=a.replace(e,""),!1)));if(!(r||l))break;o-=.5,e.fontSize(o)}return e.fontSize(r),e.height(n),o}function generateBackgroundShape({lines:e,lineHeight:t,width:r,align:n="left",padding:i=0,cornerRadius:o=0}){var a;e.forEach(((e,t)=>{e.cx=r/2,"right"===n?e.cx=r-e.width/2:"left"===n&&(e.cx=e.width/2),"justify"!==n||e.lastInParagraph||(e.width=r),"justify"===n&&(e.cx=e.width/2)}));let l=`M ${null===(a=e[0])||void 0===a?void 0:a.cx} ${-i}`;e.forEach(((r,n)=>{const{cx:o}=r,a=e[n-1];a&&a.width>r.width?l+=` L ${o+r.width/2+i} ${n*t+i}`:l+=` L ${o+r.width/2+i} ${n*t-i}`;const s=e[n+1];s&&s.width>r.width?l+=` L ${o+r.width/2+i} ${(n+1)*t-i}`:l+=` L ${o+r.width/2+i} ${(n+1)*t+i}`}));for(var s=e.length-1;s>=0;s--){const r=e[s],{cx:n}=r,o=e[s+1];o&&o.width>r.width?l+=` L ${n-r.width/2-i} ${(s+1)*t-i}`:l+=` L ${n-r.width/2-i} ${(s+1)*t+i}`;const a=e[s-1];a&&a.width>r.width?l+=` L ${n-r.width/2-i} ${s*t+i}`:l+=` L ${n-r.width/2-i} ${s*t-i}`}l+=" Z";const u=(0,svg_round_corners_1.parsePath)(l);return(0,svg_round_corners_1.roundCommands)(u,o).path}exports.getLineHeight=getLineHeight,exports.usePrevious=usePrevious,exports.TextElement=(0,mobx_react_lite_1.observer)((({element:e,store:t})=>{const r=react_1.default.useRef(null),n=react_1.default.useRef(null),{editorEnabled:i,selectAll:o}=useEditor(e),[a,l]=react_1.default.useState(!1),[s,u]=react_1.default.useState(!1),d=react_1.default.useRef(e.a.height),c=t.selectedElements.indexOf(e)>=0,{textVerticalResizeEnabled:f}=flags_1.flags,h=usePrevious(e.fontFamily),[g,_]=react_1.default.useState([]);react_1.default.useEffect((()=>{var e,t;const n=null!==(t=null===(e=r.current)||void 0===e?void 0:e.textArr)&&void 0!==t?t:[];JSON.stringify(n)!==JSON.stringify(g)&&_(n)})),react_1.default.useEffect((()=>{if(e.a.width)return;const t=r.current;t.width(600),e.set({width:1.4*t.getTextWidth()})}),[]),react_1.default.useLayoutEffect((()=>(0,mobx_1.autorun)((()=>{const t=r.current;(0,apply_filters_1.applyFilter)(t,e)}))));const[x]=(0,exports.useFontLoader)(t,e.fontFamily),p=(0,text_1.removeTags)(e.text),m=()=>{const e=r.current.clone({height:void 0}),t=Math.ceil(e.fontSize()*e.lineHeight()*e.textArr.length+1);return e.destroy(),t};react_1.default.useLayoutEffect((()=>{if(!x)return;const{textOverflow:n}=flags_1.flags;if(e.a.height)if("change-font-size"!==n||s||t.isPlaying){if("resize"===n){const n=m();f&&e.a.height<n&&t.history.ignore((()=>{var t;(0,mobx_state_tree_1.isAlive)(e)&&e.set({height:n}),null===(t=r.current)||void 0===t||t.height(n)}),!1,!0),f||e.a.height===n||t.history.ignore((()=>{var t;(0,mobx_state_tree_1.isAlive)(e)&&e.set({height:n}),null===(t=r.current)||void 0===t||t.height(n)}),!1,!0)}}else{const n=findFitFontSize(r.current,e);if(n!==e.a.fontSize)return void t.history.ignore((()=>{e.set({fontSize:n})}),!1,!0);const i=m();e.a.height===i||f||t.history.ignore((()=>{e.set({height:i})}),!1,!0)}else{const r=m();t.history.ignore((()=>{e.set({height:r})}),!1,!0)}})),react_1.default.useLayoutEffect((()=>{const t=r.current;t&&(t.width(t.width()+1e-8),t._setTextData(),(0,apply_filters_1.applyFilter)(t,e))}),[x]);const v=react_1.default.useRef(null),w=react_1.default.useRef(0),y=r=>{r.evt.preventDefault();const n=t.selectedShapes.find((t=>t===e));n&&e.contentEditable&&(w.current=getCursorPosition(r),e.toggleEditMode())},S=!p&&e.placeholder?.6:e.a.opacity;(0,use_fadein_1.useFadeIn)(r,S);const b=(0,exports.getLineHeight)({fontLoaded:x,fontFamily:e.fontFamily,fontSize:e.a.fontSize,lineHeight:e.lineHeight}),E=e.selectable||"admin"===t.role,L=(0,use_color_1.useColor)(e),z=react_1.default.useMemo((()=>e.backgroundEnabled?generateBackgroundShape({lines:JSON.parse(JSON.stringify(g)),cornerRadius:e.backgroundCornerRadius*(e.a.fontSize*b*.5),lineHeight:b*e.a.fontSize,padding:e.backgroundPadding*(e.a.fontSize*b*.5),width:e.a.width,align:e.align}):""),[e.backgroundEnabled,e.backgroundCornerRadius,e.a.fontSize,b,e.backgroundPadding,e.a.width,e.align,g]),T=(0,screen_1.useMobile)();let F=0;return"middle"===e.verticalAlign?F=(e.a.height-g.length*b*e.a.fontSize)/2:"bottom"===e.verticalAlign&&(F=e.a.height-g.length*b*e.a.fontSize),react_1.default.createElement(react_1.default.Fragment,null,react_1.default.createElement(react_konva_1.Path,{ref:n,x:e.a.x,y:e.a.y,rotation:e.a.rotation,hideInExport:!e.showInExport,listening:!1,visible:e.backgroundEnabled,opacity:e.backgroundOpacity*S,data:z,fill:e.backgroundColor,offsetY:-F}),react_1.default.createElement(react_konva_1.Text,Object.assign({ref:r,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:p||e.placeholder},L,{stroke:e.stroke,lineJoin:"round",strokeWidth:e.strokeWidth,fillAfterStrokeEnabled:!0,fontSize:e.a.fontSize,fontFamily:`"${e.fontFamily}", "${h}"`,fontStyle:e.fontStyle+" "+e.fontWeight,textDecoration:e.textDecoration,align:e.align,verticalAlign:e.verticalAlign,draggable:T?e.draggable&&c:e.draggable,preventDefault:!T||c,opacity:S,visible:!e._editModeEnabled,ellipsis:"ellipsis"===flags_1.flags.textOverflow,shadowEnabled:e.shadowEnabled,shadowBlur:e.shadowBlur,shadowOffsetX:e.shadowOffsetX,shadowOffsetY:e.shadowOffsetY,shadowColor:e.shadowColor,shadowOpacity:e.shadowOpacity,lineHeight:b,letterSpacing:e.letterSpacing*e.a.fontSize,listening:E,onDragMove:t=>{e.set({x:t.target.x(),y:t.target.y()})},onDragEnd:t=>{e.set({x:t.target.x(),y:t.target.y()})},onMouseEnter:()=>{l(!0)},onMouseLeave:()=>{l(!1)},onClick:y,onTap:y,onTransformStart:()=>{u(!0),d.current=r.current.height()},onTransform:t=>{var r,i;const o=t.target;null===(r=n.current)||void 0===r||r.setAttrs({x:o.x(),y:o.y(),rotation:o.rotation(),scale:o.scale()});const a=(null===(i=o.getStage())||void 0===i?void 0:i.findOne("Transformer")).getActiveAnchor();if("middle-left"===a||"middle-right"===a){const t=o.scaleX(),r=o.width()*t,n=e.a.fontSize;let i=r;r<n&&(i=n,v.current&&o.position(v.current)),o.width(i),o.scaleX(1),o.scaleY(1);const a=m();if("ellipsis"!==flags_1.flags.textOverflow){const t=Math.max(a,d.current);o.height(t),e.set({height:o.height()})}e.set({x:o.x(),y:o.y(),width:o.width(),rotation:o.rotation()}),(0,apply_filters_1.applyFilter)(o,e)}if("top-center"===a||"bottom-center"===a){let r="resize"===flags_1.flags.textOverflow?m():b*e.a.fontSize;t.target.height(Math.max(r,t.target.height()*t.target.scaleY())),t.target.scaleY(1)}v.current=t.target.position()},onTransformEnd:t=>{var r;const i=t.target.scaleX();t.target.scaleX(1),t.target.scaleY(1),e.set({fontSize:Math.round(e.a.fontSize*i),width:Math.ceil(t.target.width()*i),x:t.target.x(),y:t.target.y(),rotation:t.target.rotation(),height:t.target.height()*i,shadowBlur:e.shadowBlur*i,shadowOffsetX:e.shadowOffsetX*i,shadowOffsetY:e.shadowOffsetY*i,strokeWidth:e.strokeWidth*i}),null===(r=n.current)||void 0===r||r.setAttrs({scaleX:1,scaleY:1}),u(!1)}})),i&&react_1.default.createElement(react_konva_1.Group,{x:e.a.x,y:e.a.y,rotation:e.a.rotation},react_1.default.createElement(TextInput,{textNodeRef:r,element:e,selectAll:o,cursorPosition:w.current,onBlur:()=>{e.toggleEditMode(!1)}})),!s&&(a||c)&&react_1.default.createElement(highlighter_1.Highlighter,{element:e}))}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polotno",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.3",
|
|
4
4
|
"description": "Design Editor Framework",
|
|
5
5
|
"author": "Anton Lavrenov",
|
|
6
6
|
"keywords": [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"functions-have-names": "^1.2.3",
|
|
18
18
|
"gradient-parser": "^1.0.2",
|
|
19
19
|
"konva": "^9.3.11",
|
|
20
|
-
"mobx": "6.12.
|
|
20
|
+
"mobx": "6.12.4",
|
|
21
21
|
"mobx-react-lite": "^4.0.7",
|
|
22
22
|
"mobx-state-tree": "6.0.0",
|
|
23
23
|
"nanoid": "3.3.4",
|
|
@@ -66,12 +66,12 @@
|
|
|
66
66
|
"@types/jest": "^29",
|
|
67
67
|
"@types/react": "^18.3.3",
|
|
68
68
|
"@types/sanitize-html": "^2.11.0",
|
|
69
|
-
"@vitest/browser": "^
|
|
69
|
+
"@vitest/browser": "^1.6.0",
|
|
70
70
|
"assert": "^2.1.0",
|
|
71
71
|
"buffer": "^6.0.3",
|
|
72
72
|
"canvas": "^2.11.2",
|
|
73
73
|
"jest-file-snapshot": "^0.5.0",
|
|
74
|
-
"jsdom": "^
|
|
74
|
+
"jsdom": "^24.1.0",
|
|
75
75
|
"parcel": "^2.12.0",
|
|
76
76
|
"path-browserify": "^1.0.1",
|
|
77
77
|
"process": "^0.11.10",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"ts-jest": "^29",
|
|
86
86
|
"typescript": "^5.4.5",
|
|
87
87
|
"uglifyjs-folder": "^3.3.0",
|
|
88
|
-
"vitest": "^
|
|
88
|
+
"vitest": "^1.6.0",
|
|
89
89
|
"webdriverio": "^8.38.2"
|
|
90
90
|
},
|
|
91
91
|
"homepage": "https://polotno.com/",
|