{t.addEventListener("mousedown",t=>{t.preventDefault()})}),this.container.addEventListener("click",t=>{const e=t.target.closest("button");if(e){const t=e.getAttribute("data-action");t&&this.emit("toolbarAction",t)}})}updateActiveStates(t){if(this.container.querySelectorAll("button").forEach(e=>{const n=e.getAttribute("data-action");let i=!1;"bold"===n&&t.bold&&(i=!0),"italic"===n&&t.italic&&(i=!0),"underline"===n&&t.underline&&(i=!0),"strikethrough"===n&&t.strikethrough&&(i=!0),"hyperlink"===n&&t.hyperlink&&(i=!0),"undo"===n&&t.undo&&(i=!0),"redo"===n&&t.redo&&(i=!0),e.classList.toggle("active",i)}),this.container.querySelectorAll("select").forEach(e=>{const n=e.getAttribute("data-action");"fontFamily"===n&&t.fontFamily&&(e.value=t.fontFamily),"fontSize"===n&&t.fontSize&&(e.value=t.fontSize)}),t.fontColor){const e=document.getElementById("fontColorPicker");e&&(e.value=t.fontColor,e.dispatchEvent(new Event("input",{bubbles:!0})))}if(t.bgColor){const e=document.getElementById("bgColorPicker");e&&(e.value=t.bgColor,e.dispatchEvent(new Event("input",{bubbles:!0})))}}}const u={TOOLBAR_CLASSNAME:"toolbar",TOOLBAR_ID:"toolbar",EDITOR_CLASSNAME:"editor",EDITOR_ID:"editor",EDITOR_ELEMENT_NT_FOUND:"Editor element not found or incorrect element type.",FONT_FAMILY_SELECT_ID:"fontFamily",FONT_SIZE_SELECT_ID:"fontSize",FONT_COLOR_WRAPPER_ID:"fontColorWrapper",FONT_COLOR_ID:"fontColor",FONT_COLOR_PICKER_WRAPPER_ID:"colorWrapper",FONT_COLOR_PICKER_ID:"fontColorPicker",FONT_COLOR_RESET_ID:"colorResetFont",BG_COLOR_WRAPPER_ID:"bgColorWrapper",BG_COLOR_ID:"bgColor",BG_COLOR_PICKER_WRAPPER_ID:"colorBgWrapper",BG_COLOR_RESET_ID:"colorResetBG",BG_COLOR_PICKER_ID:"bgColorPicker",GET_HTML_BUTTON_ID:"getHtmlButton",LOAD_HTML_BUTTON_ID:"loadHtmlButton",HYPERLINK_CONTAINER_ID:"hyperlink-container",HYPERLINK_INPUT_ID:"hyperlink-input",HYPERLINK_PLACEHOLDER:"Enter a URL...",HYPERLINK_APPLY_BTN_ID:"apply-hyperlink",HYPERLINK_CANCEL_BTN_ID:"cancel-hyperlink",VIEW_HYPERLINK_CONTAINER_ID:"hyperlink-container-view",VIEW_HYPERLINK_LABEL_ID:"hyperlink-view-span",VIEW_HYPERLINK_ANCHOR_ID:"hyperlink-view-link",TEMPORARY_SELECTION_HIGHLIGHT_CLASS:"temporary-selection-highlight",PARAGRAPH_BLOCK_CLASS:"paragraph-block",IMAGE_CROSS_CLASS:"image-cross",TEST_HTML_CODE:' ajsh diujaksdajsh diujaksdajsh
diujaksdasd 98hasiudasdh 98
This is a t this is a test work
This is a test work. this is a test work
da90 uasd y98asiodoiasda90 uasd y98asiodoiasda90 uasd y98asioda
sdjasdjasdja9sudoija9sudoija9sudoija90sdoa90sdoa90sdo
',TEST_BLOG_POST_HTML_CODE:'Blog Post Title
Start writing your post here...
',TEST_NEWSLATER_HTML_CODE:'Weekly Newsletter
Hello subscribers,
',TEST_RESUME_HTML_CODE:'John Doe
Experience
• Role 1
',TEST_EMAIL_HTML_CODE:'Subject: Important Update
Hi Team,
',TEST_MEETING_HTML_CODE:'Meeting Minutes
Attendees:
Action Items:
',POPUP_TOOLBAR_CLASSNAME:"popup-toolbar",POPUP_TOOLBAR_ID:"popup-toolbar",TOAST_ID:"ti-toast",TOAST_SHOW_CLASS:"ti-toast--show",TOAST_DEFAULT_MESSAGE:"HTML copied to clipboard",TOAST_DEFAULT_DURATION_MS:2e3};class p{constructor(t,e,n){this.savedSelection=null,this.clickOutsideHandler=null,this.editorContainer=t,this.editorView=e,this.document=n}setUndoRedoManager(t){this.undoRedoManager=t}hanldeHyperlinkClick(t,e,n,i,o){const s=this.getCommonHyperlinkInRange(t,e,n,i,o);this.showHyperlinkInput(s)}getCommonHyperlinkInRange(t,e,n,i,o){let s=n,l=0;i&&(l=o.findIndex(t=>t.dataId===i));const r=o[l].pieces;let a=null;for(let n of r){const i=s+n.text.length;if(i>t&&s0){const t=c.getRangeAt(0);let o=null;if(t&&"function"==typeof t.getBoundingClientRect)o=t.getBoundingClientRect();else if(t&&"function"==typeof t.getClientRects){const n=null===(e=t.getClientRects)||void 0===e?void 0:e.call(t);o=n&&n.length?n[0]:null}(!o||Number.isNaN(o.top)&&Number.isNaN(o.left))&&(o=this.editorView.container.getBoundingClientRect());const l=(null===window||void 0===window?void 0:window.scrollY)||0,r=(null===window||void 0===window?void 0:window.scrollX)||0;s.style.top=`${(null!==(n=o.bottom)&&void 0!==n?n:o.top)+l+5}px`,s.style.left=`${(null!==(i=o.left)&&void 0!==i?i:0)+r}px`}l.value=t||"",this.savedSelection=o(this.editorView.container),this.highlightSelection(),l.focus(),r.onclick=null,a.onclick=null;const h=this.document.dataIds,u=()=>{const t=d(l.value.trim());t&&this.applyHyperlink(t,h),s.style.display="none"};r.onclick=u,l.onkeydown=t=>{"Enter"===t.key&&(t.preventDefault(),u())},a.onclick=()=>{this.removeHyperlink(h),s.style.display="none"}}}highlightSelection(){this.removeHighlightSelection();const t=window.getSelection();if(t&&t.rangeCount>0){const e=t.getRangeAt(0),n=document.createElement("span");n.className=u.TEMPORARY_SELECTION_HIGHLIGHT_CLASS,n.appendChild(e.extractContents()),e.insertNode(n),t.removeAllRanges();const i=document.createRange();i.selectNodeContents(n),t.addRange(i)}}removeHighlightSelection(){var t;const e=null===(t=this.editorContainer)||void 0===t?void 0:t.querySelectorAll(`span.${u.TEMPORARY_SELECTION_HIGHLIGHT_CLASS}`);null==e||e.forEach(t=>{const e=t.parentNode;if(e){for(;t.firstChild;)e.insertBefore(t.firstChild,t);e.removeChild(t)}})}applyHyperlink(t,e){this.undoRedoManager.saveUndoSnapshot(),this.removeHighlightSelection(),s(this.editorView.container,this.savedSelection);const[n,i]=l(this.editorView);if(n1?this.document.blocks.forEach(t=>{if(e.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let e=0;t.pieces.forEach(t=>{e+=t.text.length});let i=n-e;this.document.formatAttribute(i,e,"hyperlink",o)}}):this.document.formatAttribute(n,i,"hyperlink",o),this.editorView.render();const s=window.getSelection();s&&s.removeAllRanges(),this.editorView.container.focus()}this.savedSelection=null}removeHyperlink(t){this.undoRedoManager.saveUndoSnapshot(),this.removeHighlightSelection(),s(this.editorView.container,this.savedSelection);const[e,n]=l(this.editorView);e1?this.document.blocks.forEach(n=>{if(t.includes(n.dataId)){this.document.selectedBlockId=n.dataId;let t=0;n.pieces.forEach(e=>{t+=e.text.length});let i=e-t;this.document.formatAttribute(i,t,"hyperlink",!1)}}):this.document.formatAttribute(e,n,"hyperlink",!1),this.editorView.render(),s(this.editorView.container,this.savedSelection),this.editorView.container.focus()),this.savedSelection=null}addClickOutsideListener(t){this.removeClickOutsideListener(),this.clickOutsideHandler=e=>{t&&!t.contains(e.target)&&this.hideHyperlinkViewButton()},setTimeout(()=>{document.addEventListener("click",this.clickOutsideHandler)},100)}removeClickOutsideListener(){this.clickOutsideHandler&&(document.removeEventListener("click",this.clickOutsideHandler),this.clickOutsideHandler=null)}showHyperlinkViewButton(t){var e,n,i;const o=document.getElementById(u.VIEW_HYPERLINK_CONTAINER_ID),s=document.getElementById(u.VIEW_HYPERLINK_ANCHOR_ID);if(o&&s){o.style.display="block";const l=window.getSelection();if(l&&l.rangeCount>0){const t=l.getRangeAt(0);let s=null;if(t&&"function"==typeof t.getBoundingClientRect)s=t.getBoundingClientRect();else if(t&&"function"==typeof t.getClientRects){const n=null===(e=t.getClientRects)||void 0===e?void 0:e.call(t);s=n&&n.length?n[0]:null}s||(s=this.editorView.container.getBoundingClientRect());const r=(null===window||void 0===window?void 0:window.scrollY)||0,a=(null===window||void 0===window?void 0:window.scrollX)||0;s&&(o.style.top=`${(null!==(n=s.bottom)&&void 0!==n?n:s.top)+r+5}px`,o.style.left=`${(null!==(i=s.left)&&void 0!==i?i:0)+a}px`)}t&&(s.innerText=t,s.href=d(t))}this.addClickOutsideListener(o)}hideHyperlinkViewButton(){const t=document.getElementById(u.VIEW_HYPERLINK_CONTAINER_ID);t&&(t.style.display="none"),this.removeClickOutsideListener()}}function g(t){return m((new DOMParser).parseFromString(t,"text/html").body,{bold:!1,italic:!1,underline:!1,hyperlink:!1})}function m(t,e){let i=Object.assign({},e);const o=[];if(t instanceof HTMLElement){if("A"===t.tagName){const e=t.getAttribute("href");e&&(i.hyperlink=e)}"STRONG"!==t.tagName&&"B"!==t.tagName||(i.bold=!0),"EM"!==t.tagName&&"I"!==t.tagName||(i.italic=!0),"U"===t.tagName&&(i.underline=!0),t.childNodes.forEach(t=>{o.push(...m(t,i))})}else if(t instanceof Text){const e=t.nodeValue||"";""!==e.trim()&&o.push(new n(e,Object.assign({},i)))}return o}const f={bold:'',italic:'',underline:'',strikethrough:'',subscript:'',superscript:'',left_align:'',center_align:'',right_align:'',justify:'',bullet_list:'',numbered_list:'',insert_table:'',insert_layout:'',heading:'',hyperlink:'',image:'',stop_microphone:' \n \n ',start_microphone:'\n \n ',emoji:''},b={dropdowns:["fontFamily","fontSize"],colors:["fontColor","bgColor"],formatting:["bold","italic","underline","strikethrough"],alignment:["alignLeft","alignCenter","alignRight"],lists:["unorderedList","orderedList"],media:["hyperlink","image","emoji"],utility:["getHtmlContent","loadHtmlContent"]};function y(){const t=document.createElement("div");return t.className="toolbar-separator",t}function k(t,e){const n=u.EDITOR_ID,i=u.TOOLBAR_ID,o=u.POPUP_TOOLBAR_ID,s=["Arial","Times New Roman","Courier New","Verdana"],l=["12px","14px","16px","18px","20px"],r=document.getElementById(t);if(!r)throw new Error(u.EDITOR_ELEMENT_NT_FOUND);r.classList.add("editor-container");const a=document.createElement("div");a.className=u.TOOLBAR_CLASSNAME,a.id=i,r.appendChild(a),(null==e?void 0:e.showToolbar)||(a.style.display="none");const d=document.createElement("div");d.id=n,d.className=u.EDITOR_CLASSNAME,d.contentEditable="true",r.appendChild(d);const c={bold:"B",italic:"I",underline:"U",hyperlink:"🔗",alignLeft:"⇤",alignCenter:"↔",alignRight:"⇥",unorderedList:"•",orderedList:"1.",fontFamily:"fontFamily",fontSize:"fontSize",fontColor:"A",subscript:"X2",superscript:"X2",justify:"⇄",insert_table:"⊢",insert_layout:"❐",heading:"H",image:"📷",colors:"🎨"},h={bold:"Bold (Ctrl+B)",italic:"Italic (Ctrl+I)",underline:"Underline (Ctrl+U)",strikethrough:"Strikethrough",hyperlink:"Insert Link (Ctrl+H)",alignLeft:"Align Left (Ctrl+L)",alignCenter:"Align Center (Ctrl+E)",alignRight:"Align Right (Ctrl+R)",unorderedList:"Bullet List",orderedList:"Numbered List",fontColor:"Text Color",bgColor:"Highlight Color",image:"Insert Image",emoji:"Emoji",getHtmlContent:"Get HTML",loadHtmlContent:"Load HTML"},p=[{feature:"alignLeft",id:"alignLeft",icon:f.left_align},{feature:"alignCenter",id:"alignCenter",icon:f.center_align},{feature:"alignRight",id:"alignRight",icon:f.right_align},{feature:"unorderedList",id:"unorderedList",icon:f.bullet_list},{feature:"orderedList",id:"orderedList",icon:f.numbered_list},{feature:"hyperlink",id:"hyperlink",icon:f.hyperlink},{feature:"emoji",id:"emoji",icon:f.emoji},{feature:"strikethrough",id:"strikethrough",icon:f.strikethrough}],g=(t,e)=>{const n=document.createElement("select");return n.dataset.action=t,n.id=t,e.forEach(t=>{const e=document.createElement("option");e.value=t,e.textContent=t,n.appendChild(e)}),n},m=document.createElement("div");m.id=o,m.className=u.POPUP_TOOLBAR_CLASSNAME,m.style.display="none",r.appendChild(m),e.popupFeatures&&e.popupFeatures.forEach((t,e)=>{e>0&&"hyperlink"===t&&m.appendChild(y());const n=p.find(e=>e.feature===t)||{icon:c[t]||t},i=document.createElement("button");i.dataset.action=t,i.innerHTML=n.icon,i.dataset.tooltip=h[t]||t.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" "),m.appendChild(i)});let k=null;e.features.forEach((t,n)=>{const i=function(t){for(const[e,n]of Object.entries(b))if(n.includes(t))return e;return null}(t);if(n>0&&i&&k&&i!==k&&a.appendChild(y()),k=i,"fontFamily"===t){const t=g(u.FONT_FAMILY_SELECT_ID,s);a.appendChild(t)}else if("fontSize"===t){const t=g(u.FONT_SIZE_SELECT_ID,l);a.appendChild(t)}else if("fontColor"===t){if(document.getElementById(u.FONT_COLOR_WRAPPER_ID))return;const t=document.createElement("span");t.id=u.FONT_COLOR_WRAPPER_ID,t.style.display="inline-flex",t.style.alignItems="center",t.style.position="relative",t.style.gap="4px";const e=document.createElement("button");e.id=u.FONT_COLOR_ID,e.type="button",e.dataset.tooltip=h.fontColor,e.innerHTML='A',t.appendChild(e);const n=document.createElement("div");n.id=u.FONT_COLOR_PICKER_WRAPPER_ID,n.style.display="none",n.style.position="absolute",n.style.top="100%",n.style.left="0",n.style.marginTop="4px",n.style.zIndex="1000",n.style.backgroundColor="#ffffff",n.style.border="1px solid #d1d1d1",n.style.borderRadius="4px",n.style.padding="8px",n.style.boxShadow="0 2px 8px rgba(0,0,0,0.15)",n.style.width="135px";const i=document.createElement("input");i.type="color",i.id=u.FONT_COLOR_PICKER_ID,i.setAttribute("data-action","fontColor"),i.style.width="100%",i.style.height="32px",i.style.border="1px solid #d1d1d1",i.style.borderRadius="4px",i.style.cursor="pointer",i.style.marginBottom="8px",i.value="#000000",n.appendChild(i);const o=document.createElement("button");o.id=u.FONT_COLOR_RESET_ID,o.type="button",o.textContent="Reset",o.style.display="block",o.style.width="100%",o.style.padding="6px 12px",o.style.fontSize="12px",o.style.border="1px solid #000000",o.style.borderRadius="4px",o.style.backgroundColor="#f8f8f8",o.style.cursor="pointer",o.style.transition="background-color 0.2s",o.onmouseenter=()=>o.style.backgroundColor="#e8e8e8",o.onmouseleave=()=>o.style.backgroundColor="#f8f8f8",n.appendChild(o),t.appendChild(n),a.appendChild(t)}else if("bgColor"===t){if(document.getElementById(u.BG_COLOR_WRAPPER_ID))return;const t=document.createElement("span");t.id=u.BG_COLOR_WRAPPER_ID,t.style.display="inline-flex",t.style.alignItems="center",t.style.position="relative",t.style.gap="4px";const e=document.createElement("button");e.id=u.BG_COLOR_ID,e.type="button",e.dataset.tooltip=h.bgColor,e.innerHTML='B',t.appendChild(e);const n=document.createElement("div");n.id=u.BG_COLOR_PICKER_WRAPPER_ID,n.style.display="none",n.style.position="absolute",n.style.top="100%",n.style.left="0",n.style.marginTop="4px",n.style.zIndex="1000",n.style.backgroundColor="#ffffff",n.style.border="1px solid #000000",n.style.borderRadius="4px",n.style.padding="8px",n.style.boxShadow="0 2px 8px rgba(0,0,0,0.15)",n.style.width="135px";const i=document.createElement("input");i.setAttribute("data-action","bgColor"),i.type="color",i.id=u.BG_COLOR_PICKER_ID,i.style.width="100%",i.style.height="32px",i.style.border="1px solid #000000ff",i.style.borderRadius="4px",i.style.cursor="pointer",i.style.marginBottom="8px",i.value="#ffffff",n.appendChild(i);const o=document.createElement("button");o.id=u.BG_COLOR_RESET_ID,o.type="button",o.textContent="Reset",o.style.display="block",o.style.width="100%",o.style.padding="6px 12px",o.style.fontSize="12px",o.style.border="1px solid #d1d1d1",o.style.borderRadius="4px",o.style.backgroundColor="#f8f8f8",o.style.cursor="pointer",o.style.transition="background-color 0.2s",o.onmouseenter=()=>o.style.backgroundColor="#e8e8e8",o.onmouseleave=()=>o.style.backgroundColor="#f8f8f8",n.appendChild(o),t.appendChild(n),a.appendChild(t)}else if("getHtmlContent"===t){const t=document.createElement("button");t.id=u.GET_HTML_BUTTON_ID,t.type="button",t.textContent="Get HTML",t.dataset.tooltip=h.getHtmlContent,a.appendChild(t)}else if("loadHtmlContent"===t){const t=document.createElement("select");t.id=u.LOAD_HTML_BUTTON_ID,t.dataset.action="loadHtmlContent",t.dataset.tooltip=h.loadHtmlContent,t.style.cursor="pointer",t.style.padding="4px 8px",t.style.border="1px solid #ccc",t.style.borderRadius="4px",t.style.backgroundColor="#f9f9f9",t.style.fontSize="13px",t.style.outline="none",t.style.color="#333",t.style.height="28px",t.addEventListener("mouseenter",()=>{t.style.backgroundColor="#eaeaea"}),t.addEventListener("mouseleave",()=>{t.style.backgroundColor="#f9f9f9"});const n=document.createElement("option");n.value="",n.textContent="Templates...",n.disabled=!0,n.selected=!0,t.appendChild(n);[...[{name:"Default Test",html:u.TEST_HTML_CODE},{name:"Blog Post",html:u.TEST_BLOG_POST_HTML_CODE},{name:"Newsletter",html:u.TEST_NEWSLATER_HTML_CODE},{name:"Resume",html:u.TEST_RESUME_HTML_CODE},{name:"Email",html:u.TEST_EMAIL_HTML_CODE},{name:"Meeting Notes",html:u.TEST_MEETING_HTML_CODE}],...e.templates||[]].forEach((e,n)=>{const i=document.createElement("option");i.value=n.toString(),i.dataset.html=e.html,i.textContent=e.name,t.appendChild(i)}),a.appendChild(t)}else if(p.map(t=>t.feature).includes(t)){const e=p.find(e=>e.feature===t),n=document.createElement("button");n.id=t,n.dataset.action=t,n.innerHTML=(null==e?void 0:e.icon)||"",n.dataset.tooltip=h[t]||t,a.appendChild(n)}else{const e=document.createElement("button");e.dataset.action=t,e.innerHTML=c[t]||t,e.id=t,e.dataset.tooltip=h[t]||t.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" "),a.appendChild(e)}});const C=document.createElement("div");C.id=u.HYPERLINK_CONTAINER_ID,C.style.display="none";const I=document.createElement("input");I.type="text",I.id=u.HYPERLINK_INPUT_ID,I.placeholder=u.HYPERLINK_PLACEHOLDER;const v=document.createElement("button");v.id=u.HYPERLINK_APPLY_BTN_ID,v.textContent="Link";const E=document.createElement("button");E.id=u.HYPERLINK_CANCEL_BTN_ID,E.textContent="Unlink",C.appendChild(I),C.appendChild(v),C.appendChild(E),a.appendChild(C);const x=document.createElement("div");x.id=u.VIEW_HYPERLINK_CONTAINER_ID,x.style.display="none";const w=document.createElement("span");w.id=u.VIEW_HYPERLINK_LABEL_ID,w.innerHTML="Visit URL : ";const S=document.createElement("a");return S.id=u.VIEW_HYPERLINK_ANCHOR_ID,S.href="",S.target="_blank",x.appendChild(w),x.appendChild(S),a.appendChild(x),{mainEditorId:n,toolbarId:i,popupToolbarId:o}}class C{constructor(t){this.htmlString=t,this.doc=(new DOMParser).parseFromString(t,"text/html")}parse(){const t=this.doc.body.children;let e=[];return Array.from(t).forEach((t,n)=>{const i=this.parseElement(t);console.log(t,"element parse",n,i),e.push(i)}),console.log(e,"element--jsondata"),e}parseElement(t){const e=t.getAttribute("data-id")||`data-id-${Date.now()}-${Math.floor(1e3*Math.random())}`,n=t.className||"paragraph-block",i=t.style.textAlign||"left";let o=null,s=null;"UL"===t.tagName?o="ul":"OL"===t.tagName&&(o="ol",s=parseInt(t.getAttribute("start")||"1",10));let l=[];return o?this.parseListItems(t,l):this.parseParagraphText(t,l),Object.assign(Object.assign(Object.assign({dataId:e,class:n,alignment:i,pieces:l},o?{listType:o}:{}),null!==s?{listStart:s}:{}),{})}parseListItems(t,e){t.querySelectorAll("li").forEach(t=>{const i=this.extractTextAttributes(t);i&&e.push(new n(i.text,i.attributes))})}parseParagraphText(t,e){const i=t.querySelectorAll("span"),o=new Map;i.forEach(t=>{const e=this.extractTextAttributes(t);if(console.log(e,"piece parseParagraphText span",t.textContent,t.style.color),e){const t=o.get(e.text);t?(t.attributes.bold=t.attributes.bold||e.attributes.bold,t.attributes.italic=t.attributes.italic||e.attributes.italic,t.attributes.underline=t.attributes.underline||e.attributes.underline,t.attributes.fontFamily=e.attributes.fontFamily||t.attributes.fontFamily,t.attributes.fontSize=e.attributes.fontSize||t.attributes.fontSize,t.attributes.fontColor=e.attributes.fontColor||t.attributes.fontColor,t.attributes.bgColor=e.attributes.bgColor||t.attributes.bgColor):o.set(e.text,Object.assign({},e))}}),o.forEach(t=>{e.push(new n(t.text,t.attributes))}),console.log(e,"pieces--parseParagraphText (merged)")}extractTextAttributes(t){var e;const n=t.textContent||"";return n?(console.log("extractTextAttributes node",t,t.style.color),{text:n,attributes:{bold:null!==t.querySelector("b, strong"),italic:null!==t.querySelector("i, em"),underline:null!==t.querySelector("u"),undo:!1,redo:!1,fontFamily:t.style.fontFamily||"Arial",fontSize:t.style.fontSize||"12px",hyperlink:!!t.querySelector("a")&&(null===(e=t.querySelector("a"))||void 0===e?void 0:e.getAttribute("href")),fontColor:t.style.color,bgColor:t.style.backgroundColor}}):null}rgbToHex(t,e=!1){const n=t.match(/\d+/g);if(!n||n.length<3)return null;const i=n.map(t=>{const e=parseInt(t);return e<0||e>255?"00":e.toString(16).padStart(2,"0")}).join("");return e||"000000"!==i?`#${i}`:null}}class I{constructor(t,e){this.editor=t,this.document=e,this.isImageHighlighted=!1,this.highLightedImageDataId="",this.currentCursorLocation=0,this.isCrossIconVisible=!1}setEditorView(t){this.editorView=t}insertImage(){const t=document.createElement("input");t.type="file",t.accept="image/*",t.click(),t.onchange=()=>{const e=t.files?t.files[0]:null;if(e){const t=new FileReader;t.onload=t=>{var e;const n=null===(e=t.target)||void 0===e?void 0:e.result;this.insertImageAtCursor(n)},t.readAsDataURL(e)}}}insertImageAtCursor(t){if(!t)return;const[e,n]=l(this.editorView);n>e&&this.document.deleteRange(e,n,this.document.selectedBlockId),this.insertImageAtPosition(t,e,this.document.selectedBlockId)}setCursorPostion(t,e){if("number"!=typeof t||!e)return;const n=document.querySelector(`[data-id="${e}"]`);n&&("function"==typeof n.focus&&n.focus(),setTimeout(()=>{const e=document.createRange(),i=window.getSelection();if(n.firstChild)e.setStart(n.firstChild,t);else{const t=document.createTextNode("");n.appendChild(t),e.setStart(t,0)}e.collapse(!0),null==i||i.removeAllRanges(),null==i||i.addRange(e)},0))}insertImageAtPosition(t,e,i){if(!t||"number"!=typeof e||!this.editorView)return;console.log(t,e,i,"vicky insertImageAtPosition",this.document.blocks);const o=`data-id-${Date.now()}-${1e3*Math.random()}`,s=`data-id-${Date.now()}-${1e3*Math.random()}`,l=`data-id-${Date.now()}-${1e3*Math.random()}`,r={dataId:o,class:u.PARAGRAPH_BLOCK_CLASS,pieces:[new n(" ")],type:"image",image:t},a={dataId:s,class:u.PARAGRAPH_BLOCK_CLASS,pieces:[new n(" ")],type:"text"};let d=this.document.selectedBlockId;const c=this.document.blocks.findIndex(t=>t.dataId===this.document.selectedBlockId);let h=[];const{remainingText:p,piece:g}=function(t,e){const n=window.getSelection();if(!n||0===n.rangeCount)return{remainingText:"",piece:null};const i=n.getRangeAt(0).startContainer;let o="";const s=e.blocks.filter(e=>{if(e.dataId===t)return e});if(!s[0]||!s[0].pieces)return{remainingText:"",piece:null};const l=document.querySelector(`[data-id="${t}"]`),r=e.getCursorOffsetInParent(`[data-id="${t}"]`);let a=[],d=0;if(s[0].pieces.forEach((t,e)=>{o+=t.text,(null==r?void 0:r.innerText)===t.text&&(d=e,a.push(t))}),s[0].pieces.length>1&&s[0].pieces.forEach((t,e)=>{d0){const t=p.split(" ");let e=[];""!==t[0]||void 0!==t[1]?1===g.length?e=[new n(m,g[0].attributes)]:(e.push(new n(" "+t[0]+" ",g[0].attributes)),g.length>=2&&g.forEach((t,n)=>{0!==n&&e.push(t)})):e=[new n(" ")],console.log(this.document.selectedBlockId,"uniqueId3 extractTextFromDataId-vicky",l),f=function(t,e,n){const i=t.findIndex(t=>t.dataId===e);return-1===i?(console.error(`Block with dataId "${e}" not found.`),t):[...t.slice(0,i+1),n,...t.slice(i+1)]}(this.document.blocks,this.document.selectedBlockId||"",{dataId:l,class:u.PARAGRAPH_BLOCK_CLASS,pieces:e,type:"text"})}this.document.blocks=f,this.document.deleteRange(this.currentCursorLocation,this.currentCursorLocation+p.length,this.document.selectedBlockId,this.document.currentOffset),this.document.blocks.length>c+1?this.document.blocks.forEach((t,e)=>{h.push(t),e===c?h.push(r):d===this.document.selectedBlockId&&(d=t.dataId)}):(h=[...this.document.blocks,r,a],d=a.dataId),this.document.blocks=h,this.editorView.render(),this.document.selectedBlockId=d;const b=document.querySelector(`[data-id="${d}"]`);b.focus(),setTimeout(()=>{const t=document.createRange(),e=window.getSelection();if(b.firstChild)t.setStart(b.firstChild,1);else{const e=document.createTextNode("");b.appendChild(e),t.setStart(e,0)}t.collapse(!0),null==e||e.removeAllRanges(),null==e||e.addRange(t)},0)}createImageFragment(t,e){if(!t||!e)return document.createDocumentFragment();const n=document.createDocumentFragment(),i=document.createElement("img");i.src=t,i.style.maxWidth="30%",i.setAttribute("contenteditable","false"),n.appendChild(i);const o=document.createElement("span");return o.setAttribute("contenteditable","false"),o.appendChild(n),i.addEventListener("click",()=>this.addStyleToImage(e)),o}addStyleToImage(t){if(t&&!this.isCrossIconVisible){const e=document.querySelector(`[data-id="${t}"]`),n=null==e?void 0:e.querySelector("span");n&&(n.style.position="relative");const i=null==e?void 0:e.querySelector("img");i&&(i.style.border="2px solid blue");const o=document.createElement("div");o.className=u.IMAGE_CROSS_CLASS,o.innerHTML="x",Object.assign(o.style,{position:"absolute",top:"0",left:"50%",transform:"translate(-50%, 0)",background:"#fff",borderRadius:"50%",width:"30px",height:"30px",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",border:"3px solid blue",zIndex:"999"}),o.addEventListener("mouseover",()=>o.style.border="3px solid black"),o.addEventListener("mouseout",()=>o.style.border="3px solid blue"),o.addEventListener("click",t=>{t.stopPropagation(),this.deleteImage()}),null==n||n.appendChild(o),this.isImageHighlighted=!0,this.highLightedImageDataId=t,this.isCrossIconVisible=!0}}clearImageStyling(){if(!this.highLightedImageDataId)return;const t=document.querySelector(`[data-id="${this.highLightedImageDataId}"]`);if(t){const e=t.querySelector("span");null==e||e.removeAttribute("style");const n=null==e?void 0:e.querySelector("img");n&&n.removeAttribute("style");const i=null==e?void 0:e.querySelector(`.${u.IMAGE_CROSS_CLASS}`);null==i||i.remove(),this.highLightedImageDataId=""}this.isCrossIconVisible=!1}deleteImage(){this.highLightedImageDataId&&(this.document.blocks=this.document.blocks.filter(t=>t.dataId!==this.highLightedImageDataId),this.highLightedImageDataId="",this.isImageHighlighted=!1,this.clearImageStyling(),this.document.emit("documentChanged",this))}}class v{constructor(t,e){this.snapshotUndoStack=[],this.snapshotRedoStack=[],this.maxSnapshots=5e3,this.document=t,this.editorView=e}createSnapshot(){const[t,e]=l(this.editorView);return{blocks:JSON.parse(JSON.stringify(this.document.blocks)),dataIds:[...this.document.dataIds],selectedBlockId:this.document.selectedBlockId,currentOffset:this.document.currentOffset,selection:this.getCurrentSelection(),cursorPosition:t}}getCurrentSelection(){const t=o(this.document.editorView.container);return t?{start:t.start,end:t.end}:{start:0,end:0}}saveUndoSnapshot(){const t=this.createSnapshot();console.log("Saving snapshot:",t.cursorPosition,"Stack length:",this.snapshotUndoStack.length),this.snapshotUndoStack.push(t),this.snapshotUndoStack.length>this.maxSnapshots&&this.snapshotUndoStack.shift(),this.snapshotRedoStack=[]}restoreSnapshot(t){this.document.blocks=t.blocks,this.document.dataIds=t.dataIds,this.document._selectedBlockId=t.selectedBlockId,this.document.currentOffset=t.currentOffset;for(let t of this.document.blocks)t.pieces&&Array.isArray(t.pieces)&&(t.pieces=t.pieces.map(t=>new n(t.text,t.attributes)));this.document.emit("documentChanged",this.document),setTimeout(()=>{this.document.setCursorPosition(t.cursorPosition||0)},0)}undo(){if(console.log("UNDO - Undo stack length:",this.snapshotUndoStack.length),console.log("UNDO - Redo stack length:",this.snapshotRedoStack.length),0===this.snapshotUndoStack.length)return;const t=this.createSnapshot();this.snapshotRedoStack.push(t),this.snapshotRedoStack.length>this.maxSnapshots&&this.snapshotRedoStack.shift();const e=this.snapshotUndoStack.pop();e&&(console.log("UNDO - Restoring cursor position:",e.cursorPosition),this.restoreSnapshot(e))}redo(){if(0===this.snapshotRedoStack.length)return;const t=this.createSnapshot();this.snapshotUndoStack.push(t),this.snapshotUndoStack.length>this.maxSnapshots&&this.snapshotUndoStack.shift();const e=this.snapshotRedoStack.pop();e&&this.restoreSnapshot(e)}}class E extends e{constructor(t){super(),this.container=t,this.setupButtons()}setupButtons(){this.container.addEventListener("mousedown",t=>{t.preventDefault()}),this.container.addEventListener("click",t=>{const e=t.target.closest("button");if(e){const t=e.getAttribute("data-action");t&&this.emit("popupAction",t)}})}show(t){const e=t.getRangeAt(0).getBoundingClientRect();if(0===e.width&&0===e.height)return void this.hide();this.container.style.display="flex";const n=this.container.offsetWidth,i=this.container.offsetHeight;let o=e.top+window.scrollY-i-8,s=e.left+window.scrollX+e.width/2-n/2;o{const n=e.getAttribute("data-action");let i=!1;"bold"===n&&t.bold&&(i=!0),"italic"===n&&t.italic&&(i=!0),"underline"===n&&t.underline&&(i=!0),"strikethrough"===n&&t.strikethrough&&(i=!0),"hyperlink"===n&&t.hyperlink&&(i=!0),e.classList.toggle("active",i)})}}class x{constructor(){this.linkElement=null,this.createPopup()}setCallbacks(t,e){this.onOpenClick=t,this.onUnlinkClick=e}createPopup(){this.popup=document.createElement("div"),this.popup.className="link-popup",this.popup.style.cssText="\n position: absolute;\n background: #000;\n border-radius: 4px;\n padding: 2px;\n box-shadow: 0 1px 4px rgba(0,0,0,0.5);\n z-index: 1000;\n display: none;\n ";const t=this.createButton("Open","🔗"),e=this.createButton("Unlink","✕");t.addEventListener("click",()=>this.handleOpenClick()),e.addEventListener("click",()=>this.handleUnlinkClick()),this.popup.appendChild(t),this.popup.appendChild(e),document.body.appendChild(this.popup)}createButton(t,e){const n=document.createElement("button");return n.innerHTML=`${e}`,n.title=t,n.style.cssText="\n background: transparent;\n color: white;\n border: none;\n padding: 4px;\n margin: 0 1px;\n border-radius: 2px;\n cursor: pointer;\n font-size: 16px;\n transition: background 0.1s;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n ",n.addEventListener("mouseenter",()=>{n.style.background="#333"}),n.addEventListener("mouseleave",()=>{n.style.background="transparent"}),n}handleOpenClick(){this.linkElement&&this.onOpenClick&&this.onOpenClick(this.linkElement.href)}handleUnlinkClick(){this.onUnlinkClick&&this.linkElement&&this.onUnlinkClick(this.linkElement)}show(t,e,n){this.linkElement=t;const i=t.getBoundingClientRect();this.popup.style.left=`${i.left+window.scrollX}px`,this.popup.style.top=`${i.bottom+window.scrollY+5}px`,this.popup.style.display="flex",this.popup.style.opacity="0",this.popup.style.transform="translateY(-2px)",requestAnimationFrame(()=>{this.popup.style.transition="opacity 0.1s ease-in-out, transform 0.1s ease-in-out",this.popup.style.opacity="1",this.popup.style.transform="translateY(0)"})}hide(){"none"!==this.popup.style.display&&(this.popup.style.transition="opacity 0.1s ease-in-out, transform 0.1s ease-in-out",this.popup.style.opacity="0",this.popup.style.transform="translateY(-2px)",setTimeout(()=>{this.popup.style.display="none",this.popup.style.transition=""},100))}isPopup(t){return this.popup.contains(t)}isVisible(){return"none"!==this.popup.style.display}}class w{constructor(t,e,n,i){this.isRecording=!1,this.silenceTimer=null,this.document=t,this.editorView=e,this.onStateChange=n,this.insertText=i;const o=window.SpeechRecognition||window.webkitSpeechRecognition;o?(this.recognition=new o,this.recognition.continuous=!0,this.recognition.interimResults=!1,this.recognition.onresult=t=>{const e=t.results[t.results.length-1];if(e.isFinal){const t=e[0].transcript+" ";this.insertText(t)}},this.recognition.onerror=t=>{console.error("Speech recognition error:",t.error),"no-speech"!==t.error&&this.stopRecording()},this.recognition.onend=()=>{this.stopRecording()}):console.warn("Speech Recognition API not supported in this browser.")}toggleRecording(){this.isRecording?this.stopRecording():this.startRecording()}startRecording(){if(this.recognition)try{this.recognition.start(),this.isRecording=!0,this.onStateChange(!0)}catch(t){console.error("Failed to start speech recognition:",t)}}stopRecording(){if(this.recognition&&this.isRecording){try{this.recognition.stop()}catch(t){console.warn("Some problem occur during the stop recording . . . ",t)}this.isRecording=!1,this.onStateChange(!1),this.silenceTimer&&(clearTimeout(this.silenceTimer),this.silenceTimer=null)}}}const S=[{label:"Smileys & People",items:[{char:"😀",name:"grinning face",shortcode:":grinning:"},{char:"😃",name:"big eyes smile",shortcode:":smiley:"},{char:"😄",name:"smiling eyes grin",shortcode:":smile:"},{char:"😁",name:"beaming grin",shortcode:":grin:"},{char:"😆",name:"squinting laugh",shortcode:":laughing:"},{char:"😅",name:"sweat smile",shortcode:":sweat_smile:"},{char:"🤣",name:"rolling floor laughing",shortcode:":rofl:"},{char:"😂",name:"tears of joy",shortcode:":joy:"},{char:"🙂",name:"slightly smiling",shortcode:":slightly_smiling_face:"},{char:"😊",name:"smiling eyes blush",shortcode:":blush:"}]}],T="recent_emojies";class A{constructor(){this.isOpen=!1,this.popup=this.buildPopup(),this.gridArea=this.popup.querySelector(".emoji_grid"),this.searchInput=this.popup.querySelector(".emoji_serch"),document.body.appendChild(this.popup),document.addEventListener("mousedown",t=>{if(this.isOpen&&!this.popup.contains(t.target)){t.target.closest('[data-action="emoji"]')||this.close()}})}onSelect(t){this.onSelectCallback=t}open(t){const e=t.getBoundingClientRect();let n=e.left+window.scrollX;n+320>window.innerWidth-8&&(n=window.innerWidth-320-8);const i=e.bottom+window.scrollY+4;this.popup.style.left=`${n}px`,this.popup.style.top=`${i}px`,this.popup.style.display="flex",this.isOpen=!0,this.searchInput.value="",this.renderGrid("")}close(){this.popup.style.display="none",this.isOpen=!1}getIsOpen(){return this.isOpen}buildPopup(){const t=document.createElement("div");t.style.cssText="\n position: absolute;\n display: none;\n flex-direction: column;\n width: 320px;\n max-height: 380px;\n background: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 10px;\n box-shadow: 0 6px 24px rgba(0,0,0,0.14);\n z-index: 9999;\n overflow: hidden;\n font-family: system-ui, -apple-system, sans-serif;\n ";const e=document.createElement("div");e.style.cssText="\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border-bottom: 1px solid #f0f0f0;\n background: #fafafa;\n ";const n=document.createElement("input");n.type="text",n.placeholder="🔍 Search emojis or :shortcode:",n.className="emoji_serch",n.style.cssText="\n flex: 1;\n padding: 6px 10px;\n border: 1px solid #ccc;\n border-radius: 6px;\n font-size: 13px;\n outline: none;\n background: #fff;\n ",n.addEventListener("input",()=>this.renderGrid(n.value.trim())),e.appendChild(n);const i=document.createElement("div");return i.className="emoji_grid",i.style.cssText="\n flex: 1;\n overflow-y: auto;\n padding: 10px 12px 12px;\n ",t.appendChild(e),t.appendChild(i),t}getRecentEmojis(){try{const t=localStorage.getItem(T);return t?JSON.parse(t):[]}catch(t){return[]}}saveRecentEmoji(t){const e=this.getRecentEmojis().filter(e=>e.char!==t.char);e.unshift(t),e.length>24&&(e.length=24);try{localStorage.setItem(T,JSON.stringify(e))}catch(t){console.error("Problem occur in saving emojies",t)}}resolveChar(t){return t.char}renderGrid(t){this.gridArea.innerHTML="";const e=t.toLowerCase().replace(/^:/,"").replace(/:$/,""),n=(t,e)=>{if(!e.length)return;const n=document.createElement("div");n.style.marginBottom="12px";const i=document.createElement("div");i.textContent=t,i.style.cssText="\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #999;\n margin-bottom: 6px;\n ",n.appendChild(i);const o=document.createElement("div");o.style.cssText="\n display: grid;\n grid-template-columns: repeat(8, 1fr);\n gap: 2px;\n ",e.forEach(t=>{const e=this.resolveChar(t),n=document.createElement("button");n.textContent=e,n.title=`${t.name} ${t.shortcode}`,n.style.cssText="\n font-size: 20px;\n background: transparent;\n border: none;\n cursor: pointer;\n border-radius: 5px;\n padding: 4px;\n line-height: 1.2;\n transition: background 0.1s;\n aspect-ratio: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n ",n.addEventListener("mouseenter",()=>n.style.background="#f0f0f0"),n.addEventListener("mouseleave",()=>n.style.background="transparent"),n.addEventListener("mousedown",n=>{var i;n.preventDefault(),this.saveRecentEmoji(t),null===(i=this.onSelectCallback)||void 0===i||i.call(this,e)}),o.appendChild(n)}),n.appendChild(o),this.gridArea.appendChild(n)};if(e){const t=[];S.forEach(n=>{n.items.forEach(n=>{(n.name.includes(e)||n.shortcode.includes(e))&&t.push(n)})}),n(`Results for "${e}"`,t)}else{const t=this.getRecentEmojis();n("Recently Used",t),S.forEach(t=>n(t.label,t.items))}if(!this.gridArea.querySelector("button")){const t=document.createElement("div");t.textContent="No emojis found",t.style.cssText="text-align: center; color: #aaa; padding: 24px 0; font-size: 13px;",this.gridArea.appendChild(t)}}}class L extends e{constructor(t,e){var o,s,l,d,m,b,y,S,T,L,R,_,O;super(),this.savedSelection=null,this.debounceTimer=null;const{mainEditorId:B,toolbarId:H,popupToolbarId:N}=k(t,e);this.editorContainer=document.getElementById(B)||null,this.toolbarContainer=document.getElementById(H)||null;const P=document.getElementById(N)||null;if(!this.editorContainer||!this.toolbarContainer||!P)throw new Error("Editor element not found or incorrect element type.");this.document=new i,this.editorView=new c(this.editorContainer,this.document),this.toolbarView=new h(this.toolbarContainer),this.popupToolbarView=new E(P),this.linkPopupView=new x,this.hyperlinkHandler=new p(this.editorContainer,this.editorView,this.document),this.imageHandler=new I(this.editorContainer,this.document),this.undoRedoManager=new v(this.document,this.editorView),this.editorView.setImageHandler(this.imageHandler),this.imageHandler.setEditorView(this.editorView),this.document.setEditorView(this.editorView),this.document.setUndoRedoManager(this.undoRedoManager),this.hyperlinkHandler.setUndoRedoManager(this.undoRedoManager),this.linkPopupView.setCallbacks(t=>this.openLink(t),t=>this.unlinkText(t)),this.speechToTextHandler=new w(this.document,this.editorView,t=>{const e=document.getElementById("speechtotext");e&&(e.innerHTML=t?f.stop_microphone:f.start_microphone,e.dataset.tooltip=t?"stop":"start")},t=>{const[e,n]=this.getSelectionRange();n>e&&this.document.deleteRange(e,n,this.document.selectedBlockId,this.document.currentOffset);let i=e;this.document.insertAt(t,Object.assign({},this.currentAttributes),i,this.document.selectedBlockId,0,"","batch"),i+=t.length,this.setCursorPosition(i)});const D=document.getElementById("speechtotext");D&&(D.innerHTML="",D.insertAdjacentHTML("afterbegin",f.start_microphone),D.dataset.tooltip="start"),this.emojiPickerView=new A,this.emojiPickerView.onSelect(t=>{this.savedSelection&&this.setCursorPosition(this.savedSelection.start);const[e,n]=this.getSelectionRange();n>e&&this.document.deleteRange(e,n,this.document.selectedBlockId,this.document.currentOffset,!1),this.document.insertAt(t,Object.assign({},this.currentAttributes),e,this.document.selectedBlockId,0,"","batch");const i=e+t.length;this.savedSelection={start:i,end:i},this.setCursorPosition(i)}),this.currentAttributes={bold:!1,italic:!1,underline:!1,strikethrough:!1,undo:!1,redo:!1,hyperlink:!1},this.manualOverride=!1,this.lastPiece=null,this.toolbarView.on("toolbarAction",(t,e=[])=>this.handleToolbarAction(t,e)),this.popupToolbarView.on("popupAction",t=>this.handleToolbarAction(t)),this.document.on("documentChanged",()=>{if(0===this.document.blocks.length||1===this.document.blocks.length&&this.document.blocks[0].pieces.every(t=>""===t.text.trim()||""===t.text)){const t=document.getElementById("loadHtmlButton");t&&(t.selectedIndex=0)}this.editorView.render()}),this.document.on("documentChanged",()=>{var t;const e=this.document.getHtmlContent();this.emit("contentChange",{html:e,text:(null===(t=this.editorContainer)||void 0===t?void 0:t.textContent)||""})}),this.editorContainer.addEventListener("keydown",t=>{this.syncCurrentAttributesWithCursor(),this.handleKeydown(t)}),this.editorContainer.addEventListener("keyup",()=>this.syncCurrentAttributesWithCursor()),this.editorContainer.addEventListener("blur",()=>{this.hyperlinkHandler.hideHyperlinkViewButton()}),document.addEventListener("mouseup",()=>{this.syncCurrentAttributesWithCursor();const t=this.document.getAllSelectedDataIds();console.log(t,"dataId lntgerr")}),document.addEventListener("selectionchange",()=>{const t=window.getSelection();t&&!t.isCollapsed||(this.document.dataIds=[],this.document.selectAll=!1)}),null===(o=document.getElementById("fontColor"))||void 0===o||o.addEventListener("click",t=>{t.stopPropagation();const e=document.getElementById("colorWrapper"),n=document.getElementById("fontColorPicker");if(!e||!n)return;const i="block"===e.style.display;e.style.display=i?"none":"block"}),null===(s=document.getElementById("fontColorPicker"))||void 0===s||s.addEventListener("input",t=>{const e=t.target.value,[n,i]=this.getSelectionRange(),o=document.getElementById("fontColorIndicator");o&&(o.style.backgroundColor=e),this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let i=0;t.pieces.forEach(t=>{i+=t.text.length});let o=n-i;this.document.applyFontColor(o,i,e)}}):(this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.document.applyFontColor(n,i,e)},300))}),null===(l=document.getElementById("colorResetFont"))||void 0===l||l.addEventListener("click",()=>{const t=document.getElementById("fontColorPicker"),e=document.getElementById("fontColorIndicator");t&&(t.value="#000000",e&&(e.style.backgroundColor="#000000"),t.dispatchEvent(new Event("input")))}),document.addEventListener("click",t=>{var e;const n=t.target,i=document.getElementById("colorWrapper"),o=document.getElementById("colorBgWrapper"),s=document.getElementById("fontColor"),l=document.getElementById("bgColor");!i||n.closest("#colorWrapper")||n===s||(null==s?void 0:s.contains(n))||(i.style.display="none"),!o||n.closest("#colorBgWrapper")||n===l||(null==l?void 0:l.contains(n))||(o.style.display="none"),(null===(e=this.editorContainer)||void 0===e?void 0:e.contains(n))||n.closest(".hyperlink-popup")||this.hyperlinkHandler.hideHyperlinkViewButton()}),null===(d=document.getElementById("bgColor"))||void 0===d||d.addEventListener("click",t=>{t.stopPropagation();const e=document.getElementById("colorBgWrapper"),n=document.getElementById("bgColorPicker");if(!e||!n)return;const i="block"===e.style.display;e.style.display=i?"none":"block"}),null===(m=document.getElementById("bgColorPicker"))||void 0===m||m.addEventListener("input",t=>{const e=t.target.value,[n,i]=this.getSelectionRange(),o=document.getElementById("bgColorIndicator");o&&(o.style.backgroundColor=e),this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let i=0;t.pieces.forEach(t=>{i+=t.text.length});let o=n-i;this.document.applyBgColor(o,i,e)}}):(this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.document.applyBgColor(n,i,e)},300))}),null===(b=document.getElementById("colorResetBG"))||void 0===b||b.addEventListener("click",()=>{const t=document.getElementById("bgColorPicker"),e=document.getElementById("bgColorIndicator");t&&(t.value="#ffffff",e&&(e.style.backgroundColor="#ffffff"),t.dispatchEvent(new Event("input")))}),null===(y=document.getElementById("getHtmlButton"))||void 0===y||y.addEventListener("click",t=>{const e=this.document.getHtmlContent(!0);console.log("Editor HTML Content:",e),this.htmlToJsonParser=new C(e);const n=this.htmlToJsonParser.parse();console.log("htmltoJson",JSON.stringify(n,null,2),n),this.showAcknowledgement("HTML copied to clipboard",2e3)}),null===(S=document.getElementById("loadHtmlButton"))||void 0===S||S.addEventListener("change",t=>{this.undoRedoManager.saveUndoSnapshot();const e=t.target,n=e.options[e.selectedIndex].dataset.html||u.TEST_HTML_CODE;this.htmlToJsonParser=new C(n),console.log(this.htmlToJsonParser,"this.htmlToJsonParser");const i=this.htmlToJsonParser.parse();this.document.blocks=i,i.length>0&&(this.document.dataIds[0]=i[0].dataId,this.document.selectedBlockId=i[0].dataId),this.document.emit("documentChanged",this);const[o]=this.getSelectionRange();this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let e=0;t.pieces.forEach(t=>{e+=t.text.length});let n=o-e;t.fontSize&&this.document.setFontSize(n,e,t.fontSize)}}),console.log("blocks",this.document.blocks,this.document.dataIds,this.document.currentOffset),console.log("htmltoJson",JSON.stringify(i,null,2),i)}),null===(T=document.getElementById("fontFamily"))||void 0===T||T.addEventListener("change",t=>{this.undoRedoManager.saveUndoSnapshot();const e=t.target.value,[n,i]=this.getSelectionRange();this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let i=0;t.pieces.forEach(t=>{i+=t.text.length});let o=n-i;this.document.setFontFamily(o,i,e)}}):this.document.setFontFamily(n,i,e)}),null===(L=document.getElementById("fontSize"))||void 0===L||L.addEventListener("change",t=>{this.undoRedoManager.saveUndoSnapshot();const e=t.target.value,[n,i]=this.getSelectionRange();this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let i=0;t.pieces.forEach(t=>{i+=t.text.length});let o=n-i;this.document.setFontSize(o,i,e)}}):this.document.setFontSize(n,i,e)}),null===(R=document.getElementById("alignLeft"))||void 0===R||R.addEventListener("click",()=>{console.log("alignment alignLeft",this.document.dataIds),this.document.dataIds.forEach(t=>this.document.setAlignment("left",t))}),null===(_=document.getElementById("alignCenter"))||void 0===_||_.addEventListener("click",()=>{console.log("alignment alignCenter",this.document.dataIds),this.document.dataIds.forEach(t=>this.document.setAlignment("center",t))}),null===(O=document.getElementById("alignRight"))||void 0===O||O.addEventListener("click",()=>{console.log("alignment alignRight",this.document.dataIds),this.document.dataIds.forEach(t=>this.document.setAlignment("right",t))}),this.editorContainer.addEventListener("keydown",t=>{if((t.ctrlKey||t.metaKey)&&!t.altKey){const e=t.key.toLowerCase();if(["b","i","u","h"].includes(e)){t.preventDefault();let n="b";switch(e){case"b":n="bold";break;case"i":n="italic";break;case"u":n="underline";break;case"h":n="hyperlink"}this.handleToolbarAction(n)}if("z"===e?(t.preventDefault(),this.undoRedoManager.undo()):"y"===e&&(t.preventDefault(),this.undoRedoManager.redo()),"a"===e){const t=this.document.handleCtrlASelection();this.document.selectAll=!0,console.log("Selected text is inside element with data-id:",t)}"l"===t.key?(t.preventDefault(),this.document.setAlignment("left",this.document.selectedBlockId)):"e"===t.key?(t.preventDefault(),this.document.setAlignment("center",this.document.selectedBlockId)):"r"===t.key&&(t.preventDefault(),this.document.setAlignment("right",this.document.selectedBlockId))}}),document.addEventListener("selectionchange",this.handleSelectionChange.bind(this)),this.editorContainer.addEventListener("click",t=>{const e=t.target;if("A"===e.tagName||e.closest("a")){t.preventDefault(),t.stopPropagation();const n="A"===e.tagName?e:e.closest("a");this.showLinkPopup(n,t.clientX,t.clientY)}else this.hideLinkPopup()}),document.addEventListener("click",t=>{this.linkPopupView.isPopup(t.target)||this.hideLinkPopup()}),this.document.emit("documentChanged",this.document),this.editorContainer.addEventListener("paste",t=>{var e,i;this.undoRedoManager.saveUndoSnapshot(),t.preventDefault();const o=null===(e=t.clipboardData)||void 0===e?void 0:e.getData("text/html"),[s,l]=this.getSelectionRange();l>s&&this.document.deleteRange(s,l,this.document.selectedBlockId,this.document.currentOffset);let d=[];if(o)d=g(o);else{const e=function(t){const e=[];let n,i=0;for(;null!==(n=r.exec(t));){const o=n.index;let s=n[0],l="";const r=s.match(/[.,!?;:)\]\}"']+$/);if(r&&(l=r[0],s=s.slice(0,-l.length)),a(t,o))continue;o>i&&e.push({text:t.substring(i,o),isUrl:!1});let d=s;d.startsWith("http")||(d="https://"+d),e.push({text:s,isUrl:!0,url:d}),l&&e.push({text:l,isUrl:!1}),i=o+n[0].length}return it.isUrl&&t.url?new n(t.text,Object.assign(Object.assign({},this.currentAttributes),{hyperlink:t.url})):new n(t.text,Object.assign({},this.currentAttributes)))}let c=s;for(const t of d)this.document.insertAt(t.text,Object.assign({},t.attributes),c,this.document.selectedBlockId,0,"","batch"),c+=t.text.length;this.setCursorPosition(c)}),this.editorContainer.addEventListener("dragover",t=>{t.preventDefault()}),this.editorContainer.addEventListener("drop",t=>{var e,i;t.preventDefault(),this.undoRedoManager.saveUndoSnapshot();const o=null===(e=t.dataTransfer)||void 0===e?void 0:e.getData("text/html"),[s,l]=this.getSelectionRange();l>s&&this.document.deleteRange(s,l,this.document.selectedBlockId,this.document.currentOffset);let r=[];if(o)r=g(o);else{const e=(null===(i=t.dataTransfer)||void 0===i?void 0:i.getData("text/plain"))||"";r=[new n(e,Object.assign({},this.currentAttributes))]}let a=s;for(const t of r)this.document.insertAt(t.text,Object.assign({},t.attributes),a,this.document.selectedBlockId,0,"","batch"),a+=t.text.length;this.setCursorPosition(a)})}getSelectionRange(){const t=o(this.editorView.container);return t?[t.start,t.end]:[0,0]}applyFontColor(t){const e=window.getSelection();if(!e||0===e.rangeCount)return;e.getRangeAt(0).toString()}handleToolbarAction(t,e=[]){const[n,i]=this.getSelectionRange();switch(t){case"orderedList":if(this.document.dataIds.length>1)this.document.toggleOrderedListForMultipleBlocks(this.document.dataIds);else{const t=this.document.selectedBlockId||this.document.dataIds[0];this.document.toggleOrderedList(t)}this.document.updateOrderedListNumbers();break;case"unorderedList":this.document.dataIds.forEach(t=>{this.document.toggleUnorderedList(t)});break;case"image":this.imageHandler.insertImage();break;case"speechtotext":this.speechToTextHandler.toggleRecording();break;case"emoji":this.savedSelection=o(this.editorView.container);const e=document.querySelector('[data-action="emoji"]');e.addEventListener("mousedown",t=>{t.preventDefault()}),e&&this.emojiPickerView.open(e);break;default:if(n1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let e=0;t.pieces.forEach(t=>{e+=t.text.length});let i=n-e;this.document.toggleBoldRange(i,e)}}):this.document.toggleBoldRange(n,i);break;case"italic":this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let e=0;t.pieces.forEach(t=>{e+=t.text.length});let i=n-e;this.document.toggleItalicRange(i,e)}}):this.document.toggleItalicRange(n,i);break;case"underline":this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let e=0;t.pieces.forEach(t=>{e+=t.text.length});let i=n-e;this.document.toggleUnderlineRange(i,e)}}):this.document.toggleUnderlineRange(n,i);break;case"strikethrough":this.document.dataIds.length>1?this.document.blocks.forEach(t=>{if(this.document.dataIds.includes(t.dataId)){this.document.selectedBlockId=t.dataId;let e=0;t.pieces.forEach(t=>{e+=t.text.length});let i=n-e;this.document.toggleStrikethroughRange(i,e)}}):this.document.toggleStrikethroughRange(n,i);break;case"hyperlink":this.hyperlinkHandler.hanldeHyperlinkClick(n,i,this.document.currentOffset,this.document.selectedBlockId,this.document.blocks)}else this.currentAttributes[t]=!this.currentAttributes[t],this.manualOverride=!0}this.toolbarView.updateActiveStates(this.currentAttributes)}handleSelectionChange(){var t,e;const n=window.getSelection();if(!n||0===n.rangeCount||!(null===(t=this.editorContainer)||void 0===t?void 0:t.contains(n.anchorNode)))return this.hyperlinkHandler.hideHyperlinkViewButton(),void this.popupToolbarView.hide();const[i]=this.getSelectionRange();if(this.imageHandler.currentCursorLocation=i,n.isCollapsed?(this.document.dataIds=[],this.document.selectAll=!1,this.popupToolbarView.hide()):(this.document.getAllSelectedDataIds(),this.document.dataIds.length===this.document.blocks.length&&this.document.blocks.length>0&&(this.document.selectAll=!0),this.popupToolbarView.show(n)),!n||0===n.rangeCount)return;n&&!0===n.isCollapsed&&(this.document.dataIds=[],this.document.selectAll=!1);const o=n.getRangeAt(0),s=(null===(e=o.startContainer.parentElement)||void 0===e?void 0:e.closest("[data-id]"))||o.startContainer;s instanceof HTMLElement&&(this.document.selectedBlockId=s.getAttribute("data-id")||(o.startContainer instanceof HTMLElement?o.startContainer.getAttribute("data-id"):null)),this.syncCurrentAttributesWithCursor()}handleKeydown(t){var e,i;const[o,s]=this.getSelectionRange();if(this.imageHandler.currentCursorLocation=o,"Enter"===t.key){t.preventDefault(),this.undoRedoManager.saveUndoSnapshot();const i=`data-id-${Date.now()}`,l=this.document.blocks.findIndex(t=>t.dataId===this.document.selectedBlockId),r=this.document.blocks[l],a=(null===(e=null==r?void 0:r.pieces)||void 0===e?void 0:e.length)>0?r.pieces[r.pieces.length-1]:null,d=a?Object.assign({},a.attributes):{fontFamily:"Arial",fontSize:"16px",fontColor:"#000000",bgColor:"#ffffff",bold:!1,italic:!1,underline:!1,strikethrough:!1};if(r&&"image"===r.type)this.document.blocks.splice(l+1,0,{dataId:i,class:"paragraph-block",pieces:[new n("",d)],type:"text"}),this.document.emit("documentChanged",this),this.imageHandler.setCursorPostion(1,i);else if(!r||"ol"!==r.listType&&"ul"!==r.listType&&"li"!==r.listType){const t=this.getCurrentCursorBlock(),e=null==t?void 0:t.toString();if(e&&r&&"text"===r.type){const t=o-this.document.currentOffset,s=[],l=[];let a=0;for(const e of r.pieces){const i=a+e.text.length;if(i<=t)s.push(e.clone());else if(a>=t)l.push(e.clone());else{const i=t-a,o=e.text.slice(0,i),r=e.text.slice(i);o&&s.push(new n(o,Object.assign({},e.attributes))),r&&l.push(new n(r,Object.assign({},e.attributes)))}a=i}r.pieces=s.length>0?s:[new n("",d)];const c=l.length>0?l:[new n("",d)],h=this.addBlockAfter(this.document.blocks,e,{dataId:i,class:"paragraph-block",pieces:c,type:"text"});this.document.blocks=h}else this.document.blocks.push({dataId:i,class:"paragraph-block",pieces:[new n("",d)],type:"text"})}else{let t={dataId:i,class:"paragraph-block",pieces:[new n("",d)],type:"text"},e="";if("ol"===r.listType?(t.listType="li",t.listStart=r.listStart+1,t.parentId=r.dataId,e=r.dataId):"li"===r.listType?(t.listType="li",t.listStart=r.listStart+1,t.parentId=r.parentId,e=r.parentId):"ul"===r.listType&&(t.listType="ul",t.parentId=r.parentId||r.dataId),this.document.blocks.splice(l+1,0,t),"ol"===r.listType||"li"===r.listType)for(let t=l+2;tt.dataId===this.imageHandler.highLightedImageDataId);return this.imageHandler.deleteImage(),void this.imageHandler.setCursorPostion(1,this.document.blocks[t-1].dataId)}const e=window.getSelection();console.log(e,"selection lntgerr");if((this.document.selectAll||this.document.dataIds.length===this.document.blocks.length&&this.document.dataIds.length>0||this.document.dataIds.length>1)&&!(null===(i=window.getSelection())||void 0===i?void 0:i.isCollapsed)){this.undoRedoManager.saveUndoSnapshot();const t=this.document.dataIds[0],e=this.document.blocks.findIndex(e=>e.dataId===t);this.document.deleteBlocks();let i=null,o=0;if(0===this.document.blocks.length){const t=`data-id-${Date.now()}`;this.document.blocks.push({dataId:t,class:"paragraph-block",pieces:[new n(" ")],type:"text"}),i=t,o=0,this.editorView.render()}else if(et+e.text.length,0)}return void this.setCursorPosition(o,i)}if(s>o){this.undoRedoManager.saveUndoSnapshot();const t=Math.min(this.document.currentOffset,o);this.document.deleteRange(o,s,this.document.selectedBlockId,t,!0),this.setCursorPosition(o-1);const e=this.document.blocks.findIndex(t=>t.dataId===this.document.selectedBlockId);console.log(e,"index lntgerr");if(null===document.querySelector(`[data-id="${this.document.selectedBlockId}"]`)){let t=0;console.log(t," listStart lntgerr");const e=this.document.blocks.map((e,n)=>(void 0===(null==e?void 0:e.listType)&&null===(null==e?void 0:e.listType)||("ol"===(null==e?void 0:e.listType)?(t=1,e.listStart=1):"li"===(null==e?void 0:e.listType)&&(t+=1,e.listStart=t)),e));console.log(e,"blocks lntgerr"),this.document.emit("documentChanged",this)}}else o===s&&o>0&&(this.document.deleteRange(o-1,o,this.document.selectedBlockId,this.document.currentOffset,!0),this.setCursorPosition(o-1))}else if(1!==t.key.length||t.ctrlKey||t.metaKey||t.altKey){if("Delete"===t.key){if(t.preventDefault(),o===s){if(this.undoRedoManager.saveUndoSnapshot(),s>o){const t=Math.min(this.document.currentOffset,o);this.document.deleteRange(o,s,this.document.selectedBlockId,t),this.setCursorPosition(o)}else if(s>o)return this.undoRedoManager.saveUndoSnapshot(),void this.document.deleteRange(o,s,this.document.selectedBlockId);const t=this.document.blocks.findIndex(t=>t.dataId===this.document.selectedBlockId);if(-1===t)return;const e=this.document.blocks[t].pieces.reduce((t,e)=>t+e.text.length,0);o-this.document.currentOffseto&&(this.undoRedoManager.saveUndoSnapshot(),this.document.deleteRange(o,s,this.document.selectedBlockId),this.setCursorPosition(o))}this.hyperlinkHandler.hideHyperlinkViewButton()}}else t.preventDefault(),s>o&&(this.undoRedoManager.saveUndoSnapshot(),this.document.deleteRange(o,s,this.document.selectedBlockId,this.document.currentOffset,!1)),console.log("insertat",t.key,this.currentAttributes,o,this.document.selectedBlockId,this.document.currentOffset,"","",!t.isTrusted||!1),this.document.insertAt(t.key,this.currentAttributes,o,this.document.selectedBlockId,this.document.currentOffset,"","",!t.isTrusted||!1),this.setCursorPosition(o+1)}extractTextFromDataId(t){const e=window.getSelection();if(console.log("selection::",e),!e||0===e.rangeCount)return{remainingText:"",piece:null};const n=e.getRangeAt(0).startContainer;let i="";console.log(0,"count lntgerr");const o=this.document.blocks.filter(e=>{if(e.dataId===t)return e}),s=document.querySelector(`[data-id="${t}"]`),l=this.document.getCursorOffsetInParent(`[data-id="${t}"]`);let r=[],a=0;if(o[0].pieces.forEach((t,e)=>{i+=t.text,(null==l?void 0:l.innerText)===t.text&&(a=e,r.push(t))}),o[0].pieces.length>1&&o[0].pieces.forEach((t,e)=>{at.dataId===e);if(-1===i)return console.error(`Block with dataId "${e}" not found.`),t;return[...t.slice(0,i+1),n,...t.slice(i+1)]}syncCurrentAttributesWithCursor(){var t;const[e,n]=this.getSelectionRange();console.log("log1",{start:e,end:n});const i=this.document.blocks.findIndex(t=>t.dataId===this.document.selectedBlockId);if("image"===(null===(t=this.document.blocks[i])||void 0===t?void 0:t.type)?this.imageHandler.addStyleToImage(this.document.selectedBlockId||""):this.imageHandler.isImageHighlighted&&this.imageHandler.clearImageStyling(),e===n){const t=this.document.findPieceAtOffset(e,this.document.selectedBlockId);t?(t!==this.lastPiece&&(this.manualOverride=!1,this.lastPiece=t),this.manualOverride||(this.currentAttributes={bold:t.attributes.bold,italic:t.attributes.italic,underline:t.attributes.underline,strikethrough:t.attributes.strikethrough||!1,hyperlink:t.attributes.hyperlink||!1,fontFamily:t.attributes.fontFamily,fontSize:t.attributes.fontSize,fontColor:t.attributes.fontColor,bgColor:t.attributes.bgColor},this.toolbarView.updateActiveStates(this.currentAttributes),this.popupToolbarView.updateActiveStates(this.currentAttributes)),this.hyperlinkHandler.hideHyperlinkViewButton()):(this.hyperlinkHandler.hideHyperlinkViewButton(),this.manualOverride||(this.currentAttributes={bold:!1,italic:!1,underline:!1,strikethrough:!1,hyperlink:!1},this.toolbarView.updateActiveStates(this.currentAttributes),this.popupToolbarView.updateActiveStates(this.currentAttributes)),this.lastPiece=null)}else{this.hyperlinkHandler.hideHyperlinkViewButton();const t=this.document.isRangeEntirelyAttribute(e,n,"bold"),i=this.document.isRangeEntirelyAttribute(e,n,"italic"),o=this.document.isRangeEntirelyAttribute(e,n,"underline"),s=this.document.isRangeEntirelyAttribute(e,n,"strikethrough");this.currentAttributes={bold:t,italic:i,underline:o,strikethrough:s,hyperlink:!1},this.toolbarView.updateActiveStates(this.currentAttributes),this.popupToolbarView.updateActiveStates(this.currentAttributes)}}setCursorPosition(t,e=""){if(""===e)this.editorView.container.focus();else{const t=document.querySelector('[data-id="'+e+'"]');t&&t.focus()}const n=window.getSelection();if(!n)return;const i=document.createRange();let o=0;const s=[this.editorView.container];let l;for(;l=s.pop();)if(3===l.nodeType){const e=l,n=o+e.length;if(t>=o&&t<=n){i.setStart(e,t-o),i.collapse(!0);break}o=n}else if("BR"===l.tagName){if(t===o){i.setStartBefore(l),i.collapse(!0);break}o++}else{const t=l;let e=t.childNodes.length;for(;e--;)s.push(t.childNodes[e])}n.removeAllRanges(),n.addRange(i)}showAcknowledgement(t,e=2e3){const n=document.getElementById(u.TOAST_ID);n&&n.remove();const i=document.createElement("div");i.id=u.TOAST_ID,i.className="ti-toast",i.textContent=t||u.TOAST_DEFAULT_MESSAGE,document.body.appendChild(i),i.offsetHeight,i.classList.add(u.TOAST_SHOW_CLASS),setTimeout(()=>{i.classList.remove(u.TOAST_SHOW_CLASS),setTimeout(()=>i.remove(),200)},e||u.TOAST_DEFAULT_DURATION_MS)}showLinkPopup(t,e,n){this.linkPopupView.show(t,e,n)}hideLinkPopup(){this.linkPopupView.hide()}openLink(t){window.open(t,"_blank"),this.hideLinkPopup()}unlinkText(t){this.undoRedoManager.saveUndoSnapshot();const e=t.textContent||"",n=(this.editorView.container.textContent||"").indexOf(e);-1!==n&&(this.document.formatAttribute(n,n+e.length,"hyperlink",!1),this.editorView.render()),this.hideLinkPopup()}onContentChange(t){this.on("contentChange",t)}getContent(){return this.document.getHtmlContent()||""}getTextContent(){var t;return(null===(t=this.editorContainer)||void 0===t?void 0:t.textContent)||""}}window.TextIgniter=L,t.TextIgniter=L});
diff --git a/packages/core/index.html b/packages/core/index.html
index 75b4b76..be9b8c8 100644
--- a/packages/core/index.html
+++ b/packages/core/index.html
@@ -50,7 +50,8 @@ Real-time Content Preview:
'bgColor',
'getHtmlContent',
'loadHtmlContent',
- 'speechtotext'
+ 'speechtotext',
+ 'emoji'
// "subscript",
// "superscript",
// "insert_table",
diff --git a/packages/core/src/TextIgniter.ts b/packages/core/src/TextIgniter.ts
index 12e8953..8bcd172 100644
--- a/packages/core/src/TextIgniter.ts
+++ b/packages/core/src/TextIgniter.ts
@@ -18,6 +18,7 @@ import { detectUrlsInText } from './utils/urlDetector';
import EventEmitter from './utils/events';
import { SpeechToTextHandler } from './handlers/speechToText';
import { icons } from './assets/icons';
+import EmojiPickerView from './view/emojiPickerView';
// Link functionality imports
export interface CurrentAttributeDTO {
@@ -52,6 +53,7 @@ class TextIgniter extends EventEmitter {
savedSelection: { start: number; end: number } | null = null;
debounceTimer: NodeJS.Timeout | null = null;
undoRedoManager: UndoRedoManager;
+ emojiPickerView: EmojiPickerView;
constructor(editorId: string, config: EditorConfig) {
super();
@@ -138,6 +140,42 @@ class TextIgniter extends EventEmitter {
btn.insertAdjacentHTML('afterbegin', icons.start_microphone);
btn.dataset.tooltip = 'start';
}
+
+ this.emojiPickerView = new EmojiPickerView();
+ this.emojiPickerView.onSelect((char: string) => {
+ if (this.savedSelection) {
+ this.setCursorPosition(this.savedSelection.start);
+ }
+
+ const [start, end] = this.getSelectionRange();
+
+ if (end > start) {
+ this.document.deleteRange(
+ start,
+ end,
+ this.document.selectedBlockId,
+ this.document.currentOffset,
+ false
+ );
+ }
+
+ this.document.insertAt(
+ char,
+ { ...this.currentAttributes },
+ start,
+ this.document.selectedBlockId,
+ 0,
+ '',
+ 'batch'
+ );
+
+ const newPos = start + char.length;
+
+ this.savedSelection = { start: newPos, end: newPos };
+
+ this.setCursorPosition(newPos);
+ });
+
this.currentAttributes = {
bold: false,
italic: false,
@@ -745,6 +783,19 @@ class TextIgniter extends EventEmitter {
case 'speechtotext':
this.speechToTextHandler.toggleRecording();
break;
+ case 'emoji':
+ this.savedSelection = saveSelection(this.editorView.container);
+
+ const emojiBtn = document.querySelector(
+ '[data-action="emoji"]'
+ ) as HTMLElement;
+ emojiBtn.addEventListener('mousedown', e => {
+ e.preventDefault();
+ });
+ if (emojiBtn) {
+ this.emojiPickerView.open(emojiBtn);
+ }
+ break;
default:
if (start < end) {
this.undoRedoManager.saveUndoSnapshot();
diff --git a/packages/core/src/assets/icons.ts b/packages/core/src/assets/icons.ts
index ff4971b..0cef818 100644
--- a/packages/core/src/assets/icons.ts
+++ b/packages/core/src/assets/icons.ts
@@ -147,4 +147,12 @@ export const icons = {
`,
+
+ emoji: ``,
};
diff --git a/packages/core/src/config/editorConfig.ts b/packages/core/src/config/editorConfig.ts
index 6595eee..0567289 100644
--- a/packages/core/src/config/editorConfig.ts
+++ b/packages/core/src/config/editorConfig.ts
@@ -9,7 +9,7 @@ const featureGroups = {
formatting: ['bold', 'italic', 'underline', 'strikethrough'],
alignment: ['alignLeft', 'alignCenter', 'alignRight'],
lists: ['unorderedList', 'orderedList'],
- media: ['hyperlink', 'image'],
+ media: ['hyperlink', 'image', 'emoji'],
utility: ['getHtmlContent', 'loadHtmlContent'],
};
@@ -100,6 +100,7 @@ export function createEditor(
fontColor: 'Text Color',
bgColor: 'Highlight Color',
image: 'Insert Image',
+ emoji: 'Emoji',
getHtmlContent: 'Get HTML',
loadHtmlContent: 'Load HTML',
};
@@ -111,6 +112,7 @@ export function createEditor(
{ feature: 'unorderedList', id: 'unorderedList', icon: icons.bullet_list },
{ feature: 'orderedList', id: 'orderedList', icon: icons.numbered_list },
{ feature: 'hyperlink', id: 'hyperlink', icon: icons.hyperlink },
+ { feature: 'emoji', id: 'emoji', icon: icons.emoji },
{
feature: 'strikethrough',
id: 'strikethrough',
diff --git a/packages/core/src/constants/emojis.ts b/packages/core/src/constants/emojis.ts
new file mode 100644
index 0000000..8a01e10
--- /dev/null
+++ b/packages/core/src/constants/emojis.ts
@@ -0,0 +1,23 @@
+import { EmojiCategory } from '../types/emoji.type';
+
+export const EMOJI_CATEGORIES: EmojiCategory[] = [
+ {
+ label: 'Smileys & People',
+ items: [
+ { char: '😀', name: 'grinning face', shortcode: ':grinning:' },
+ { char: '😃', name: 'big eyes smile', shortcode: ':smiley:' },
+ { char: '😄', name: 'smiling eyes grin', shortcode: ':smile:' },
+ { char: '😁', name: 'beaming grin', shortcode: ':grin:' },
+ { char: '😆', name: 'squinting laugh', shortcode: ':laughing:' },
+ { char: '😅', name: 'sweat smile', shortcode: ':sweat_smile:' },
+ { char: '🤣', name: 'rolling floor laughing', shortcode: ':rofl:' },
+ { char: '😂', name: 'tears of joy', shortcode: ':joy:' },
+ {
+ char: '🙂',
+ name: 'slightly smiling',
+ shortcode: ':slightly_smiling_face:',
+ },
+ { char: '😊', name: 'smiling eyes blush', shortcode: ':blush:' },
+ ],
+ },
+];
diff --git a/packages/core/src/types/emoji.type.ts b/packages/core/src/types/emoji.type.ts
new file mode 100644
index 0000000..2c2eede
--- /dev/null
+++ b/packages/core/src/types/emoji.type.ts
@@ -0,0 +1,10 @@
+export interface EmojiItem {
+ char: string;
+ name: string;
+ shortcode: string;
+}
+
+export interface EmojiCategory {
+ label: string;
+ items: EmojiItem[];
+}
diff --git a/packages/core/src/view/emojiPickerView.ts b/packages/core/src/view/emojiPickerView.ts
new file mode 100644
index 0000000..3b5a7c6
--- /dev/null
+++ b/packages/core/src/view/emojiPickerView.ts
@@ -0,0 +1,243 @@
+import { EMOJI_CATEGORIES } from '../constants/emojis';
+import { EmojiItem } from '../types/emoji.type';
+
+const RECENT_KEY = 'recent_emojies';
+const MAX_RECENT = 24;
+
+class EmojiPickerView {
+ private popup: HTMLElement;
+ private gridArea: HTMLElement;
+ private searchInput: HTMLInputElement;
+ private onSelectCallback?: (char: string) => void;
+ private isOpen: boolean = false;
+
+ constructor() {
+ this.popup = this.buildPopup();
+ this.gridArea = this.popup.querySelector('.emoji_grid') as HTMLElement;
+ this.searchInput = this.popup.querySelector(
+ '.emoji_serch'
+ ) as HTMLInputElement;
+ document.body.appendChild(this.popup);
+
+ // in outside click close the modal
+ document.addEventListener('mousedown', e => {
+ if (this.isOpen && !this.popup.contains(e.target as Node)) {
+ const clickedBtn = (e.target as HTMLElement).closest(
+ '[data-action="emoji"]'
+ );
+ if (!clickedBtn) this.close();
+ }
+ });
+ }
+
+ onSelect(cb: (char: string) => void) {
+ this.onSelectCallback = cb;
+ }
+
+ open(element: HTMLElement) {
+ const rect = element.getBoundingClientRect();
+ const popupWidth = 320;
+ let left = rect.left + window.scrollX;
+ if (left + popupWidth > window.innerWidth - 8) {
+ left = window.innerWidth - popupWidth - 8;
+ }
+ const top = rect.bottom + window.scrollY + 4;
+
+ this.popup.style.left = `${left}px`;
+ this.popup.style.top = `${top}px`;
+ this.popup.style.display = 'flex';
+ this.isOpen = true;
+
+ // reset the state
+ this.searchInput.value = '';
+ this.renderGrid('');
+ }
+
+ close() {
+ this.popup.style.display = 'none';
+ this.isOpen = false;
+ }
+
+ getIsOpen() {
+ return this.isOpen;
+ }
+
+ private buildPopup(): HTMLElement {
+ const popup = document.createElement('div');
+ popup.style.cssText = `
+ position: absolute;
+ display: none;
+ flex-direction: column;
+ width: 320px;
+ max-height: 380px;
+ background: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 10px;
+ box-shadow: 0 6px 24px rgba(0,0,0,0.14);
+ z-index: 9999;
+ overflow: hidden;
+ font-family: system-ui, -apple-system, sans-serif;
+ `;
+
+ const header = document.createElement('div');
+ header.style.cssText = `
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 12px;
+ border-bottom: 1px solid #f0f0f0;
+ background: #fafafa;
+ `;
+
+ const search = document.createElement('input');
+ search.type = 'text';
+ search.placeholder = '🔍 Search emojis or :shortcode:';
+ search.className = 'emoji_serch';
+ search.style.cssText = `
+ flex: 1;
+ padding: 6px 10px;
+ border: 1px solid #ccc;
+ border-radius: 6px;
+ font-size: 13px;
+ outline: none;
+ background: #fff;
+ `;
+ search.addEventListener('input', () =>
+ this.renderGrid(search.value.trim())
+ );
+
+ header.appendChild(search);
+
+ const gridArea = document.createElement('div');
+ gridArea.className = 'emoji_grid';
+ gridArea.style.cssText = `
+ flex: 1;
+ overflow-y: auto;
+ padding: 10px 12px 12px;
+ `;
+
+ popup.appendChild(header);
+ popup.appendChild(gridArea);
+
+ return popup;
+ }
+
+ private getRecentEmojis(): EmojiItem[] {
+ try {
+ const raw = localStorage.getItem(RECENT_KEY);
+ return raw ? JSON.parse(raw) : [];
+ } catch {
+ return [];
+ }
+ }
+
+ private saveRecentEmoji(item: EmojiItem) {
+ const recents = this.getRecentEmojis().filter(e => e.char !== item.char);
+ recents.unshift(item);
+ if (recents.length > MAX_RECENT) recents.length = MAX_RECENT;
+ try {
+ localStorage.setItem(RECENT_KEY, JSON.stringify(recents));
+ } catch (e) {
+ console.error('Problem occur in saving emojies', e);
+ }
+ }
+
+ private resolveChar(item: EmojiItem): string {
+ return item.char;
+ }
+
+ private renderGrid(query: string) {
+ this.gridArea.innerHTML = '';
+ const q = query.toLowerCase().replace(/^:/, '').replace(/:$/, '');
+
+ const renderCategory = (label: string, items: EmojiItem[]) => {
+ if (!items.length) return;
+
+ const section = document.createElement('div');
+ section.style.marginBottom = '12px';
+
+ const title = document.createElement('div');
+ title.textContent = label;
+ title.style.cssText = `
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ color: #999;
+ margin-bottom: 6px;
+ `;
+ section.appendChild(title);
+
+ const grid = document.createElement('div');
+ grid.style.cssText = `
+ display: grid;
+ grid-template-columns: repeat(8, 1fr);
+ gap: 2px;
+ `;
+
+ items.forEach(item => {
+ const char = this.resolveChar(item);
+ const btn = document.createElement('button');
+ btn.textContent = char;
+ btn.title = `${item.name} ${item.shortcode}`;
+ btn.style.cssText = `
+ font-size: 20px;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ border-radius: 5px;
+ padding: 4px;
+ line-height: 1.2;
+ transition: background 0.1s;
+ aspect-ratio: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ `;
+ btn.addEventListener(
+ 'mouseenter',
+ () => (btn.style.background = '#f0f0f0')
+ );
+ btn.addEventListener(
+ 'mouseleave',
+ () => (btn.style.background = 'transparent')
+ );
+ btn.addEventListener('mousedown', e => {
+ e.preventDefault();
+ this.saveRecentEmoji(item);
+ this.onSelectCallback?.(char);
+ });
+ grid.appendChild(btn);
+ });
+
+ section.appendChild(grid);
+ this.gridArea.appendChild(section);
+ };
+
+ if (!q) {
+ const recents = this.getRecentEmojis();
+ renderCategory('Recently Used', recents);
+ EMOJI_CATEGORIES.forEach(cat => renderCategory(cat.label, cat.items));
+ } else {
+ const results: EmojiItem[] = [];
+ EMOJI_CATEGORIES.forEach(cat => {
+ cat.items.forEach(item => {
+ if (item.name.includes(q) || item.shortcode.includes(q)) {
+ results.push(item);
+ }
+ });
+ });
+ renderCategory(`Results for "${q}"`, results);
+ }
+
+ if (!this.gridArea.querySelector('button')) {
+ const empty = document.createElement('div');
+ empty.textContent = 'No emojis found';
+ empty.style.cssText =
+ 'text-align: center; color: #aaa; padding: 24px 0; font-size: 13px;';
+ this.gridArea.appendChild(empty);
+ }
+ }
+}
+
+export default EmojiPickerView;