UNPKG

bandicoot

Version:

React rich text editor

3 lines (2 loc) 19.1 kB
(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?b(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],b):(a=a||self,b(a.bandicoot={},a.React))})(this,function(a,b){'use strict';function c(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function d(a){for(var b,d=1;d<arguments.length;d++)b=null==arguments[d]?{}:arguments[d],d%2?c(Object(b),!0).forEach(function(c){e(a,c,b[c])}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(b)):c(Object(b)).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))});return a}function e(a,b,c){return b=h(b),b in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function f(){return f=Object.assign?Object.assign.bind():function(a){for(var b,c=1;c<arguments.length;c++)for(var d in b=arguments[c],b)Object.prototype.hasOwnProperty.call(b,d)&&(a[d]=b[d]);return a},f.apply(this,arguments)}function g(a,b){if("object"!=typeof a||null===a)return a;var c=a[Symbol.toPrimitive];if(c!==void 0){var d=c.call(a,b||"default");if("object"!=typeof d)return d;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===b?String:Number)(a)}function h(a){var b=g(a,"string");return"symbol"==typeof b?b:b+""}function i(){const a=b.useRef(null),[c,d]=b.useState(!1);return{isFocused:function(){return a.current},setFocused:function(b){a.current=b,d(!c)}}}function j(a){const c=b.useContext(v);return{performCommand(b){c.selectRangeFromBeforeBlur(),document.execCommand(a)},performCommandWithValue(b){c.selectRangeFromBeforeBlur();document.execCommand(a,null,b)}}}function k(a,c){function d(){const b=document.queryCommandValue(a),d=c?c===b:document.queryCommandState(a);(d!==f.isActive||b!==f.value)&&g({isActive:d,value:b})}function e(){g(y)}const[f,g]=b.useState(y),h=b.useContext(v);return b.useEffect(()=>(h.addSelectionChangedListener(d),()=>h.removeSelectionChangedListener(d)),[f,g]),b.useEffect(()=>(h.addBlurListener(e),()=>h.removeBlurListener(e)),[f,g]),{isActive:f.isActive,activeValue:f.value}}function l(a,b){b(URL.createObjectURL(a))}function m(a){const b=document.createRange();b.setStartAfter(a);const c=window.getSelection();c.removeAllRanges(),c.addRange(b)}function n(a){let{text:b,referenceEl:d,fontFamily:e,fillStyle:f,fontWeight:g,textBottom:h}=a;const i=window.getComputedStyle(d),j=+i.fontSize.replace("px",""),k=+i.lineHeight.replace("px",""),l=e||i.fontFamily,m="".concat(g||"normal"," ").concat(j,"px ").concat(l),n=document.createElement("div");n.style.font=m,n.style.position="absolute",n.style.visibility="hidden",n.style.whiteSpace="nowrap",n.textContent=b,document.body.appendChild(n);const o=document.createElement("canvas");o.width=n.clientWidth+1,o.height=k;const p=o.getContext("2d");p.font=m,p.fillStyle=f||J.fillStyle,p.textBaseline="bottom";return p.fillText(b,0,h||k-3),document.body.removeChild(n),p.canvas.toDataURL()}function o(a,b,c){a.style.verticalAlign="bottom",a.dataset.textAsImage=b,a.style.backgroundColor=c||J.backgroundColor,a.addEventListener("click",b=>{const c=a.getBoundingClientRect(),d=c.left+c.width/2,e=document.createRange();b.x<d?e.setStartBefore(a):e.setStartAfter(a);const f=window.getSelection();f.removeAllRanges(),f.addRange(e)})}function p(){let a=getSelection().getRangeAt(0).commonAncestorContainer;return 1===a.nodeType?a:a.parentElement}function q(a){return s.createElement("button",f({},a,{className:"\n ".concat(K.bandicootButton,"\n ").concat(a.isActive?"active-control-button":"","\n ").concat(a.className||"","\n "),onClick:a.onClick}),a.children)}function r(a){return s.createElement("svg",{width:a.width,height:a.height,xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",viewBox:"0 0 317.41 317.41"},s.createElement("path",{d:"M281.4 158.7c21.7-15.1 36-40.3 36-68.7 0-46.2-37.6-83.7-83.7-83.7h-40H115 45 0v30h45v245H0v30h45 70 78.7 40c46.2 0 83.8-37.6 83.8-83.7C317.4 199 303.2 173.9 281.4 158.7zM193.7 36.2c29.6 0 53.8 24.1 53.8 53.8s-24.1 53.8-53.7 53.8H115v-107.5H193.7zM115 173.7h78.7c29.6 0 53.8 24.1 53.8 53.8s-24.1 53.8-53.7 53.8H115V173.7z"}))}var s="default"in b?b["default"]:b;const t=()=>{},u={addSelectionChangedListener:t,removeSelectionChangedListener:t,fireSelectionChanged:t,selectRangeFromBeforeBlur:t,getRangeBeforeBlur:t,addBlurListener:t,removeBlurListener:t,fireBlur:t,addNewHTMLListener:t,removeNewHTMLListener:t,fireNewHTML:t,isFocused:t,getContentEditableElement:t,numSerializers:()=>0,addSerializer:t,removeSerializer:t,serialize:t,sanitizeHTML:t},v=s.createContext(u);let w=0;const x=b.forwardRef((a,c)=>{function e(b){b.preventDefault(),b.stopPropagation();const c=b.clipboardData||window.clipboardData,d=!c.types.includes("text/html"),e=c.getData(d?"text":"text/html");let f=q.sanitizeHTML(e,"pasteHTML"),g=a.pasteFn(f);!1!==g&&document.execCommand(d?"insertText":"insertHTML",null,g)}function f(){g(),document.execCommand("removeFormat"),document.execCommand("delete")}function g(a){const b=document.createRange();b.selectNodeContents(r.current),a&&b.collapse(!1);const c=window.getSelection();c.removeAllRanges(),c.addRange(b)}function h(){if(u()){const a=window.getSelection();0<a.rangeCount&&(t.current=window.getSelection().getRangeAt(0)),q.fireSelectionChanged()}}function j(){const b=n();b!==z&&(A(b),a.save(b))}function k(){var a;let b=(null===r||void 0===r||null===(a=r.current)||void 0===a?void 0:a.innerHTML)||"";if(0<q.numSerializers()){const a=new DOMParser().parseFromString(b,"text/html");b=q.serialize(a.body)}return b}function l(b,c){c?(r.current.innerHTML=q.sanitizeHTML(b,"setHTML"),a.autoFocus&&o()):(f(),r.current.innerHTML=q.sanitizeHTML(b,"setHTML"),o()),q.fireNewHTML()}function m(){l("")}function n(){return q.sanitizeHTML(k(),"getHTML")}function o(){g(!0),x(!0)}function p(){return!window.chrome||!window.chrome.webstore&&!window.chrome.runtime?{opacity:"0.54"}:{color:"rgb(117, 117, 117)"}}if("function"!=typeof a.sanitizeHTML)throw Error("RichTextEditor must be passed a sanitizeHTML function as a prop");const q=b.useContext(v);q.sanitizeHTML=a.sanitizeHTML;const r=b.useRef(null),t=b.useRef(null),{isFocused:u,setFocused:x}=i(),y=b.useRef(w++),[z,A]=b.useState(()=>q.sanitizeHTML(a.initialHTML,"initialSetLastSavedHTML")),[B,C]=b.useState(!1);if(c){const a={setHTML:l,resetEditor:m,getHTML:n,focus:o};"function"==typeof c?c({current:a}):c.current=a}b.useLayoutEffect(()=>(r.current.addEventListener("paste",e),()=>r.current.removeEventListener("paste",e)),[a.pasteFn]),b.useLayoutEffect(()=>(document.addEventListener("selectionchange",h),()=>document.removeEventListener("selectionchange",h)),[q.fireSelectionChanged]),b.useEffect(()=>{if(r.current)for(let a=r.current;a.parentNode;)a=a.parentNode,"SPAN"===a.tagName&&console.warn("A span tag has been detected in the parents of <RichTextEditor>. This has been known to cause issues. https://github.com/CanopyTax/bandicoot/issues/69")},[r.current]),b.useEffect(()=>{if(a.save&&a.unchangedInterval&&r.current&&u()){let b;const c=new MutationObserver(()=>{clearTimeout(b),b=setTimeout(j,a.unchangedInterval)});return c.observe(r.current,{attributes:!0,childList:!0,subtree:!0,characterData:!0}),()=>{c.disconnect(),clearTimeout(b)}}},[a.unchangedInterval,a.save,r.current,u()]),b.useEffect(()=>{if(!1===u()){const a=setTimeout(()=>{q.fireBlur(),j()},100);return()=>{clearTimeout(a)}}},[u()]),b.useEffect(()=>{q.selectRangeFromBeforeBlur=function(){let a=0<arguments.length&&arguments[0]!==void 0?arguments[0]:{usePreviousRange:!1};if(r.current&&document.activeElement!==r.current&&!r.current.contains(document.activeElement)){if(a.usePreviousRange&&t.current){const a=window.getSelection();a.removeAllRanges(),a.addRange(t.current)}else r.current.focus();x(!0),setTimeout(h)}},q.getRangeFromBeforeBlur=()=>t.current,q.isFocused=u,q.getContentEditableElement=()=>r.current}),b.useEffect(()=>{!B&&a.initialHTML&&(C(!0),l(a.initialHTML,!0))},[B,l,q]),b.useEffect(()=>{if(a.placeholder){const b=document.createElement("style");b.textContent=".bandicoot-id-".concat(y.current,":empty:before { content: attr(data-placeholder); }"),document.head.appendChild(b);const c=Array.prototype.slice.call(document.styleSheets).find(a=>a.ownerNode===b);if(c){const b=c.cssRules[0].style,d=a.placeholderStyle?a.placeholderStyle:p();for(let c in d)b[c]=a.placeholderStyle?a.placeholderStyle[c]:d[c]}return()=>b.parentNode.removeChild(b)}},[a.placeholder,a.placeholderStyle,y.current]);const D=a.style||{};return s.createElement("div",{contentEditable:!a.disabled,onBlur:()=>x(!1),onFocus:function(){x(!0);const a=window.getSelection();0<a.rangeCount&&(t.current=a.getRangeAt(0))},onInput:a.onInput,onKeyDown:a.onKeyDown,ref:r,className:a.className+" bandicoot-id-"+y.current,style:d({wordBreak:"break-word",wordWrap:"break-word",overflowWrap:"break-word"},D),"data-placeholder":a.placeholder,tabIndex:a.tabIndex})});x.defaultProps={className:"",initialHTML:"",save:()=>{},placeholder:"",pasteFn:a=>a};const y={isActive:!1,value:!1},z=()=>{},A=".jpg, .png, image/*",B={processImgElement:z,fileBlobToUrl:l,acceptImgTypes:A};let C=0;const D=()=>{},E={processAnchorElement:D};let F=0;const G=()=>{},H={processContentEditableFalseElement:G},I=()=>{},J={processSerializedElement:I,fontFamily:null,fillStyle:"#00bf4b",fontWeight:"bold",textBottom:null,backgroundColor:"transparent"};var K={bandicootButton:"icon-button_bandicootButton__2IZP5"};(function(a,b){void 0===b&&(b={});var c=b.insertAt;if(a&&"undefined"!=typeof document){var d=document.head||document.getElementsByTagName("head")[0],e=document.createElement("style");e.type="text/css","top"===c?d.firstChild?d.insertBefore(e,d.firstChild):d.appendChild(e):d.appendChild(e),e.styleSheet?e.styleSheet.cssText=a:e.appendChild(document.createTextNode(a))}})(".icon-button_bandicootButton__2IZP5 {\n background-color: transparent;\n border: none;\n border-radius: 4px;\n}\n.icon-button_bandicootButton__2IZP5:hover {\n transition: background-color .25s ease-in-out;\n background-color: rgba(0, 0, 0, 0.05);\n}\n.icon-button_bandicootButton__2IZP5 svg {\n fill: currentcolor;\n}"),r.defaultProps={width:24,height:24},a.BoldButton=function(a){const{performCommand:b}=j("bold"),{isActive:c}=k("bold");return s.createElement(q,{onClick:b,isActive:c},s.createElement(r,a))},a.RichTextContainer=function(a){const c=b.useRef(Object.assign({},u)),d=c.current,e=b.useRef([]),f=b.useRef([]),g=b.useRef([]),h=b.useRef([]);return b.useEffect(()=>{const a=d.getContentEditableElement();a&&a.innerHTML&&d.fireNewHTML()},[d]),d.addSelectionChangedListener=b.useCallback(a=>{e.current.push(a)},[]),d.removeSelectionChangedListener=b.useCallback(a=>{e.current=e.current.filter(b=>b!==a)},[]),d.fireSelectionChanged=b.useCallback(()=>{e.current.forEach(a=>a())},[]),d.addBlurListener=b.useCallback(a=>{f.current.push(a)},[]),d.removeBlurListener=b.useCallback(a=>{f.current=f.current.filter(b=>b!==a)},[]),d.fireBlur=b.useCallback(()=>{f.current.forEach(a=>a())},[]),d.addNewHTMLListener=b.useCallback(a=>{g.current.push(a)},[]),d.removeNewHTMLListener=b.useCallback(a=>{g.current=g.current.filter(b=>b!==a)},[]),d.fireNewHTML=b.useCallback(()=>{g.current.forEach(a=>a())},[]),d.numSerializers=b.useCallback(()=>h.current.length,[]),d.addSerializer=b.useCallback(a=>{h.current.push(a)},[]),d.removeSerializer=b.useCallback(a=>{h.current=h.current.filter(b=>b!==a)},[]),d.serialize=b.useCallback(a=>(h.current.forEach(b=>b(a)),a.innerHTML),[]),s.createElement(v.Provider,{value:d},a.children)},a.RichTextContext=v,a.RichTextEditor=x,a.useContentEditableFalse=function(){function a(a){if(a.removeAttribute("id"),a.contentEditable=!1,a.addEventListener("click",()=>m(a)),!a.previousSibling&&a.parentElement===e.getContentEditableElement()){const b=document.createElement("span");a.parentElement.insertBefore(b,a)}if(!a.nextSibling&&a.parentElement===e.getContentEditableElement()){const b=document.createElement("span");a.insertAdjacentElement("afterend",b)}m(a),c(a)}let{processContentEditableFalseElement:c=G}=0<arguments.length&&arguments[0]!==void 0?arguments[0]:H;const{performCommandWithValue:d}=j("insertHTML"),e=b.useContext(v);return{insertContentEditableFalseElement(b){const c="rte-ce-false-temp-id-"+F++,f="<span id=\"".concat(c,"\">").concat(e.sanitizeHTML(b,"insertContentEditableFalseHTML"),"</span>");d(f);const g=document.getElementById(c);a(g)}}},a.useDocumentExecCommand=j,a.useDocumentQueryCommandState=k,a.useElementDeletionDetection=function(a,c){const d=b.useContext(v);b.useEffect(()=>{if(a){function b(){a.isConnected||a._bandicoot_delete_callback_called||(a._bandicoot_delete_callback_called=!0,c(a))}return d.addSelectionChangedListener(b),()=>d.removeSelectionChangedListener(b)}},[a,c])},a.useFontSize=function(a){let{defaultFontSize:d="14px",fontSizes:c}=a;if(7<c.length)throw Error("Browsers only support up to 7 font sizes with document.execCommand('fontSize', null, size)");const[e,f]=b.useState(d),[g,h]=b.useState(null),{performCommandWithValue:i}=j("fontSize"),k=b.useContext(v),l=function(){return b.useEffect(()=>{function a(){const a=window.getSelection();if((!g||a.anchorNode!==g.anchorNode||a.anchorOffset!==g.anchorOffset||a.focusNode!==g.focusNode||a.focusOffset!==g.focusOffset)&&(h({anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),0<a.rangeCount)){let b=a.getRangeAt(0).startContainer;1!==b.nodeType&&(b=b.parentElement);const c=window.getComputedStyle(b).fontSize,d=c;d!==e&&f(d)}}return k.addSelectionChangedListener(a),()=>k.removeSelectionChangedListener(a)},[e,f,g]),e}();return function(){b.useEffect(()=>{const a=c.reduce((a,b,c)=>"".concat(a," font[size=\"").concat(c+1,"\"] {font-size: ").concat(b,"}"),""),b=document.createElement("style");return b.textContent=a,document.head.appendChild(b),()=>document.head.removeChild(b)},[c]),b.useEffect(()=>{function a(a){const b=a.querySelectorAll("font");for(let d=0;d<b.length;d++){const a=b[d],e=+a.getAttribute("size");if(e>c.length)throw Error("Cannot find fontSize for integer size '".concat(e,"'"));const f=c[e-1];a.removeAttribute("size"),a.style.fontSize=f,a.dataset.integerSize=e}}return k.addSerializer(a),()=>k.removeSerializer(a)},[c]),b.useEffect(()=>{function a(){const a=k.getContentEditableElement().querySelectorAll("font");for(let b=0;b<a.length;b++){const d=a[b],e=d.style.fontSize,f=c.findIndex(a=>a===e)+1;0<f&&(d.style.fontSize="",d.setAttribute("size",f))}}return k.addNewHTMLListener(a),()=>k.removeNewHTMLListener(a)},[c])}(),{currentlySelectedFontSize:l,setSize(a){const b=c.findIndex(b=>b===a)+1;if(0>=b)throw Error("Cannot set font size since '".concat(a,"' was not passed in the fontSizes array"));f(a),i(b)}}},a.useFormatBlock=function(){const{performCommandWithValue:a}=j("formatBlock");return{formatBlock(b){b===document.queryCommandValue("formatBlock")?a("div"):a(b)}}},a.useImage=function(){function a(a){a.style.cursor="pointer",a.style.maxWidth="100%",d(a)}function c(a){a.querySelectorAll("img").forEach(a=>{k.current[a.src]&&(a.src=k.current[a.src])})}let{processImgElement:d=z,fileBlobToUrl:e=l,acceptImgTypes:f=A}=0<arguments.length&&void 0!==arguments[0]?arguments[0]:B;const{performCommandWithValue:g}=j("insertImage"),h=b.useContext(v),i=b.useRef(null),k=s.useRef({});return function(){b.useEffect(()=>{function b(){const b=h.getContentEditableElement().querySelectorAll("img:not([data-text-as-image])");b.forEach(a)}return h.addNewHTMLListener(b),()=>h.removeNewHTMLListener(b)},[d])}(),function(){b.useEffect(()=>{i.current=document.createElement("input");const b=i.current;b.type="file",b.accept=f,b.multiple=!1,b.addEventListener("change",()=>{b.files&&0<b.files.length&&e(b.files[0],c=>{g(c);const d=document.querySelector("img[src=\"".concat(c,"\"]"));if(d.src&&d.src.startsWith("blob:")){const a=new FileReader;a.addEventListener("load",()=>{k.current[d.src]=a.result}),a.readAsDataURL(b.files[0])}a(d)})})},[e,d,f])}(),function(){b.useEffect(()=>(h.addSerializer(c),()=>h.removeSerializer(c)))}(),{chooseFile(a){i.current.click()},removeImage(a){const b=document.createRange();b.selectNode(a);const c=window.getSelection();c.removeAllRanges(),c.addRange(b),document.execCommand("delete")}}},a.useLink=function(){function a(a,b){d.selectRangeFromBeforeBlur({usePreviousRange:!0});const e="rte-link-temp-id-".concat(C++);f("<a href=\"".concat(a,"\" id=\"").concat(e,"\" target=\"_blank\" rel=\"noopener noreferrer\">").concat(b,"</a>"));const g=document.getElementById(e);g.removeAttribute("id"),c(g)}let{processAnchorElement:c=D}=0<arguments.length&&void 0!==arguments[0]?arguments[0]:E;const d=b.useContext(v),{performCommand:e}=j("unlink"),{performCommandWithValue:f}=j("insertHTML");return function(){b.useEffect(()=>{function a(){const a=d.getContentEditableElement().querySelectorAll("a");a.forEach(c)}return d.addNewHTMLListener(a),()=>d.removeNewHTMLListener(a)},[c])}(),{getTextFromBeforeBlur:function(){const a=d.getRangeFromBeforeBlur();return a?a.toString():null},selectEntireLink:function(a){const b=document.createRange();b.selectNodeContents(a);const c=window.getSelection();c.removeAllRanges(),c.addRange(b)},unlink:function(){e(),(window.navigator.userAgent.includes("Edge/14")||window.navigator.userAgent.includes("Edge/15")||window.navigator.userAgent.includes("Edge/16")||window.navigator.userAgent.includes("Edge/17"))&&document.execCommand("removeFormat")},insertLink:a}},a.useTextAsImage=function(){let{processSerializedElement:g=I,fontFamily:a,fillStyle:c,fontWeight:d,textBottom:e,backgroundColor:f}=0<arguments.length&&void 0!==arguments[0]?arguments[0]:J;const{performCommandWithValue:h}=j("insertImage"),i=b.useContext(v);return function(){b.useEffect(()=>{function b(){const b=i.getContentEditableElement().querySelectorAll("span[data-text-as-image]");for(let g=0;g<b.length;g++){const h=b[g],i=n({text:h.dataset.textAsImage,referenceEl:h.previousElementSibling||h.nextElementSibling||h.parentElement,fontFamily:a,fontWeight:d,fillStyle:c,textBottom:e}),j=document.createElement("img");j.src=i,o(j,h.dataset.textAsImage,f),h.parentNode.replaceChild(j,h)}}return i.addNewHTMLListener(b),()=>i.removeNewHTMLListener(b)})}(),function(){b.useEffect(()=>{function a(a){const b=a.querySelectorAll("img[data-text-as-image]");for(let c=0;c<b.length;c++){const a=b[c],d=document.createElement("span");d.dataset.textAsImage=a.dataset.textAsImage,g(d,d.dataset.textAsImage),a.parentNode.replaceChild(d,a)}}return i.addSerializer(a),()=>i.removeSerializer(a)},[])}(),{insertTextAsImage(b){i.selectRangeFromBeforeBlur({usePreviousRange:!0});const g=n({text:b,referenceEl:p(),fontFamily:a,fontWeight:d,fillStyle:c,textBottom:e});h(g);const j=document.querySelector("img[src=\"".concat(g,"\"]:not([data-text-as-image])"));o(j,b,f)}}},Object.defineProperty(a,"__esModule",{value:!0})}); //# sourceMappingURL=bandicoot.umd.js.map