@meenainwal/rich-text-editor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReadME.md +76 -0
- package/dist/rich-text-editor.css +1 -0
- package/dist/test-editor.cjs +9 -0
- package/dist/test-editor.cjs.map +1 -0
- package/dist/test-editor.mjs +862 -0
- package/dist/test-editor.mjs.map +1 -0
- package/package.json +45 -0
package/ReadME.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Premium Rich Text Editor
|
|
2
|
+
|
|
3
|
+
A lightweight, framework-agnostic, and beautifully designed rich text editor built with TypeScript. Featuring a sophisticated **Slate & Indigo** design system, it provides a premium writing experience with modern interactive states and smooth transitions.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## โจ Features
|
|
8
|
+
|
|
9
|
+
- ๐
**Premium UI**: Modern aesthetic with a curated color palette and refined geometry.
|
|
10
|
+
- ๐ **Zero Dependencies**: Pure Vanilla JS/TypeScript implementation.
|
|
11
|
+
- ๐ **Framework Agnostic**: Works perfectly with React, Vue, Svelte, or Next.js.
|
|
12
|
+
- ๐ **Clean HTML**: Produces semantic and sanitized HTML output.
|
|
13
|
+
- ๐ **Smart Links**: Automatically adds `target="_blank"` and security attributes.
|
|
14
|
+
- ๐ก **Advanced Formatting**: Headings (H1-H6), dynamic font sizes, font families, and more.
|
|
15
|
+
|
|
16
|
+
## ๐ฆ Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @meenainwal/rich-text-editor
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## ๐ Quick Start
|
|
23
|
+
|
|
24
|
+
### Basic Usage
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import { CoreEditor } from '@meenainwal/rich-text-editor';
|
|
28
|
+
import '@meenainwal/rich-text-editor/dist/test-editor.css';
|
|
29
|
+
|
|
30
|
+
const container = document.getElementById('editor');
|
|
31
|
+
const editor = new CoreEditor(container, {
|
|
32
|
+
placeholder: 'Type something beautiful...',
|
|
33
|
+
autofocus: true
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Get content
|
|
37
|
+
const content = editor.getHTML();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### In React
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { useEffect, useRef } from 'react';
|
|
44
|
+
import { CoreEditor } from '@meenainwal/rich-text-editor';
|
|
45
|
+
import '@meenainwal/rich-text-editor/dist/test-editor.css';
|
|
46
|
+
|
|
47
|
+
export const EditorComponent = () => {
|
|
48
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (containerRef.current) {
|
|
52
|
+
new CoreEditor(containerRef.current);
|
|
53
|
+
}
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
return <div ref={containerRef} />;
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## โ๏ธ Configuration
|
|
61
|
+
|
|
62
|
+
| Option | Type | Default | Description |
|
|
63
|
+
| :--- | :--- | :--- | :--- |
|
|
64
|
+
| `placeholder` | `string` | `undefined` | The placeholder text when the editor is empty. |
|
|
65
|
+
| `autofocus` | `boolean` | `false` | Whether to focus the editor on initialization. |
|
|
66
|
+
|
|
67
|
+
## ๐ API Methods
|
|
68
|
+
|
|
69
|
+
- `getHTML()`: Returns the content as a sanitized HTML string.
|
|
70
|
+
- `setHTML(html)`: Sets the editor content.
|
|
71
|
+
- `focus()`: Programmatically focus the editor.
|
|
72
|
+
- `execute(command, value)`: Execute standard editor commands.
|
|
73
|
+
|
|
74
|
+
## ๐ License
|
|
75
|
+
|
|
76
|
+
MIT ยฉ [Anuj Nainwal](https://github.com/anujnainwal)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--te-primary-color: #6366f1;--te-primary-hover: #4f46e5;--te-bg-app: #f8fafc;--te-bg-editor: #ffffff;--te-toolbar-bg: #ffffff;--te-border-color: #e2e8f0;--te-border-focus: #cbd5e1;--te-text-main: #1e293b;--te-text-muted: #64748b;--te-placeholder: #94a3b8;--te-btn-hover: #f1f5f9;--te-btn-active: #e2e8f0;--te-radius-lg: 12px;--te-radius-md: 8px;--te-radius-sm: 6px;--te-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--te-shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--te-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--te-transition: all .2s cubic-bezier(.4, 0, .2, 1)}.te-container{display:flex;flex-direction:column;height:500px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-lg);background:var(--te-bg-editor);box-shadow:var(--te-shadow-sm);overflow:hidden;font-family:Inter,-apple-system,system-ui,sans-serif;color:var(--te-text-main);transition:var(--te-transition);max-width:100%}.te-container:focus-within{border-color:var(--te-primary-color);box-shadow:0 0 0 4px #6366f11a,var(--te-shadow-md)}.te-toolbar{display:flex;flex-wrap:wrap;gap:6px;padding:10px 12px;border-bottom:1px solid var(--te-border-color);background:var(--te-toolbar-bg);align-items:center;-webkit-user-select:none;user-select:none;position:sticky;top:0;z-index:10}.te-divider{width:1px;height:20px;background-color:var(--te-border-color);margin:0 6px}.te-button,.te-select,.te-input{display:flex;align-items:center;justify-content:center;height:32px;border:1px solid transparent;background:transparent;border-radius:var(--te-radius-sm);cursor:pointer;color:var(--te-text-muted);font-size:13px;font-weight:500;transition:var(--te-transition);box-sizing:border-box}.te-button{width:32px;padding:0}.te-button svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.2;fill:none}.te-select{padding:0 24px 0 8px;min-width:120px;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;background-size:12px;border:1px solid var(--te-border-color);background-color:#fff}.te-input{width:56px;padding:0 4px;text-align:center;cursor:text;border:1px solid var(--te-border-color);background-color:#fff}.te-color-picker{width:32px;height:32px;padding:4px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);background:#fff;cursor:pointer;box-sizing:border-box}.te-color-picker:hover{border-color:var(--te-border-focus)}.te-emoji-picker{position:absolute;width:280px;height:320px;background:#fff;border:1px solid var(--te-border-color);border-radius:var(--te-radius-md);box-shadow:var(--te-shadow-lg);display:flex;flex-direction:column;z-index:1000;animation:te-fade-in .2s ease-out}@keyframes te-fade-in{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.te-emoji-header{padding:12px;border-bottom:1px solid var(--te-border-color)}.te-emoji-search{width:100%;padding:8px 12px;border:1px solid var(--te-border-color);border-radius:var(--te-radius-sm);font-size:13px;outline:none;transition:var(--te-transition)}.te-emoji-search:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a}.te-emoji-body{flex:1;overflow-y:auto;padding:8px}.te-emoji-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.te-emoji-category-title{grid-column:span 7;padding:8px 4px 4px;font-size:11px;font-weight:600;color:var(--te-text-muted);text-transform:uppercase;letter-spacing:.05em}.te-emoji-item{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:20px;border:none;background:transparent;cursor:pointer;border-radius:var(--te-radius-sm);transition:var(--te-transition)}.te-emoji-item:hover{background:var(--te-btn-hover);transform:scale(1.1)}.te-emoji-empty{grid-column:span 7;text-align:center;padding:20px;color:var(--te-text-muted);font-size:13px}.te-button:hover{background:var(--te-btn-hover);color:var(--te-text-main)}.te-select:hover,.te-input:hover{border-color:var(--te-border-focus)}.te-button.active{background:var(--te-btn-active);color:var(--te-primary-color);border-color:#6366f133}.te-select:focus,.te-input:focus{border-color:var(--te-primary-color);box-shadow:0 0 0 2px #6366f11a;outline:none;background:#fff;color:var(--te-text-main)}.te-content{flex:1;overflow-y:auto;min-height:240px;padding:24px;line-height:1.25;outline:none;font-size:16px}.te-content p{margin:0 0 1.25em}.te-content h1,.te-content h2,.te-content h3,.te-content h4,.te-content h5,.te-content h6{color:var(--te-text-main);font-weight:700;margin:1.5em 0 .5em;line-height:1.25}.te-content h1:first-child,.te-content p:first-child{margin-top:0}.te-content h1{font-size:2.25em}.te-content h2{font-size:1.875em}.te-content h3{font-size:1.5em}.te-content h4{font-size:1.25em}.te-content[data-placeholder]:empty:before{content:attr(data-placeholder);color:var(--te-placeholder);pointer-events:none}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class g{getSelection(){return window.getSelection()}getRange(){const e=this.getSelection();return!e||e.rangeCount===0?null:e.getRangeAt(0)}saveSelection(){const e=this.getRange();return e?e.cloneRange():null}restoreSelection(e){if(!e)return;const t=this.getSelection();t&&(t.removeAllRanges(),t.addRange(e))}isSelectionInElement(e){const t=this.getRange();return t?e.contains(t.commonAncestorContainer):!1}clearSelection(){const e=this.getSelection();e&&e.removeAllRanges()}}class j{container;editableElement;selection;options;pendingStyles={};constructor(e,t={}){this.container=e,this.container.classList.add("te-container"),this.options=t,this.selection=new g,this.editableElement=this.createEditableElement(),this.setupInputHandlers(),this.container.appendChild(this.editableElement),this.options.autofocus&&this.focus(),document.execCommand("defaultParagraphSeparator",!1,"p")}setupInputHandlers(){this.editableElement.addEventListener("beforeinput",e=>{if(e.inputType==="insertText"&&Object.keys(this.pendingStyles).length>0){const t=e.data;if(!t)return;e.preventDefault();const i=document.createElement("span");for(const[a,n]of Object.entries(this.pendingStyles))i.style.setProperty(a,n);i.textContent=t;const o=this.selection.getRange();if(o){o.deleteContents(),o.insertNode(i);const a=document.createRange();a.setStart(i.firstChild,t.length),a.setEnd(i.firstChild,t.length),this.selection.restoreSelection(a),this.pendingStyles={},this.editableElement.dispatchEvent(new Event("input",{bubbles:!0}))}}}),document.addEventListener("selectionchange",()=>{const e=window.getSelection();e&&e.rangeCount>0&&(e.getRangeAt(0).collapsed||(this.pendingStyles={}))})}createEditableElement(){const e=document.createElement("div");return e.setAttribute("contenteditable","true"),e.setAttribute("role","textbox"),e.setAttribute("spellcheck","true"),e.classList.add("te-content"),this.options.placeholder&&e.setAttribute("data-placeholder",this.options.placeholder),e.style.minHeight="150px",e.style.outline="none",e.style.padding="1rem",e.innerHTML===""&&(e.innerHTML="<p><br></p>"),e}focus(){this.editableElement.focus()}execute(e,t=null){this.focus(),document.execCommand(e,!1,t??void 0),this.editableElement.dispatchEvent(new Event("input",{bubbles:!0}))}clearStyleRecursive(e,t){const i=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT);let o=i.nextNode();for(;o;)o.style.getPropertyValue(t)&&o.style.removeProperty(t),o=i.nextNode()}setStyle(e,t,i){if(e==="font-size"){const n=parseInt(t,10);isNaN(n)||(t=`${Math.max(1,Math.min(100,n))}px`)}if(!i){const n=window.getSelection();if(!n||n.rangeCount===0)return null;i=n.getRangeAt(0)}if(i.collapsed)return this.pendingStyles[e]=t,i;let o=i.commonAncestorContainer;o.nodeType===Node.TEXT_NODE&&(o=o.parentElement);let a=null;if(o.tagName==="SPAN"&&o.children.length===0&&o.textContent===i.toString())o.style.setProperty(e,t),a=i.cloneRange();else{const n=document.createElement("span");n.style.setProperty(e,t);try{const r=o.tagName==="SPAN"?o:null,y=i.extractContents();this.clearStyleRecursive(y,e),n.appendChild(y),i.insertNode(n),r&&r.innerHTML===""&&r.remove();const l=document.createRange();l.selectNodeContents(n),a=l;const c=window.getSelection();c&&c.rangeCount>0&&(c.removeAllRanges(),c.addRange(l))}catch(r){console.warn("Failed to apply style:",r)}}return this.editableElement.dispatchEvent(new Event("input",{bubbles:!0})),a}createLink(e){this.focus(),!/^https?:\/\//i.test(e)&&!/^mailto:/i.test(e)&&!e.startsWith("#")&&(e="https://"+e),document.execCommand("createLink",!1,e);const t=window.getSelection();if(t&&t.rangeCount>0){let o=t.getRangeAt(0).commonAncestorContainer;o.nodeType===Node.TEXT_NODE&&(o=o.parentElement);let a=null;o.tagName==="A"?a=o:a=o.querySelector("a"),a&&(a.setAttribute("target","_blank"),a.setAttribute("rel","noopener noreferrer"))}this.editableElement.dispatchEvent(new Event("input",{bubbles:!0}))}getHTML(){return this.editableElement.innerHTML}setHTML(e){this.editableElement.innerHTML=e}get el(){return this.editableElement}}const u={type:"button",title:"Undo",command:"undo",icon:'<svg viewBox="0 0 24 24"><path d="M9 14L4 9l5-5"></path><path d="M20 20v-7a4 4 0 0 0-4-4H4"></path></svg>'},p={type:"button",title:"Redo",command:"redo",icon:'<svg viewBox="0 0 24 24"><path d="M15 14l5-5-5-5"></path><path d="M4 20v-7a4 4 0 0 1 4-4h12"></path></svg>'},v={type:"select",title:"Heading",command:"formatBlock",options:[{label:"Paragraph",value:"P"},{label:"Heading 1",value:"H1"},{label:"Heading 2",value:"H2"},{label:"Heading 3",value:"H3"},{label:"Heading 4",value:"H4"},{label:"Heading 5",value:"H5"},{label:"Heading 6",value:"H6"}]},b={type:"select",title:"Font",command:"fontFamily",options:[{label:"Inter",value:"'Inter', sans-serif"},{label:"Arial",value:"Arial, sans-serif"},{label:"Georgia",value:"Georgia, serif"},{label:"Courier",value:"'Courier New', monospace"},{label:"Times New Roman",value:"'Times New Roman', serif"},{label:"Verdana",value:"Verdana, sans-serif"},{label:"Tahoma",value:"Tahoma, sans-serif"},{label:"Roboto",value:"'Roboto', sans-serif"},{label:"Open Sans",value:"'Open Sans', sans-serif"},{label:"Montserrat",value:"'Montserrat', sans-serif"},{label:"Lato",value:"'Lato', sans-serif"},{label:"Poppins",value:"'Poppins', sans-serif"},{label:"Oswald",value:"'Oswald', sans-serif"},{label:"Playfair Display",value:"'Playfair Display', serif"},{label:"Merriweather",value:"'Merriweather', serif"}]},f={type:"input",title:"Size (px)",command:"fontSize",placeholder:"Size",value:"16"},S={type:"button",title:"Bold",command:"bold",icon:'<svg viewBox="0 0 24 24"><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path></svg>'},x={type:"button",title:"Italic",command:"italic",icon:'<svg viewBox="0 0 24 24"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg>'},w={type:"button",title:"Underline",command:"underline",icon:'<svg viewBox="0 0 24 24"><path d="M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg>'},A={type:"button",title:"Strikethrough",command:"strikeThrough",icon:'<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"></line><path d="M16 4.9C15.1 4.3 13.9 4 12.6 4c-3.1 0-5.6 1.8-5.6 4s1.8 3.3 4.4 3.8"></path><path d="M7 19.1c.9.6 2.1.9 3.4.9 3.1 0 5.6-1.8 5.6-4s-1.8-3.3-4.4-3.8"></path></svg>'},k={type:"color-picker",title:"Text Color",command:"foreColor",value:"#1e293b"},E={type:"color-picker",title:"Highlight Color",command:"backColor",value:"#ffffff"},F={type:"button",title:"Align Left",command:"justifyLeft",icon:'<svg viewBox="0 0 24 24"><line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line></svg>'},L={type:"button",title:"Align Center",command:"justifyCenter",icon:'<svg viewBox="0 0 24 24"><line x1="18" y1="10" x2="6" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="18" y1="18" x2="6" y2="18"></line></svg>'},C={type:"button",title:"Align Right",command:"justifyRight",icon:'<svg viewBox="0 0 24 24"><line x1="21" y1="10" x2="7" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="7" y2="18"></line></svg>'},T={type:"button",title:"Justify",command:"justifyFull",icon:'<svg viewBox="0 0 24 24"><line x1="21" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="3" y2="18"></line></svg>'},H={type:"button",title:"Bulleted List",command:"insertUnorderedList",icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><circle cx="3" cy="6" r="1" fill="currentColor"></circle><circle cx="3" cy="12" r="1" fill="currentColor"></circle><circle cx="3" cy="18" r="1" fill="currentColor"></circle></svg>'},O={type:"button",title:"Numbered List",command:"insertOrderedList",icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"></line><line x1="10" y1="12" x2="21" y2="21"></line><line x1="10" y1="18" x2="21" y2="18"></line><path d="M4 6h1v4"></path><path d="M4 10h2"></path><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"></path></svg>'},R={type:"button",title:"Outdent",command:"outdent",icon:'<svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"></polyline><line x1="21" y1="12" x2="9" y2="12"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="18" x2="3" y2="18"></line></svg>'},M={type:"button",title:"Indent",command:"indent",icon:'<svg viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"></polyline><line x1="3" y1="12" x2="15" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>'},I={type:"button",title:"Horizontal Rule",command:"insertHorizontalRule",icon:'<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"></line></svg>'},P={type:"button",title:"Clear Formatting",command:"removeFormat",icon:'<svg viewBox="0 0 24 24"><path d="M17.41 15.41L12 10l-5.41 5.41L5.17 14l5.41-5.41L5.17 3.17 6.59 1.76 12 7.17l5.41-5.41 1.41 1.41-5.41 5.41 5.41 5.41-1.41 1.42z"></path></svg>'},B={type:"button",title:"Insert Emoji",command:"insertEmoji",icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M8 14s1.5 2 4 2 4-2 4-2"></path><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line></svg>'},N={type:"button",title:"Insert Link",command:"createLink",icon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>'},m={type:"divider",title:""},z=[u,p,m,v,b,f,m,S,x,w,A,m,k,E,m,F,L,C,T,m,H,O,R,M,m,I,B,N,P],d=[{emoji:"๐",name:"grinning",category:"Smileys"},{emoji:"๐",name:"smiley",category:"Smileys"},{emoji:"๐",name:"smile",category:"Smileys"},{emoji:"๐",name:"grin",category:"Smileys"},{emoji:"๐",name:"laughing",category:"Smileys"},{emoji:"๐
",name:"sweat smile",category:"Smileys"},{emoji:"๐คฃ",name:"rofl",category:"Smileys"},{emoji:"๐",name:"joy",category:"Smileys"},{emoji:"๐",name:"slight smile",category:"Smileys"},{emoji:"๐",name:"upside down",category:"Smileys"},{emoji:"๐",name:"wink",category:"Smileys"},{emoji:"๐",name:"blush",category:"Smileys"},{emoji:"๐",name:"innocent",category:"Smileys"},{emoji:"๐ฅฐ",name:"smiling face with hearts",category:"Smileys"},{emoji:"๐",name:"heart eyes",category:"Smileys"},{emoji:"๐คฉ",name:"star struck",category:"Smileys"},{emoji:"๐",name:"kissing heart",category:"Smileys"},{emoji:"๐",name:"kissing",category:"Smileys"},{emoji:"๐",name:"kissing closed eyes",category:"Smileys"},{emoji:"๐",name:"yum",category:"Smileys"},{emoji:"๐",name:"stuck out tongue",category:"Smileys"},{emoji:"๐",name:"stuck out tongue winking eye",category:"Smileys"},{emoji:"๐คช",name:"zany face",category:"Smileys"},{emoji:"๐คจ",name:"raised eyebrow",category:"Smileys"},{emoji:"๐ง",name:"monocle",category:"Smileys"},{emoji:"๐ค",name:"nerd",category:"Smileys"},{emoji:"๐",name:"sunglasses",category:"Smileys"},{emoji:"๐ฅณ",name:"partying face",category:"Smileys"},{emoji:"๐",name:"smirk",category:"Smileys"},{emoji:"๐",name:"unamused",category:"Smileys"},{emoji:"๐",name:"disappointed",category:"Smileys"},{emoji:"๐",name:"pensive",category:"Smileys"},{emoji:"๐",name:"worried",category:"Smileys"},{emoji:"๐",name:"confused",category:"Smileys"},{emoji:"๐ซ",name:"tired",category:"Smileys"},{emoji:"๐ฅต",name:"hot face",category:"Smileys"},{emoji:"๐ฅถ",name:"cold face",category:"Smileys"},{emoji:"๐ณ",name:"flushed",category:"Smileys"},{emoji:"๐ฑ",name:"scream",category:"Smileys"},{emoji:"๐คข",name:"nauseated",category:"Smileys"},{emoji:"๐คฎ",name:"vomiting",category:"Smileys"},{emoji:"๐คฌ",name:"cursing",category:"Smileys"},{emoji:"๐คซ",name:"shushing",category:"Smileys"},{emoji:"๐ค",name:"thinking",category:"Smileys"},{emoji:"๐ค",name:"hugs",category:"Smileys"},{emoji:"๐ฅฑ",name:"yawn",category:"Smileys"},{emoji:"๐ด",name:"sleeping",category:"Smileys"},{emoji:"๐คค",name:"drooling",category:"Smileys"},{emoji:"๐ต",name:"dizzy",category:"Smileys"},{emoji:"๐ค",name:"zipper mouth",category:"Smileys"},{emoji:"๐ฅด",name:"woozy",category:"Smileys"},{emoji:"๐ค",name:"fever",category:"Smileys"},{emoji:"๐ค",name:"bandage",category:"Smileys"},{emoji:"๐คก",name:"clown",category:"Smileys"},{emoji:"๐ป",name:"ghost",category:"Smileys"},{emoji:"๐ฝ",name:"alien",category:"Smileys"},{emoji:"๐พ",name:"robot",category:"Smileys"},{emoji:"๐ฉ",name:"poop",category:"Smileys"},{emoji:"โค๏ธ",name:"heart",category:"Symbols"},{emoji:"๐งก",name:"orange heart",category:"Symbols"},{emoji:"๐",name:"yellow heart",category:"Symbols"},{emoji:"๐",name:"green heart",category:"Symbols"},{emoji:"๐",name:"blue heart",category:"Symbols"},{emoji:"๐",name:"purple heart",category:"Symbols"},{emoji:"๐ค",name:"black heart",category:"Symbols"},{emoji:"๐ค",name:"white heart",category:"Symbols"},{emoji:"๐ค",name:"brown heart",category:"Symbols"},{emoji:"๐",name:"broken heart",category:"Symbols"},{emoji:"โฃ๏ธ",name:"heart exclamation",category:"Symbols"},{emoji:"๐",name:"two hearts",category:"Symbols"},{emoji:"๐",name:"revolving hearts",category:"Symbols"},{emoji:"โจ",name:"sparkles",category:"Symbols"},{emoji:"๐ฅ",name:"fire",category:"Symbols"},{emoji:"โญ",name:"star",category:"Symbols"},{emoji:"๐",name:"glowing star",category:"Symbols"},{emoji:"โ
",name:"check",category:"Symbols"},{emoji:"โ",name:"cross",category:"Symbols"},{emoji:"๐ฏ",name:"hundred",category:"Symbols"},{emoji:"๐ข",name:"anger",category:"Symbols"},{emoji:"๐ฅ",name:"collision",category:"Symbols"},{emoji:"๐ซ",name:"dizzy symbol",category:"Symbols"},{emoji:"๐ฆ",name:"sweat drops",category:"Symbols"},{emoji:"๐จ",name:"dash",category:"Symbols"},{emoji:"๐",name:"thumbs up",category:"Hands"},{emoji:"๐",name:"thumbs down",category:"Hands"},{emoji:"๐",name:"ok",category:"Hands"},{emoji:"โ๏ธ",name:"victory",category:"Hands"},{emoji:"๐ค",name:"fingers crossed",category:"Hands"},{emoji:"๐ค",name:"rock on",category:"Hands"},{emoji:"๐ค",name:"horns",category:"Hands"},{emoji:"๐ค",name:"call me",category:"Hands"},{emoji:"๐",name:"point left",category:"Hands"},{emoji:"๐",name:"point right",category:"Hands"},{emoji:"๐",name:"point up",category:"Hands"},{emoji:"๐",name:"point down",category:"Hands"},{emoji:"๐๏ธ",name:"hand splayed",category:"Hands"},{emoji:"โ",name:"raised hand",category:"Hands"},{emoji:"๐",name:"vulcan salute",category:"Hands"},{emoji:"๐",name:"wave",category:"Hands"},{emoji:"๐",name:"clap",category:"Hands"},{emoji:"๐",name:"hands up",category:"Hands"},{emoji:"๐",name:"open hands",category:"Hands"},{emoji:"๐คฒ",name:"palms up",category:"Hands"},{emoji:"๐ค",name:"handshake",category:"Hands"},{emoji:"๐",name:"pray",category:"Hands"},{emoji:"๐ช",name:"flex",category:"Hands"},{emoji:"โ๏ธ",name:"writing",category:"Hands"},{emoji:"๐คณ",name:"selfie",category:"Hands"},{emoji:"๐ถ",name:"dog",category:"Animals"},{emoji:"๐ฑ",name:"cat",category:"Animals"},{emoji:"๐ญ",name:"mouse",category:"Animals"},{emoji:"๐น",name:"hamster",category:"Animals"},{emoji:"๐ฐ",name:"rabbit",category:"Animals"},{emoji:"๐ฆ",name:"fox",category:"Animals"},{emoji:"๐ป",name:"bear",category:"Animals"},{emoji:"๐ผ",name:"panda",category:"Animals"},{emoji:"๐จ",name:"koala",category:"Animals"},{emoji:"๐ฏ",name:"tiger",category:"Animals"},{emoji:"๐ฆ",name:"lion",category:"Animals"},{emoji:"๐ฎ",name:"cow",category:"Animals"},{emoji:"๐ท",name:"pig",category:"Animals"},{emoji:"๐ธ",name:"frog",category:"Animals"},{emoji:"๐ต",name:"monkey",category:"Animals"},{emoji:"๐",name:"chicken",category:"Animals"},{emoji:"๐ง",name:"penguin",category:"Animals"},{emoji:"๐ฆ",name:"bird",category:"Animals"},{emoji:"๐ค",name:"chick",category:"Animals"},{emoji:"๐ฆ",name:"duck",category:"Animals"},{emoji:"๐ฆ
",name:"eagle",category:"Animals"},{emoji:"๐ฆ",name:"owl",category:"Animals"},{emoji:"๐ฆ",name:"bat",category:"Animals"},{emoji:"๐ฆ",name:"unicorn",category:"Animals"},{emoji:"๐",name:"bee",category:"Animals"},{emoji:"๐ฆ",name:"butterfly",category:"Animals"},{emoji:"๐",name:"snail",category:"Animals"},{emoji:"๐",name:"ladybeetle",category:"Animals"},{emoji:"๐ข",name:"turtle",category:"Animals"},{emoji:"๐",name:"snake",category:"Animals"},{emoji:"๐",name:"octopus",category:"Animals"},{emoji:"๐ฌ",name:"dolphin",category:"Animals"},{emoji:"๐ณ",name:"whale",category:"Animals"},{emoji:"๐",name:"fish",category:"Animals"},{emoji:"๐ฆ",name:"zebra",category:"Animals"},{emoji:"๐ฆ",name:"giraffe",category:"Animals"},{emoji:"๐",name:"elephant",category:"Animals"},{emoji:"๐ฆ",name:"rhino",category:"Animals"},{emoji:"๐ช",name:"camel",category:"Animals"},{emoji:"๐",name:"monkey",category:"Animals"},{emoji:"๐",name:"apple",category:"Food"},{emoji:"๐",name:"pear",category:"Food"},{emoji:"๐",name:"tangerine",category:"Food"},{emoji:"๐",name:"lemon",category:"Food"},{emoji:"๐",name:"banana",category:"Food"},{emoji:"๐",name:"watermelon",category:"Food"},{emoji:"๐",name:"grapes",category:"Food"},{emoji:"๐",name:"strawberry",category:"Food"},{emoji:"๐",name:"cherries",category:"Food"},{emoji:"๐",name:"peach",category:"Food"},{emoji:"๐ฅญ",name:"mango",category:"Food"},{emoji:"๐",name:"pineapple",category:"Food"},{emoji:"๐ฅฅ",name:"coconut",category:"Food"},{emoji:"๐ฅ",name:"kiwi",category:"Food"},{emoji:"๐
",name:"tomato",category:"Food"},{emoji:"๐ฅ",name:"avocado",category:"Food"},{emoji:"๐",name:"eggplant",category:"Food"},{emoji:"๐ฅ",name:"potato",category:"Food"},{emoji:"๐ฅ",name:"carrot",category:"Food"},{emoji:"๐ฝ",name:"corn",category:"Food"},{emoji:"๐ถ๏ธ",name:"hot pepper",category:"Food"},{emoji:"๐ฅฆ",name:"broccoli",category:"Food"},{emoji:"๐",name:"mushroom",category:"Food"},{emoji:"๐ฅ",name:"peanuts",category:"Food"},{emoji:"๐",name:"bread",category:"Food"},{emoji:"๐ฅ",name:"croissant",category:"Food"},{emoji:"๐ฅฏ",name:"bagel",category:"Food"},{emoji:"๐ฅ",name:"pancakes",category:"Food"},{emoji:"๐ง",name:"cheese",category:"Food"},{emoji:"๐",name:"meat",category:"Food"},{emoji:"๐",name:"poultry leg",category:"Food"},{emoji:"๐ฅ",name:"bacon",category:"Food"},{emoji:"๐",name:"hamburger",category:"Food"},{emoji:"๐",name:"fries",category:"Food"},{emoji:"๐",name:"pizza",category:"Food"},{emoji:"๐ญ",name:"hot dog",category:"Food"},{emoji:"๐ฅช",name:"sandwich",category:"Food"},{emoji:"๐ฎ",name:"taco",category:"Food"},{emoji:"๐ฏ",name:"burrito",category:"Food"},{emoji:"๐ณ",name:"egg",category:"Food"},{emoji:"๐ฒ",name:"stew",category:"Food"},{emoji:"๐ฅฃ",name:"bowl",category:"Food"},{emoji:"๐ฅ",name:"salad",category:"Food"},{emoji:"๐ฟ",name:"popcorn",category:"Food"},{emoji:"๐ฑ",name:"bento",category:"Food"},{emoji:"๐ฃ",name:"sushi",category:"Food"},{emoji:"๐ค",name:"shrimp",category:"Food"},{emoji:"๐ฆ",name:"ice cream",category:"Food"},{emoji:"๐ง",name:"shaved ice",category:"Food"},{emoji:"๐จ",name:"ice cream",category:"Food"},{emoji:"๐ฉ",name:"donut",category:"Food"},{emoji:"๐ช",name:"cookie",category:"Food"},{emoji:"๐",name:"cake",category:"Food"},{emoji:"๐ฐ",name:"shortcake",category:"Food"},{emoji:"๐ง",name:"cupcake",category:"Food"},{emoji:"๐ฅง",name:"pie",category:"Food"},{emoji:"๐ซ",name:"chocolate",category:"Food"},{emoji:"๐ฌ",name:"candy",category:"Food"},{emoji:"๐ญ",name:"lollipop",category:"Food"},{emoji:"๐ฎ",name:"custard",category:"Food"},{emoji:"๐ฏ",name:"honey",category:"Food"},{emoji:"๐ผ",name:"baby bottle",category:"Food"},{emoji:"๐ฅ",name:"milk",category:"Food"},{emoji:"โ",name:"coffee",category:"Food"},{emoji:"๐ต",name:"tea",category:"Food"},{emoji:"๐ถ",name:"sake",category:"Food"},{emoji:"๐พ",name:"champagne",category:"Food"},{emoji:"๐ท",name:"wine",category:"Food"},{emoji:"๐ธ",name:"cocktail",category:"Food"},{emoji:"๐น",name:"tropical drink",category:"Food"},{emoji:"๐บ",name:"beer",category:"Food"},{emoji:"๐ป",name:"beers",category:"Food"},{emoji:"๐ฅ",name:"tumbler glass",category:"Food"},{emoji:"๐ฅค",name:"soda",category:"Food"},{emoji:"๐",name:"car",category:"Travel"},{emoji:"๐",name:"taxi",category:"Travel"},{emoji:"๐",name:"bus",category:"Travel"},{emoji:"๐",name:"trolleybus",category:"Travel"},{emoji:"๐๏ธ",name:"racing car",category:"Travel"},{emoji:"๐",name:"police car",category:"Travel"},{emoji:"๐",name:"ambulance",category:"Travel"},{emoji:"๐",name:"fire engine",category:"Travel"},{emoji:"๐",name:"minibus",category:"Travel"},{emoji:"๐",name:"truck",category:"Travel"},{emoji:"๐",name:"articulated lorry",category:"Travel"},{emoji:"๐",name:"tractor",category:"Travel"},{emoji:"๐ฒ",name:"bicycle",category:"Travel"},{emoji:"๐ต",name:"scooter",category:"Travel"},{emoji:"๐๏ธ",name:"motorcycle",category:"Travel"},{emoji:"๐",name:"bullet train",category:"Travel"},{emoji:"๐",name:"train",category:"Travel"},{emoji:"โ๏ธ",name:"airplane",category:"Travel"},{emoji:"๐",name:"rocket",category:"Travel"},{emoji:"๐ธ",name:"ufo",category:"Travel"},{emoji:"๐",name:"helicopter",category:"Travel"},{emoji:"๐ข",name:"ship",category:"Travel"},{emoji:"โต",name:"sailboat",category:"Travel"},{emoji:"โ",name:"anchor",category:"Travel"},{emoji:"โฝ",name:"fuel pump",category:"Travel"},{emoji:"๐ฆ",name:"traffic light",category:"Travel"},{emoji:"๐ป",name:"laptop",category:"Objects"},{emoji:"๐ฑ",name:"mobile",category:"Objects"},{emoji:"โ๏ธ",name:"telephone",category:"Objects"},{emoji:"โจ๏ธ",name:"keyboard",category:"Objects"},{emoji:"๐ฅ๏ธ",name:"desktop",category:"Objects"},{emoji:"๐จ๏ธ",name:"printer",category:"Objects"},{emoji:"๐ธ",name:"camera",category:"Objects"},{emoji:"๐ฅ",name:"video camera",category:"Objects"},{emoji:"๐บ",name:"tv",category:"Objects"},{emoji:"๐ป",name:"radio",category:"Objects"},{emoji:"โฐ",name:"alarm clock",category:"Objects"},{emoji:"๐ก",name:"light bulb",category:"Objects"},{emoji:"๐ฆ",name:"flashlight",category:"Objects"},{emoji:"๐ฏ๏ธ",name:"candle",category:"Objects"},{emoji:"๐จ",name:"hammer",category:"Objects"},{emoji:"๐ง",name:"wrench",category:"Objects"},{emoji:"๐ฉ",name:"nut and bolt",category:"Objects"},{emoji:"๐ซ",name:"water pistol",category:"Objects"},{emoji:"๐ธ",name:"money",category:"Objects"},{emoji:"๐ต",name:"dollar bill",category:"Objects"},{emoji:"๐ณ",name:"credit card",category:"Objects"},{emoji:"๐",name:"gem",category:"Objects"},{emoji:"โ๏ธ",name:"balance scale",category:"Objects"},{emoji:"๐",name:"link",category:"Objects"},{emoji:"โ๏ธ",name:"chains",category:"Objects"},{emoji:"๐",name:"syringe",category:"Objects"},{emoji:"๐",name:"pill",category:"Objects"},{emoji:"๐ช",name:"door",category:"Objects"},{emoji:"๐๏ธ",name:"bed",category:"Objects"},{emoji:"๐๏ธ",name:"couch",category:"Objects"},{emoji:"๐ฟ",name:"shower",category:"Objects"},{emoji:"๐",name:"bathtub",category:"Objects"},{emoji:"๐",name:"key",category:"Objects"},{emoji:"๐งน",name:"broom",category:"Objects"},{emoji:"โฝ",name:"soccer",category:"Activities"},{emoji:"๐",name:"basketball",category:"Activities"},{emoji:"๐",name:"football",category:"Activities"},{emoji:"โพ",name:"baseball",category:"Activities"},{emoji:"๐พ",name:"tennis",category:"Activities"},{emoji:"๐",name:"volleyball",category:"Activities"},{emoji:"๐",name:"rugby",category:"Activities"},{emoji:"๐ฑ",name:"pool",category:"Activities"},{emoji:"โณ",name:"golf",category:"Activities"},{emoji:"๐ช",name:"kite",category:"Activities"},{emoji:"๐น",name:"bow and arrow",category:"Activities"},{emoji:"๐ฃ",name:"fishing",category:"Activities"},{emoji:"๐ฅ",name:"boxing",category:"Activities"},{emoji:"๐ฅ",name:"martial arts",category:"Activities"},{emoji:"โธ๏ธ",name:"ice skate",category:"Activities"},{emoji:"๐ฟ",name:"ski",category:"Activities"},{emoji:"๐",name:"snowboard",category:"Activities"},{emoji:"๐๏ธ",name:"weightlifter",category:"Activities"},{emoji:"๐คบ",name:"fencing",category:"Activities"},{emoji:"๐คผ",name:"wrestling",category:"Activities"},{emoji:"๐คธ",name:"cartwheel",category:"Activities"},{emoji:"๐",name:"trophy",category:"Activities"},{emoji:"๐
",name:"medal",category:"Activities"},{emoji:"๐ฅ",name:"first place",category:"Activities"},{emoji:"๐๏ธ",name:"ticket",category:"Activities"},{emoji:"๐ฎ",name:"video game",category:"Activities"},{emoji:"๐ฒ",name:"die",category:"Activities"},{emoji:"โ๏ธ",name:"chess",category:"Activities"},{emoji:"๐น",name:"piano",category:"Activities"},{emoji:"๐ธ",name:"guitar",category:"Activities"},{emoji:"๐บ",name:"trumpet",category:"Activities"},{emoji:"๐ป",name:"violin",category:"Activities"},{emoji:"๐ฅ",name:"drum",category:"Activities"},{emoji:"๐ญ",name:"performing arts",category:"Activities"},{emoji:"๐จ",name:"artist palette",category:"Activities"},{emoji:"๐ฌ",name:"clapper board",category:"Activities"},{emoji:"๐ค",name:"microphone",category:"Activities"},{emoji:"๐ง",name:"headphone",category:"Activities"}];class G{container;searchInput;emojiGrid;onSelect;onClose;constructor(e,t){this.onSelect=e,this.onClose=t,this.container=this.createPickerElement(),this.searchInput=this.container.querySelector(".te-emoji-search"),this.emojiGrid=this.container.querySelector(".te-emoji-grid"),this.setupEvents(),this.renderEmojis(d)}createPickerElement(){const e=document.createElement("div");return e.classList.add("te-emoji-picker"),e.innerHTML=`
|
|
2
|
+
<div class="te-emoji-header">
|
|
3
|
+
<input type="text" class="te-emoji-search" placeholder="Search emoji...">
|
|
4
|
+
</div>
|
|
5
|
+
<div class="te-emoji-body">
|
|
6
|
+
<div class="te-emoji-grid"></div>
|
|
7
|
+
</div>
|
|
8
|
+
`,e}setupEvents(){this.searchInput.addEventListener("mousedown",t=>t.stopPropagation()),this.searchInput.addEventListener("click",t=>t.stopPropagation()),this.searchInput.addEventListener("input",()=>{const t=this.searchInput.value.toLowerCase(),i=d.filter(o=>o.name.toLowerCase().includes(t)||o.category.toLowerCase().includes(t));this.renderEmojis(i)});const e=t=>{this.container.contains(t.target)||(this.close(),document.removeEventListener("mousedown",e))};setTimeout(()=>document.addEventListener("mousedown",e),0)}renderEmojis(e){if(this.emojiGrid.innerHTML="",e.length===0){this.emojiGrid.innerHTML='<div class="te-emoji-empty">No emoji found</div>';return}this.searchInput.value.length>0?this.renderGridItems(e):["Smileys","Symbols","Hands","Animals","Food","Travel","Objects","Activities"].forEach(o=>{const a=e.filter(n=>n.category===o);if(a.length>0){const n=document.createElement("div");n.classList.add("te-emoji-category-title"),n.textContent=o,this.emojiGrid.appendChild(n),this.renderGridItems(a)}})}renderGridItems(e){e.forEach(t=>{const i=document.createElement("button");i.type="button",i.classList.add("te-emoji-item"),i.textContent=t.emoji,i.title=t.name,i.addEventListener("click",()=>{this.onSelect(t.emoji),this.close()}),this.emojiGrid.appendChild(i)})}show(e){document.body.appendChild(this.container);const t=e.getBoundingClientRect(),i=280;let o=t.bottom+window.scrollY+5,a=t.left+window.scrollX;a+i>window.innerWidth&&(a=window.innerWidth-i-10),this.container.style.top=`${o}px`,this.container.style.left=`${a}px`,this.searchInput.focus()}close(){this.container.parentElement&&(this.container.remove(),this.onClose())}get el(){return this.container}}class h{editor;container;savedRange=null;items=z;activePicker=null;constructor(e){this.editor=e,this.container=this.createToolbarElement(),this.render()}createToolbarElement(){const e=document.createElement("div");return e.classList.add("te-toolbar"),e}render(){this.items.forEach(e=>{if(e.type==="button")this.renderButton(e);else if(e.type==="select")this.renderSelect(e);else if(e.type==="input")this.renderInput(e);else if(e.type==="color-picker")this.renderColorPicker(e);else if(e.type==="divider"){const t=document.createElement("div");t.classList.add("te-divider"),this.container.appendChild(t)}}),this.editor.el.addEventListener("keyup",()=>this.updateActiveStates()),this.editor.el.addEventListener("mouseup",()=>this.updateActiveStates())}renderButton(e){const t=document.createElement("button");t.classList.add("te-button"),t.innerHTML=e.icon||"",t.title=e.title,t.addEventListener("mousedown",i=>{if(i.preventDefault(),e.command==="insertEmoji"){this.activePicker?this.activePicker.close():(this.activePicker=new G(o=>{this.editor.execute("insertText",o)},()=>{this.activePicker=null}),this.activePicker.show(t));return}if(e.command==="createLink"){const o=window.prompt("Enter the URL");o&&this.editor.createLink(o);return}e.command&&this.editor.execute(e.command,e.value||null),this.updateActiveStates()}),this.container.appendChild(t)}renderInput(e){const t=document.createElement("input");t.type="number",t.classList.add("te-input"),t.title=e.title,t.value=e.value||"",t.min="1",t.max="100";const i=()=>{const a=window.getSelection();if(a&&a.rangeCount>0){const n=a.getRangeAt(0);this.editor.el.contains(n.commonAncestorContainer)&&(this.savedRange=n.cloneRange())}};t.addEventListener("mousedown",i),t.addEventListener("focus",i);const o=()=>{let a=parseInt(t.value,10);if(!isNaN(a)&&(a=Math.max(1,Math.min(100,a)),t.value=a.toString(),e.command==="fontSize")){if(this.savedRange){const n=this.editor.setStyle("font-size",`${a}px`,this.savedRange);n&&(this.savedRange=n)}else this.editor.setStyle("font-size",`${a}px`);t.focus()}};t.addEventListener("input",o),t.addEventListener("keydown",a=>{a.key==="Enter"&&(o(),this.editor.focus())}),this.container.appendChild(t)}renderSelect(e){const t=document.createElement("select");t.classList.add("te-select"),t.title=e.title,e.options&&e.options.forEach(i=>{const o=document.createElement("option");o.value=i.value,o.textContent=i.label,t.appendChild(o)}),t.addEventListener("change",()=>{const i=t.value;this.savedRange&&this.editor.selection.restoreSelection(this.savedRange),e.command==="formatBlock"?this.editor.execute(e.command,i):e.command==="fontFamily"&&this.editor.setStyle("font-family",i),this.editor.focus()}),t.addEventListener("mousedown",()=>{this.savedRange=this.editor.selection.saveSelection()}),this.container.appendChild(t)}renderColorPicker(e){const t=document.createElement("input");t.type="color",t.classList.add("te-color-picker"),t.title=e.title,t.value=e.value||"#000000",t.addEventListener("mousedown",()=>{this.savedRange=this.editor.selection.saveSelection()}),t.addEventListener("change",()=>{this.savedRange&&this.editor.selection.restoreSelection(this.savedRange),e.command&&this.editor.execute(e.command,t.value),this.editor.focus()}),this.container.appendChild(t)}get el(){return this.container}updateActiveStates(){const e=this.container.querySelectorAll(".te-button");let t=0;this.items.forEach(i=>{if(i.type==="button"){const o=e[t++];i.command&&document.queryCommandState(i.command)?o.classList.add("active"):o.classList.remove("active")}})}}class V extends j{toolbar;constructor(e,t={}){super(e,t),this.toolbar=new h(this),this.container.insertBefore(this.toolbar.el,this.editableElement)}}exports.CoreEditor=j;exports.SelectionManager=g;exports.TestEditor=V;exports.Toolbar=h;
|
|
9
|
+
//# sourceMappingURL=test-editor.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-editor.cjs","sources":["../src/core/SelectionManager.ts","../src/core/Editor.ts","../src/ui/toolbar/items/Undo.ts","../src/ui/toolbar/items/Redo.ts","../src/ui/toolbar/items/Heading.ts","../src/ui/toolbar/items/FontFamily.ts","../src/ui/toolbar/items/FontSize.ts","../src/ui/toolbar/items/Bold.ts","../src/ui/toolbar/items/Italic.ts","../src/ui/toolbar/items/Underline.ts","../src/ui/toolbar/items/Strikethrough.ts","../src/ui/toolbar/items/TextColor.ts","../src/ui/toolbar/items/HighlightColor.ts","../src/ui/toolbar/items/AlignLeft.ts","../src/ui/toolbar/items/AlignCenter.ts","../src/ui/toolbar/items/AlignRight.ts","../src/ui/toolbar/items/AlignJustify.ts","../src/ui/toolbar/items/BulletList.ts","../src/ui/toolbar/items/OrderedList.ts","../src/ui/toolbar/items/Outdent.ts","../src/ui/toolbar/items/Indent.ts","../src/ui/toolbar/items/HorizontalRule.ts","../src/ui/toolbar/items/ClearFormatting.ts","../src/ui/toolbar/items/Emoji.ts","../src/ui/toolbar/items/Link.ts","../src/ui/toolbar/registry.ts","../src/ui/toolbar/EmojiList.ts","../src/ui/toolbar/EmojiPicker.ts","../src/ui/Toolbar.ts","../src/index.ts"],"sourcesContent":["/**\n * SelectionManager handles wrapping the native browser Selection and Range APIs.\n * This ensures consistent behavior across different environments and simplifies\n * interaction with the editor's cursor and selected text.\n */\nexport class SelectionManager {\n /**\n * Returns the current selection object.\n */\n getSelection(): Selection | null {\n return window.getSelection();\n }\n\n /**\n * Returns the first range of the current selection.\n */\n getRange(): Range | null {\n const selection = this.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return null;\n }\n return selection.getRangeAt(0);\n }\n\n /**\n * Saves the current selection range.\n */\n saveSelection(): Range | null {\n const range = this.getRange();\n return range ? range.cloneRange() : null;\n }\n\n /**\n * Restores a previously saved range.\n */\n restoreSelection(range: Range | null): void {\n if (!range) return;\n\n const selection = this.getSelection();\n if (selection) {\n selection.removeAllRanges();\n selection.addRange(range);\n }\n }\n\n /**\n * Checks if the selection is within a specific element.\n */\n isSelectionInElement(element: HTMLElement): boolean {\n const range = this.getRange();\n if (!range) return false;\n \n return element.contains(range.commonAncestorContainer);\n }\n\n /**\n * Clears the current selection.\n */\n clearSelection(): void {\n const selection = this.getSelection();\n if (selection) {\n selection.removeAllRanges();\n }\n }\n}\n","import { SelectionManager } from './SelectionManager';\n\nexport interface EditorOptions {\n placeholder?: string;\n autofocus?: boolean;\n}\n\nexport class CoreEditor {\n protected container: HTMLElement;\n protected editableElement: HTMLElement;\n public selection: SelectionManager;\n protected options: EditorOptions;\n private pendingStyles: Record<string, string> = {};\n\n constructor(container: HTMLElement, options: EditorOptions = {}) {\n this.container = container;\n this.container.classList.add('te-container');\n this.options = options;\n this.selection = new SelectionManager();\n \n // Create the contenteditable area\n this.editableElement = this.createEditableElement();\n this.setupInputHandlers();\n \n // Default structure: append editable area\n this.container.appendChild(this.editableElement);\n\n if (this.options.autofocus) {\n this.focus();\n }\n\n // Set default paragraph separator to <p>\n document.execCommand('defaultParagraphSeparator', false, 'p');\n }\n\n protected setupInputHandlers(): void {\n this.editableElement.addEventListener('beforeinput', (e: InputEvent) => {\n if (e.inputType === 'insertText' && Object.keys(this.pendingStyles).length > 0) {\n const text = e.data;\n if (!text) return;\n\n e.preventDefault();\n \n const span = document.createElement('span');\n for (const [prop, val] of Object.entries(this.pendingStyles)) {\n span.style.setProperty(prop, val);\n if (prop === 'font-size') {\n // span.style.lineHeight = '1.2'; // Removed as per user request\n }\n }\n span.textContent = text;\n\n const range = this.selection.getRange();\n if (range) {\n range.deleteContents();\n range.insertNode(span);\n \n // Move cursor to the end of the newly inserted text\n const newRange = document.createRange();\n newRange.setStart(span.firstChild!, text.length);\n newRange.setEnd(span.firstChild!, text.length);\n this.selection.restoreSelection(newRange);\n \n // Clear pending styles as they've been applied\n this.pendingStyles = {};\n this.editableElement.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n });\n\n // Clear pending styles on selection change if the selection is no longer collapsed\n // or if the user clicks elsewhere.\n document.addEventListener('selectionchange', () => {\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n if (!range.collapsed) {\n this.pendingStyles = {};\n }\n }\n });\n }\n\n protected createEditableElement(): HTMLElement {\n const el = document.createElement('div');\n el.setAttribute('contenteditable', 'true');\n el.setAttribute('role', 'textbox');\n el.setAttribute('spellcheck', 'true');\n el.classList.add('te-content');\n\n if (this.options.placeholder) {\n el.setAttribute('data-placeholder', this.options.placeholder);\n }\n\n // Default styling setup\n el.style.minHeight = '150px';\n el.style.outline = 'none';\n el.style.padding = '1rem';\n\n // Handle initial empty state\n if (el.innerHTML === '') {\n el.innerHTML = '<p><br></p>';\n }\n\n return el;\n }\n\n /**\n * Focuses the editor.\n */\n focus(): void {\n this.editableElement.focus();\n }\n\n /**\n * Executes a command on the current selection.\n */\n execute(command: string, value: string | null = null): void {\n this.focus();\n \n // For font size and family, we might want custom logic in the future.\n // However, for standard commands, execCommand is still the easiest path for undo/redo.\n document.execCommand(command, false, value ?? undefined);\n \n // Dispatch an input event to notify listeners of changes\n this.editableElement.dispatchEvent(new Event('input', { bubbles: true }));\n }\n\n /**\n * Recursively removes a style property from all elements in a fragment.\n */\n private clearStyleRecursive(fragment: Node, property: string): void {\n const walker = document.createTreeWalker(fragment, NodeFilter.SHOW_ELEMENT);\n let node = walker.nextNode() as HTMLElement | null;\n while (node) {\n if (node.style.getPropertyValue(property)) {\n node.style.removeProperty(property);\n // If the span is now empty, we could potentially remove it, \n // but for now, we'll let it be to preserve other styles (bold, etc).\n }\n node = walker.nextNode() as HTMLElement | null;\n }\n }\n\n /**\n * Applies an inline style to the selection.\n * This is used for properties like font-size (px) and font-family\n * where execCommand is outdated or limited.\n */\n setStyle(property: string, value: string, range?: Range): Range | null {\n if (property === 'font-size') {\n const numValue = parseInt(value, 10);\n if (!isNaN(numValue)) {\n const clampedValue = Math.max(1, Math.min(100, numValue));\n value = `${clampedValue}px`;\n }\n }\n\n if (!range) {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return null;\n range = selection.getRangeAt(0);\n }\n\n if (range.collapsed) {\n this.pendingStyles[property] = value;\n return range;\n }\n\n // Check if the current selection is already inside a span with this property\n let parent = range.commonAncestorContainer as HTMLElement;\n if (parent.nodeType === Node.TEXT_NODE) {\n parent = parent.parentElement!;\n }\n\n let resultRange: Range | null = null;\n\n // Modern approach: apply style and then clean up/merge\n // For now, we'll try to find if the selection is exactly a span and update it\n if (parent.tagName === 'SPAN' && parent.children.length === 0 && parent.textContent === range.toString()) {\n parent.style.setProperty(property, value);\n resultRange = range.cloneRange();\n } else {\n const span = document.createElement('span');\n span.style.setProperty(property, value);\n \n try {\n const parentSpan = parent.tagName === 'SPAN' ? parent : null;\n \n // NEW: Extract content and clean it up to prevent nesting issues\n const fragment = range.extractContents();\n this.clearStyleRecursive(fragment, property);\n \n span.appendChild(fragment);\n range.insertNode(span);\n \n // Cleanup: if the parent was a span and is now empty, remove it\n if (parentSpan && parentSpan.innerHTML === '') {\n parentSpan.remove();\n }\n \n const newRange = document.createRange();\n newRange.selectNodeContents(span);\n resultRange = newRange;\n\n // Update the selection if we are working on the active selection\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n selection.removeAllRanges();\n selection.addRange(newRange);\n }\n } catch (e) {\n console.warn('Failed to apply style:', e);\n }\n }\n\n this.editableElement.dispatchEvent(new Event('input', { bubbles: true }));\n return resultRange;\n }\n\n /**\n * Creates a link at the current selection.\n * Ensures the link opens in a new tab with proper security attributes.\n */\n createLink(url: string): void {\n this.focus();\n \n // Check if the URL has a protocol, if not add https://\n if (!/^https?:\\/\\//i.test(url) && !/^mailto:/i.test(url) && !url.startsWith('#')) {\n url = 'https://' + url;\n }\n\n // Use execCommand to create the link initially\n document.execCommand('createLink', false, url);\n\n // Find the newly created anchor tag and add target=\"_blank\"\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n let container = range.commonAncestorContainer as HTMLElement;\n \n // If the container is a text node, get its parent\n if (container.nodeType === Node.TEXT_NODE) {\n container = container.parentElement!;\n }\n\n // Look for the anchor tag\n let anchor: HTMLAnchorElement | null = null;\n if (container.tagName === 'A') {\n anchor = container as HTMLAnchorElement;\n } else {\n anchor = container.querySelector('a');\n }\n\n if (anchor) {\n anchor.setAttribute('target', '_blank');\n anchor.setAttribute('rel', 'noopener noreferrer');\n }\n }\n\n this.editableElement.dispatchEvent(new Event('input', { bubbles: true }));\n }\n\n /**\n * Returns the clean HTML content of the editor.\n */\n getHTML(): string {\n return this.editableElement.innerHTML;\n }\n\n /**\n * Sets the HTML content of the editor.\n */\n setHTML(html: string): void {\n this.editableElement.innerHTML = html;\n }\n\n /**\n * Internal access to the editable element.\n */\n get el(): HTMLElement {\n return this.editableElement;\n }\n}\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const undo: ToolbarItem = {\n type: 'button',\n title: 'Undo',\n command: 'undo',\n icon: '<svg viewBox=\"0 0 24 24\"><path d=\"M9 14L4 9l5-5\"></path><path d=\"M20 20v-7a4 4 0 0 0-4-4H4\"></path></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const redo: ToolbarItem = {\n type: 'button',\n title: 'Redo',\n command: 'redo',\n icon: '<svg viewBox=\"0 0 24 24\"><path d=\"M15 14l5-5-5-5\"></path><path d=\"M4 20v-7a4 4 0 0 1 4-4h12\"></path></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const heading: ToolbarItem = {\n type: 'select',\n title: 'Heading',\n command: 'formatBlock',\n options: [\n { label: 'Paragraph', value: 'P' },\n { label: 'Heading 1', value: 'H1' },\n { label: 'Heading 2', value: 'H2' },\n { label: 'Heading 3', value: 'H3' },\n { label: 'Heading 4', value: 'H4' },\n { label: 'Heading 5', value: 'H5' },\n { label: 'Heading 6', value: 'H6' },\n ]\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const fontFamily: ToolbarItem = {\n type: 'select',\n title: 'Font',\n command: 'fontFamily',\n options: [\n { label: 'Inter', value: \"'Inter', sans-serif\" },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Courier', value: \"'Courier New', monospace\" },\n { label: 'Times New Roman', value: \"'Times New Roman', serif\" },\n { label: 'Verdana', value: 'Verdana, sans-serif' },\n { label: 'Tahoma', value: 'Tahoma, sans-serif' },\n { label: 'Roboto', value: \"'Roboto', sans-serif\" },\n { label: 'Open Sans', value: \"'Open Sans', sans-serif\" },\n { label: 'Montserrat', value: \"'Montserrat', sans-serif\" },\n { label: 'Lato', value: \"'Lato', sans-serif\" },\n { label: 'Poppins', value: \"'Poppins', sans-serif\" },\n { label: 'Oswald', value: \"'Oswald', sans-serif\" },\n { label: 'Playfair Display', value: \"'Playfair Display', serif\" },\n { label: 'Merriweather', value: \"'Merriweather', serif\" },\n ]\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const fontSize: ToolbarItem = {\n type: 'input',\n title: 'Size (px)',\n command: 'fontSize',\n placeholder: 'Size',\n value: '16'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const bold: ToolbarItem = {\n type: 'button',\n title: 'Bold',\n command: 'bold',\n icon: '<svg viewBox=\"0 0 24 24\"><path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"></path><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"></path></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const italic: ToolbarItem = {\n type: 'button',\n title: 'Italic',\n command: 'italic',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"></line><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"></line><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const underline: ToolbarItem = {\n type: 'button',\n title: 'Underline',\n command: 'underline',\n icon: '<svg viewBox=\"0 0 24 24\"><path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"></path><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const strikethrough: ToolbarItem = {\n type: 'button',\n title: 'Strikethrough',\n command: 'strikeThrough',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line><path d=\"M16 4.9C15.1 4.3 13.9 4 12.6 4c-3.1 0-5.6 1.8-5.6 4s1.8 3.3 4.4 3.8\"></path><path d=\"M7 19.1c.9.6 2.1.9 3.4.9 3.1 0 5.6-1.8 5.6-4s-1.8-3.3-4.4-3.8\"></path></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const textColor: ToolbarItem = {\n type: 'color-picker',\n title: 'Text Color',\n command: 'foreColor',\n value: '#1e293b'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const highlightColor: ToolbarItem = {\n type: 'color-picker',\n title: 'Highlight Color',\n command: 'backColor',\n value: '#ffffff'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const alignLeft: ToolbarItem = {\n type: 'button',\n title: 'Align Left',\n command: 'justifyLeft',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\"></line><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"></line><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"></line><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const alignCenter: ToolbarItem = {\n type: 'button',\n title: 'Align Center',\n command: 'justifyCenter',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"18\" y1=\"10\" x2=\"6\" y2=\"10\"></line><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"></line><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"></line><line x1=\"18\" y1=\"18\" x2=\"6\" y2=\"18\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const alignRight: ToolbarItem = {\n type: 'button',\n title: 'Align Right',\n command: 'justifyRight',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\"></line><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"></line><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"></line><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const alignJustify: ToolbarItem = {\n type: 'button',\n title: 'Justify',\n command: 'justifyFull',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"21\" y1=\"10\" x2=\"3\" y2=\"10\"></line><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"></line><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"></line><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const bulletList: ToolbarItem = {\n type: 'button',\n title: 'Bulleted List',\n command: 'insertUnorderedList',\n icon: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"></line><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"></line><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"></line><circle cx=\"3\" cy=\"6\" r=\"1\" fill=\"currentColor\"></circle><circle cx=\"3\" cy=\"12\" r=\"1\" fill=\"currentColor\"></circle><circle cx=\"3\" cy=\"18\" r=\"1\" fill=\"currentColor\"></circle></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const orderedList: ToolbarItem = {\n type: 'button',\n title: 'Numbered List',\n command: 'insertOrderedList',\n icon: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"></line><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"21\"></line><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"></line><path d=\"M4 6h1v4\"></path><path d=\"M4 10h2\"></path><path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1\"></path></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const outdent: ToolbarItem = {\n type: 'button',\n title: 'Outdent',\n command: 'outdent',\n icon: '<svg viewBox=\"0 0 24 24\"><polyline points=\"15 18 9 12 15 6\"></polyline><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"></line><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"></line><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const indent: ToolbarItem = {\n type: 'button',\n title: 'Indent',\n command: 'indent',\n icon: '<svg viewBox=\"0 0 24 24\"><polyline points=\"9 18 15 12 9 6\"></polyline><line x1=\"3\" y1=\"12\" x2=\"15\" y2=\"12\"></line><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"></line><line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const horizontalRule: ToolbarItem = {\n type: 'button',\n title: 'Horizontal Rule',\n command: 'insertHorizontalRule',\n icon: '<svg viewBox=\"0 0 24 24\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const clearFormatting: ToolbarItem = {\n type: 'button',\n title: 'Clear Formatting',\n command: 'removeFormat',\n icon: '<svg viewBox=\"0 0 24 24\"><path d=\"M17.41 15.41L12 10l-5.41 5.41L5.17 14l5.41-5.41L5.17 3.17 6.59 1.76 12 7.17l5.41-5.41 1.41 1.41-5.41 5.41 5.41 5.41-1.41 1.42z\"></path></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const emoji: ToolbarItem = {\n type: 'button',\n title: 'Insert Emoji',\n command: 'insertEmoji',\n icon: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"M8 14s1.5 2 4 2 4-2 4-2\"></path><line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\"></line><line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\"></line></svg>'\n};\n","import { ToolbarItem } from '../ToolbarItem';\n\nexport const link: ToolbarItem = {\n type: 'button',\n title: 'Insert Link',\n command: 'createLink',\n icon: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"></path><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"></path></svg>'\n};\n","import { ToolbarItem } from './ToolbarItem';\nimport { undo } from './items/Undo';\nimport { redo } from './items/Redo';\nimport { heading } from './items/Heading';\nimport { fontFamily } from './items/FontFamily';\nimport { fontSize } from './items/FontSize';\nimport { bold } from './items/Bold';\nimport { italic } from './items/Italic';\nimport { underline } from './items/Underline';\nimport { strikethrough } from './items/Strikethrough';\nimport { textColor } from './items/TextColor';\nimport { highlightColor } from './items/HighlightColor';\nimport { alignLeft } from './items/AlignLeft';\nimport { alignCenter } from './items/AlignCenter';\nimport { alignRight } from './items/AlignRight';\nimport { alignJustify } from './items/AlignJustify';\nimport { bulletList } from './items/BulletList';\nimport { orderedList } from './items/OrderedList';\nimport { outdent } from './items/Outdent';\nimport { indent } from './items/Indent';\nimport { horizontalRule } from './items/HorizontalRule';\nimport { clearFormatting } from './items/ClearFormatting';\nimport { emoji } from './items/Emoji';\nimport { link } from './items/Link';\n\nconst divider: ToolbarItem = { type: 'divider', title: '' };\n\nexport const toolbarItems: ToolbarItem[] = [\n undo,\n redo,\n divider,\n heading,\n fontFamily,\n fontSize,\n divider,\n bold,\n italic,\n underline,\n strikethrough,\n divider,\n textColor,\n highlightColor,\n divider,\n alignLeft,\n alignCenter,\n alignRight,\n alignJustify,\n divider,\n bulletList,\n orderedList,\n outdent,\n indent,\n divider,\n horizontalRule,\n emoji,\n link,\n clearFormatting\n];\n","export interface EmojiData {\n emoji: string;\n name: string;\n category: string;\n}\n\nexport const EMOJI_LIST: EmojiData[] = [\n // Smileys & Emotion\n { emoji: '๐', name: 'grinning', category: 'Smileys' },\n { emoji: '๐', name: 'smiley', category: 'Smileys' },\n { emoji: '๐', name: 'smile', category: 'Smileys' },\n { emoji: '๐', name: 'grin', category: 'Smileys' },\n { emoji: '๐', name: 'laughing', category: 'Smileys' },\n { emoji: '๐
', name: 'sweat smile', category: 'Smileys' },\n { emoji: '๐คฃ', name: 'rofl', category: 'Smileys' },\n { emoji: '๐', name: 'joy', category: 'Smileys' },\n { emoji: '๐', name: 'slight smile', category: 'Smileys' },\n { emoji: '๐', name: 'upside down', category: 'Smileys' },\n { emoji: '๐', name: 'wink', category: 'Smileys' },\n { emoji: '๐', name: 'blush', category: 'Smileys' },\n { emoji: '๐', name: 'innocent', category: 'Smileys' },\n { emoji: '๐ฅฐ', name: 'smiling face with hearts', category: 'Smileys' },\n { emoji: '๐', name: 'heart eyes', category: 'Smileys' },\n { emoji: '๐คฉ', name: 'star struck', category: 'Smileys' },\n { emoji: '๐', name: 'kissing heart', category: 'Smileys' },\n { emoji: '๐', name: 'kissing', category: 'Smileys' },\n { emoji: '๐', name: 'kissing closed eyes', category: 'Smileys' },\n { emoji: '๐', name: 'yum', category: 'Smileys' },\n { emoji: '๐', name: 'stuck out tongue', category: 'Smileys' },\n { emoji: '๐', name: 'stuck out tongue winking eye', category: 'Smileys' },\n { emoji: '๐คช', name: 'zany face', category: 'Smileys' },\n { emoji: '๐คจ', name: 'raised eyebrow', category: 'Smileys' },\n { emoji: '๐ง', name: 'monocle', category: 'Smileys' },\n { emoji: '๐ค', name: 'nerd', category: 'Smileys' },\n { emoji: '๐', name: 'sunglasses', category: 'Smileys' },\n { emoji: '๐ฅณ', name: 'partying face', category: 'Smileys' },\n { emoji: '๐', name: 'smirk', category: 'Smileys' },\n { emoji: '๐', name: 'unamused', category: 'Smileys' },\n { emoji: '๐', name: 'disappointed', category: 'Smileys' },\n { emoji: '๐', name: 'pensive', category: 'Smileys' },\n { emoji: '๐', name: 'worried', category: 'Smileys' },\n { emoji: '๐', name: 'confused', category: 'Smileys' },\n { emoji: '๐ซ', name: 'tired', category: 'Smileys' },\n { emoji: '๐ฅต', name: 'hot face', category: 'Smileys' },\n { emoji: '๐ฅถ', name: 'cold face', category: 'Smileys' },\n { emoji: '๐ณ', name: 'flushed', category: 'Smileys' },\n { emoji: '๐ฑ', name: 'scream', category: 'Smileys' },\n { emoji: '๐คข', name: 'nauseated', category: 'Smileys' },\n { emoji: '๐คฎ', name: 'vomiting', category: 'Smileys' },\n { emoji: '๐คฌ', name: 'cursing', category: 'Smileys' },\n { emoji: '๐คซ', name: 'shushing', category: 'Smileys' },\n { emoji: '๐ค', name: 'thinking', category: 'Smileys' },\n { emoji: '๐ค', name: 'hugs', category: 'Smileys' },\n { emoji: '๐ฅฑ', name: 'yawn', category: 'Smileys' },\n { emoji: '๐ด', name: 'sleeping', category: 'Smileys' },\n { emoji: '๐คค', name: 'drooling', category: 'Smileys' },\n { emoji: '๐ต', name: 'dizzy', category: 'Smileys' },\n { emoji: '๐ค', name: 'zipper mouth', category: 'Smileys' },\n { emoji: '๐ฅด', name: 'woozy', category: 'Smileys' },\n { emoji: '๐ค', name: 'fever', category: 'Smileys' },\n { emoji: '๐ค', name: 'bandage', category: 'Smileys' },\n { emoji: '๐คก', name: 'clown', category: 'Smileys' },\n { emoji: '๐ป', name: 'ghost', category: 'Smileys' },\n { emoji: '๐ฝ', name: 'alien', category: 'Smileys' },\n { emoji: '๐พ', name: 'robot', category: 'Smileys' },\n { emoji: '๐ฉ', name: 'poop', category: 'Smileys' },\n\n // Hearts & Symbols\n { emoji: 'โค๏ธ', name: 'heart', category: 'Symbols' },\n { emoji: '๐งก', name: 'orange heart', category: 'Symbols' },\n { emoji: '๐', name: 'yellow heart', category: 'Symbols' },\n { emoji: '๐', name: 'green heart', category: 'Symbols' },\n { emoji: '๐', name: 'blue heart', category: 'Symbols' },\n { emoji: '๐', name: 'purple heart', category: 'Symbols' },\n { emoji: '๐ค', name: 'black heart', category: 'Symbols' },\n { emoji: '๐ค', name: 'white heart', category: 'Symbols' },\n { emoji: '๐ค', name: 'brown heart', category: 'Symbols' },\n { emoji: '๐', name: 'broken heart', category: 'Symbols' },\n { emoji: 'โฃ๏ธ', name: 'heart exclamation', category: 'Symbols' },\n { emoji: '๐', name: 'two hearts', category: 'Symbols' },\n { emoji: '๐', name: 'revolving hearts', category: 'Symbols' },\n { emoji: 'โจ', name: 'sparkles', category: 'Symbols' },\n { emoji: '๐ฅ', name: 'fire', category: 'Symbols' },\n { emoji: 'โญ', name: 'star', category: 'Symbols' },\n { emoji: '๐', name: 'glowing star', category: 'Symbols' },\n { emoji: 'โ
', name: 'check', category: 'Symbols' },\n { emoji: 'โ', name: 'cross', category: 'Symbols' },\n { emoji: '๐ฏ', name: 'hundred', category: 'Symbols' },\n { emoji: '๐ข', name: 'anger', category: 'Symbols' },\n { emoji: '๐ฅ', name: 'collision', category: 'Symbols' },\n { emoji: '๐ซ', name: 'dizzy symbol', category: 'Symbols' },\n { emoji: '๐ฆ', name: 'sweat drops', category: 'Symbols' },\n { emoji: '๐จ', name: 'dash', category: 'Symbols' },\n \n // Hand Gestures\n { emoji: '๐', name: 'thumbs up', category: 'Hands' },\n { emoji: '๐', name: 'thumbs down', category: 'Hands' },\n { emoji: '๐', name: 'ok', category: 'Hands' },\n { emoji: 'โ๏ธ', name: 'victory', category: 'Hands' },\n { emoji: '๐ค', name: 'fingers crossed', category: 'Hands' },\n { emoji: '๐ค', name: 'rock on', category: 'Hands' },\n { emoji: '๐ค', name: 'horns', category: 'Hands' },\n { emoji: '๐ค', name: 'call me', category: 'Hands' },\n { emoji: '๐', name: 'point left', category: 'Hands' },\n { emoji: '๐', name: 'point right', category: 'Hands' },\n { emoji: '๐', name: 'point up', category: 'Hands' },\n { emoji: '๐', name: 'point down', category: 'Hands' },\n { emoji: '๐๏ธ', name: 'hand splayed', category: 'Hands' },\n { emoji: 'โ', name: 'raised hand', category: 'Hands' },\n { emoji: '๐', name: 'vulcan salute', category: 'Hands' },\n { emoji: '๐', name: 'wave', category: 'Hands' },\n { emoji: '๐', name: 'clap', category: 'Hands' },\n { emoji: '๐', name: 'hands up', category: 'Hands' },\n { emoji: '๐', name: 'open hands', category: 'Hands' },\n { emoji: '๐คฒ', name: 'palms up', category: 'Hands' },\n { emoji: '๐ค', name: 'handshake', category: 'Hands' },\n { emoji: '๐', name: 'pray', category: 'Hands' },\n { emoji: '๐ช', name: 'flex', category: 'Hands' },\n { emoji: 'โ๏ธ', name: 'writing', category: 'Hands' },\n { emoji: '๐คณ', name: 'selfie', category: 'Hands' },\n\n // Animals & Nature\n { emoji: '๐ถ', name: 'dog', category: 'Animals' },\n { emoji: '๐ฑ', name: 'cat', category: 'Animals' },\n { emoji: '๐ญ', name: 'mouse', category: 'Animals' },\n { emoji: '๐น', name: 'hamster', category: 'Animals' },\n { emoji: '๐ฐ', name: 'rabbit', category: 'Animals' },\n { emoji: '๐ฆ', name: 'fox', category: 'Animals' },\n { emoji: '๐ป', name: 'bear', category: 'Animals' },\n { emoji: '๐ผ', name: 'panda', category: 'Animals' },\n { emoji: '๐จ', name: 'koala', category: 'Animals' },\n { emoji: '๐ฏ', name: 'tiger', category: 'Animals' },\n { emoji: '๐ฆ', name: 'lion', category: 'Animals' },\n { emoji: '๐ฎ', name: 'cow', category: 'Animals' },\n { emoji: '๐ท', name: 'pig', category: 'Animals' },\n { emoji: '๐ธ', name: 'frog', category: 'Animals' },\n { emoji: '๐ต', name: 'monkey', category: 'Animals' },\n { emoji: '๐', name: 'chicken', category: 'Animals' },\n { emoji: '๐ง', name: 'penguin', category: 'Animals' },\n { emoji: '๐ฆ', name: 'bird', category: 'Animals' },\n { emoji: '๐ค', name: 'chick', category: 'Animals' },\n { emoji: '๐ฆ', name: 'duck', category: 'Animals' },\n { emoji: '๐ฆ
', name: 'eagle', category: 'Animals' },\n { emoji: '๐ฆ', name: 'owl', category: 'Animals' },\n { emoji: '๐ฆ', name: 'bat', category: 'Animals' },\n { emoji: '๐ฆ', name: 'unicorn', category: 'Animals' },\n { emoji: '๐', name: 'bee', category: 'Animals' },\n { emoji: '๐ฆ', name: 'butterfly', category: 'Animals' },\n { emoji: '๐', name: 'snail', category: 'Animals' },\n { emoji: '๐', name: 'ladybeetle', category: 'Animals' },\n { emoji: '๐ข', name: 'turtle', category: 'Animals' },\n { emoji: '๐', name: 'snake', category: 'Animals' },\n { emoji: '๐', name: 'octopus', category: 'Animals' },\n { emoji: '๐ฌ', name: 'dolphin', category: 'Animals' },\n { emoji: '๐ณ', name: 'whale', category: 'Animals' },\n { emoji: '๐', name: 'fish', category: 'Animals' },\n { emoji: '๐ฆ', name: 'zebra', category: 'Animals' },\n { emoji: '๐ฆ', name: 'giraffe', category: 'Animals' },\n { emoji: '๐', name: 'elephant', category: 'Animals' },\n { emoji: '๐ฆ', name: 'rhino', category: 'Animals' },\n { emoji: '๐ช', name: 'camel', category: 'Animals' },\n { emoji: '๐', name: 'monkey', category: 'Animals' },\n \n // Food & Drink\n { emoji: '๐', name: 'apple', category: 'Food' },\n { emoji: '๐', name: 'pear', category: 'Food' },\n { emoji: '๐', name: 'tangerine', category: 'Food' },\n { emoji: '๐', name: 'lemon', category: 'Food' },\n { emoji: '๐', name: 'banana', category: 'Food' },\n { emoji: '๐', name: 'watermelon', category: 'Food' },\n { emoji: '๐', name: 'grapes', category: 'Food' },\n { emoji: '๐', name: 'strawberry', category: 'Food' },\n { emoji: '๐', name: 'cherries', category: 'Food' },\n { emoji: '๐', name: 'peach', category: 'Food' },\n { emoji: '๐ฅญ', name: 'mango', category: 'Food' },\n { emoji: '๐', name: 'pineapple', category: 'Food' },\n { emoji: '๐ฅฅ', name: 'coconut', category: 'Food' },\n { emoji: '๐ฅ', name: 'kiwi', category: 'Food' },\n { emoji: '๐
', name: 'tomato', category: 'Food' },\n { emoji: '๐ฅ', name: 'avocado', category: 'Food' },\n { emoji: '๐', name: 'eggplant', category: 'Food' },\n { emoji: '๐ฅ', name: 'potato', category: 'Food' },\n { emoji: '๐ฅ', name: 'carrot', category: 'Food' },\n { emoji: '๐ฝ', name: 'corn', category: 'Food' },\n { emoji: '๐ถ๏ธ', name: 'hot pepper', category: 'Food' },\n { emoji: '๐ฅฆ', name: 'broccoli', category: 'Food' },\n { emoji: '๐', name: 'mushroom', category: 'Food' },\n { emoji: '๐ฅ', name: 'peanuts', category: 'Food' },\n { emoji: '๐', name: 'bread', category: 'Food' },\n { emoji: '๐ฅ', name: 'croissant', category: 'Food' },\n { emoji: '๐ฅฏ', name: 'bagel', category: 'Food' },\n { emoji: '๐ฅ', name: 'pancakes', category: 'Food' },\n { emoji: '๐ง', name: 'cheese', category: 'Food' },\n { emoji: '๐', name: 'meat', category: 'Food' },\n { emoji: '๐', name: 'poultry leg', category: 'Food' },\n { emoji: '๐ฅ', name: 'bacon', category: 'Food' },\n { emoji: '๐', name: 'hamburger', category: 'Food' },\n { emoji: '๐', name: 'fries', category: 'Food' },\n { emoji: '๐', name: 'pizza', category: 'Food' },\n { emoji: '๐ญ', name: 'hot dog', category: 'Food' },\n { emoji: '๐ฅช', name: 'sandwich', category: 'Food' },\n { emoji: '๐ฎ', name: 'taco', category: 'Food' },\n { emoji: '๐ฏ', name: 'burrito', category: 'Food' },\n { emoji: '๐ณ', name: 'egg', category: 'Food' },\n { emoji: '๐ฒ', name: 'stew', category: 'Food' },\n { emoji: '๐ฅฃ', name: 'bowl', category: 'Food' },\n { emoji: '๐ฅ', name: 'salad', category: 'Food' },\n { emoji: '๐ฟ', name: 'popcorn', category: 'Food' },\n { emoji: '๐ฑ', name: 'bento', category: 'Food' },\n { emoji: '๐ฃ', name: 'sushi', category: 'Food' },\n { emoji: '๐ค', name: 'shrimp', category: 'Food' },\n { emoji: '๐ฆ', name: 'ice cream', category: 'Food' },\n { emoji: '๐ง', name: 'shaved ice', category: 'Food' },\n { emoji: '๐จ', name: 'ice cream', category: 'Food' },\n { emoji: '๐ฉ', name: 'donut', category: 'Food' },\n { emoji: '๐ช', name: 'cookie', category: 'Food' },\n { emoji: '๐', name: 'cake', category: 'Food' },\n { emoji: '๐ฐ', name: 'shortcake', category: 'Food' },\n { emoji: '๐ง', name: 'cupcake', category: 'Food' },\n { emoji: '๐ฅง', name: 'pie', category: 'Food' },\n { emoji: '๐ซ', name: 'chocolate', category: 'Food' },\n { emoji: '๐ฌ', name: 'candy', category: 'Food' },\n { emoji: '๐ญ', name: 'lollipop', category: 'Food' },\n { emoji: '๐ฎ', name: 'custard', category: 'Food' },\n { emoji: '๐ฏ', name: 'honey', category: 'Food' },\n { emoji: '๐ผ', name: 'baby bottle', category: 'Food' },\n { emoji: '๐ฅ', name: 'milk', category: 'Food' },\n { emoji: 'โ', name: 'coffee', category: 'Food' },\n { emoji: '๐ต', name: 'tea', category: 'Food' },\n { emoji: '๐ถ', name: 'sake', category: 'Food' },\n { emoji: '๐พ', name: 'champagne', category: 'Food' },\n { emoji: '๐ท', name: 'wine', category: 'Food' },\n { emoji: '๐ธ', name: 'cocktail', category: 'Food' },\n { emoji: '๐น', name: 'tropical drink', category: 'Food' },\n { emoji: '๐บ', name: 'beer', category: 'Food' },\n { emoji: '๐ป', name: 'beers', category: 'Food' },\n { emoji: '๐ฅ', name: 'tumbler glass', category: 'Food' },\n { emoji: '๐ฅค', name: 'soda', category: 'Food' },\n\n // Travel & Places\n { emoji: '๐', name: 'car', category: 'Travel' },\n { emoji: '๐', name: 'taxi', category: 'Travel' },\n { emoji: '๐', name: 'bus', category: 'Travel' },\n { emoji: '๐', name: 'trolleybus', category: 'Travel' },\n { emoji: '๐๏ธ', name: 'racing car', category: 'Travel' },\n { emoji: '๐', name: 'police car', category: 'Travel' },\n { emoji: '๐', name: 'ambulance', category: 'Travel' },\n { emoji: '๐', name: 'fire engine', category: 'Travel' },\n { emoji: '๐', name: 'minibus', category: 'Travel' },\n { emoji: '๐', name: 'truck', category: 'Travel' },\n { emoji: '๐', name: 'articulated lorry', category: 'Travel' },\n { emoji: '๐', name: 'tractor', category: 'Travel' },\n { emoji: '๐ฒ', name: 'bicycle', category: 'Travel' },\n { emoji: '๐ต', name: 'scooter', category: 'Travel' },\n { emoji: '๐๏ธ', name: 'motorcycle', category: 'Travel' },\n { emoji: '๐', name: 'bullet train', category: 'Travel' },\n { emoji: '๐', name: 'train', category: 'Travel' },\n { emoji: 'โ๏ธ', name: 'airplane', category: 'Travel' },\n { emoji: '๐', name: 'rocket', category: 'Travel' },\n { emoji: '๐ธ', name: 'ufo', category: 'Travel' },\n { emoji: '๐', name: 'helicopter', category: 'Travel' },\n { emoji: '๐ข', name: 'ship', category: 'Travel' },\n { emoji: 'โต', name: 'sailboat', category: 'Travel' },\n { emoji: 'โ', name: 'anchor', category: 'Travel' },\n { emoji: 'โฝ', name: 'fuel pump', category: 'Travel' },\n { emoji: '๐ฆ', name: 'traffic light', category: 'Travel' },\n\n // Objects & Tools\n { emoji: '๐ป', name: 'laptop', category: 'Objects' },\n { emoji: '๐ฑ', name: 'mobile', category: 'Objects' },\n { emoji: 'โ๏ธ', name: 'telephone', category: 'Objects' },\n { emoji: 'โจ๏ธ', name: 'keyboard', category: 'Objects' },\n { emoji: '๐ฅ๏ธ', name: 'desktop', category: 'Objects' },\n { emoji: '๐จ๏ธ', name: 'printer', category: 'Objects' },\n { emoji: '๐ธ', name: 'camera', category: 'Objects' },\n { emoji: '๐ฅ', name: 'video camera', category: 'Objects' },\n { emoji: '๐บ', name: 'tv', category: 'Objects' },\n { emoji: '๐ป', name: 'radio', category: 'Objects' },\n { emoji: 'โฐ', name: 'alarm clock', category: 'Objects' },\n { emoji: '๐ก', name: 'light bulb', category: 'Objects' },\n { emoji: '๐ฆ', name: 'flashlight', category: 'Objects' },\n { emoji: '๐ฏ๏ธ', name: 'candle', category: 'Objects' },\n { emoji: '๐จ', name: 'hammer', category: 'Objects' },\n { emoji: '๐ง', name: 'wrench', category: 'Objects' },\n { emoji: '๐ฉ', name: 'nut and bolt', category: 'Objects' },\n { emoji: '๐ซ', name: 'water pistol', category: 'Objects' },\n { emoji: '๐ธ', name: 'money', category: 'Objects' },\n { emoji: '๐ต', name: 'dollar bill', category: 'Objects' },\n { emoji: '๐ณ', name: 'credit card', category: 'Objects' },\n { emoji: '๐', name: 'gem', category: 'Objects' },\n { emoji: 'โ๏ธ', name: 'balance scale', category: 'Objects' },\n { emoji: '๐', name: 'link', category: 'Objects' },\n { emoji: 'โ๏ธ', name: 'chains', category: 'Objects' },\n { emoji: '๐', name: 'syringe', category: 'Objects' },\n { emoji: '๐', name: 'pill', category: 'Objects' },\n { emoji: '๐ช', name: 'door', category: 'Objects' },\n { emoji: '๐๏ธ', name: 'bed', category: 'Objects' },\n { emoji: '๐๏ธ', name: 'couch', category: 'Objects' },\n { emoji: '๐ฟ', name: 'shower', category: 'Objects' },\n { emoji: '๐', name: 'bathtub', category: 'Objects' },\n { emoji: '๐', name: 'key', category: 'Objects' },\n { emoji: '๐งน', name: 'broom', category: 'Objects' },\n\n // Activities & Hobbies\n { emoji: 'โฝ', name: 'soccer', category: 'Activities' },\n { emoji: '๐', name: 'basketball', category: 'Activities' },\n { emoji: '๐', name: 'football', category: 'Activities' },\n { emoji: 'โพ', name: 'baseball', category: 'Activities' },\n { emoji: '๐พ', name: 'tennis', category: 'Activities' },\n { emoji: '๐', name: 'volleyball', category: 'Activities' },\n { emoji: '๐', name: 'rugby', category: 'Activities' },\n { emoji: '๐ฑ', name: 'pool', category: 'Activities' },\n { emoji: 'โณ', name: 'golf', category: 'Activities' },\n { emoji: '๐ช', name: 'kite', category: 'Activities' },\n { emoji: '๐น', name: 'bow and arrow', category: 'Activities' },\n { emoji: '๐ฃ', name: 'fishing', category: 'Activities' },\n { emoji: '๐ฅ', name: 'boxing', category: 'Activities' },\n { emoji: '๐ฅ', name: 'martial arts', category: 'Activities' },\n { emoji: 'โธ๏ธ', name: 'ice skate', category: 'Activities' },\n { emoji: '๐ฟ', name: 'ski', category: 'Activities' },\n { emoji: '๐', name: 'snowboard', category: 'Activities' },\n { emoji: '๐๏ธ', name: 'weightlifter', category: 'Activities' },\n { emoji: '๐คบ', name: 'fencing', category: 'Activities' },\n { emoji: '๐คผ', name: 'wrestling', category: 'Activities' },\n { emoji: '๐คธ', name: 'cartwheel', category: 'Activities' },\n { emoji: '๐', name: 'trophy', category: 'Activities' },\n { emoji: '๐
', name: 'medal', category: 'Activities' },\n { emoji: '๐ฅ', name: 'first place', category: 'Activities' },\n { emoji: '๐๏ธ', name: 'ticket', category: 'Activities' },\n { emoji: '๐ฎ', name: 'video game', category: 'Activities' },\n { emoji: '๐ฒ', name: 'die', category: 'Activities' },\n { emoji: 'โ๏ธ', name: 'chess', category: 'Activities' },\n { emoji: '๐น', name: 'piano', category: 'Activities' },\n { emoji: '๐ธ', name: 'guitar', category: 'Activities' },\n { emoji: '๐บ', name: 'trumpet', category: 'Activities' },\n { emoji: '๐ป', name: 'violin', category: 'Activities' },\n { emoji: '๐ฅ', name: 'drum', category: 'Activities' },\n { emoji: '๐ญ', name: 'performing arts', category: 'Activities' },\n { emoji: '๐จ', name: 'artist palette', category: 'Activities' },\n { emoji: '๐ฌ', name: 'clapper board', category: 'Activities' },\n { emoji: '๐ค', name: 'microphone', category: 'Activities' },\n { emoji: '๐ง', name: 'headphone', category: 'Activities' },\n];\n","import { EMOJI_LIST, EmojiData } from './EmojiList';\n\nexport class EmojiPicker {\n private container: HTMLElement;\n private searchInput: HTMLInputElement;\n private emojiGrid: HTMLElement;\n private onSelect: (emoji: string) => void;\n private onClose: () => void;\n\n constructor(onSelect: (emoji: string) => void, onClose: () => void) {\n this.onSelect = onSelect;\n this.onClose = onClose;\n this.container = this.createPickerElement();\n this.searchInput = this.container.querySelector('.te-emoji-search') as HTMLInputElement;\n this.emojiGrid = this.container.querySelector('.te-emoji-grid') as HTMLElement;\n\n this.setupEvents();\n this.renderEmojis(EMOJI_LIST);\n }\n\n private createPickerElement(): HTMLElement {\n const el = document.createElement('div');\n el.classList.add('te-emoji-picker');\n el.innerHTML = `\n <div class=\"te-emoji-header\">\n <input type=\"text\" class=\"te-emoji-search\" placeholder=\"Search emoji...\">\n </div>\n <div class=\"te-emoji-body\">\n <div class=\"te-emoji-grid\"></div>\n </div>\n `;\n return el;\n }\n\n private setupEvents(): void {\n // Prevent toolbar/editor focus stealing when interacting with the search box\n this.searchInput.addEventListener('mousedown', (e) => e.stopPropagation());\n this.searchInput.addEventListener('click', (e) => e.stopPropagation());\n\n this.searchInput.addEventListener('input', () => {\n const query = this.searchInput.value.toLowerCase();\n const filtered = EMOJI_LIST.filter(e =>\n e.name.toLowerCase().includes(query) ||\n e.category.toLowerCase().includes(query)\n );\n this.renderEmojis(filtered);\n });\n\n // Close on click outside\n const handleOutsideClick = (e: MouseEvent) => {\n if (!this.container.contains(e.target as Node)) {\n this.close();\n document.removeEventListener('mousedown', handleOutsideClick);\n }\n };\n setTimeout(() => document.addEventListener('mousedown', handleOutsideClick), 0);\n }\n\n private renderEmojis(emojis: EmojiData[]): void {\n this.emojiGrid.innerHTML = '';\n\n if (emojis.length === 0) {\n this.emojiGrid.innerHTML = '<div class=\"te-emoji-empty\">No emoji found</div>';\n return;\n }\n\n // Group by category if we're not searching\n const isSearching = this.searchInput.value.length > 0;\n\n if (!isSearching) {\n const categories = ['Smileys', 'Symbols', 'Hands', 'Animals', 'Food', 'Travel', 'Objects', 'Activities'];\n categories.forEach(cat => {\n const catEmojis = emojis.filter(e => e.category === cat);\n if (catEmojis.length > 0) {\n const title = document.createElement('div');\n title.classList.add('te-emoji-category-title');\n title.textContent = cat;\n this.emojiGrid.appendChild(title);\n\n this.renderGridItems(catEmojis);\n }\n });\n } else {\n this.renderGridItems(emojis);\n }\n }\n\n private renderGridItems(emojis: EmojiData[]): void {\n emojis.forEach(item => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.classList.add('te-emoji-item');\n btn.textContent = item.emoji;\n btn.title = item.name;\n\n btn.addEventListener('click', () => {\n this.onSelect(item.emoji);\n this.close();\n });\n\n this.emojiGrid.appendChild(btn);\n });\n }\n\n public show(referenceEl: HTMLElement): void {\n document.body.appendChild(this.container);\n\n const rect = referenceEl.getBoundingClientRect();\n const pickerWidth = 280;\n\n let top = rect.bottom + window.scrollY + 5;\n let left = rect.left + window.scrollX;\n\n // Boundary check\n if (left + pickerWidth > window.innerWidth) {\n left = window.innerWidth - pickerWidth - 10;\n }\n\n this.container.style.top = `${top}px`;\n this.container.style.left = `${left}px`;\n\n this.searchInput.focus();\n }\n\n public close(): void {\n if (this.container.parentElement) {\n this.container.remove();\n this.onClose();\n }\n }\n\n public get el(): HTMLElement {\n return this.container;\n }\n}\n","import { CoreEditor } from '../core/Editor';\nimport { ToolbarItem } from './toolbar/ToolbarItem';\nimport { toolbarItems } from './toolbar/registry';\nimport { EmojiPicker } from './toolbar/EmojiPicker';\n\nexport class Toolbar {\n private editor: CoreEditor;\n private container: HTMLElement;\n private savedRange: Range | null = null;\n private items: ToolbarItem[] = toolbarItems;\n private activePicker: EmojiPicker | null = null;\n\n constructor(editor: CoreEditor) {\n this.editor = editor;\n this.container = this.createToolbarElement();\n this.render();\n }\n\n private createToolbarElement(): HTMLElement {\n const el = document.createElement('div');\n el.classList.add('te-toolbar');\n return el;\n }\n\n private render(): void {\n this.items.forEach(item => {\n if (item.type === 'button') {\n this.renderButton(item);\n } else if (item.type === 'select') {\n this.renderSelect(item);\n } else if (item.type === 'input') {\n this.renderInput(item);\n } else if (item.type === 'color-picker') {\n this.renderColorPicker(item);\n } else if (item.type === 'divider') {\n const divider = document.createElement('div');\n divider.classList.add('te-divider');\n this.container.appendChild(divider);\n }\n });\n\n // Handle selection change to update states\n this.editor.el.addEventListener('keyup', () => this.updateActiveStates());\n this.editor.el.addEventListener('mouseup', () => this.updateActiveStates());\n }\n\n private renderButton(item: ToolbarItem): void {\n const button = document.createElement('button');\n button.classList.add('te-button');\n button.innerHTML = item.icon || '';\n button.title = item.title;\n\n button.addEventListener('mousedown', (e) => {\n e.preventDefault();\n if (item.command === 'insertEmoji') {\n if (!this.activePicker) {\n this.activePicker = new EmojiPicker(\n (emoji) => {\n this.editor.execute('insertText', emoji);\n },\n () => { this.activePicker = null; }\n );\n this.activePicker.show(button);\n } else {\n this.activePicker.close();\n }\n return;\n }\n\n if (item.command === 'createLink') {\n const url = window.prompt('Enter the URL');\n if (url) {\n this.editor.createLink(url);\n }\n return;\n }\n\n if (item.command) {\n this.editor.execute(item.command, item.value || null);\n }\n this.updateActiveStates();\n });\n\n this.container.appendChild(button);\n }\n\n private renderInput(item: ToolbarItem): void {\n const input = document.createElement('input');\n input.type = 'number';\n input.classList.add('te-input');\n input.title = item.title;\n input.value = item.value || '';\n input.min = '1';\n input.max = '100';\n\n const handleActiveSelection = () => {\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n if (this.editor.el.contains(range.commonAncestorContainer)) {\n this.savedRange = range.cloneRange();\n }\n }\n };\n\n input.addEventListener('mousedown', handleActiveSelection);\n input.addEventListener('focus', handleActiveSelection);\n\n const applyChange = () => {\n let val = parseInt(input.value, 10);\n if (isNaN(val)) return;\n val = Math.max(1, Math.min(100, val));\n input.value = val.toString();\n\n if (item.command === 'fontSize') {\n if (this.savedRange) {\n const newRange = this.editor.setStyle('font-size', `${val}px`, this.savedRange);\n if (newRange) this.savedRange = newRange;\n } else {\n this.editor.setStyle('font-size', `${val}px`);\n }\n input.focus();\n }\n };\n\n input.addEventListener('input', applyChange);\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n applyChange();\n this.editor.focus();\n }\n });\n\n this.container.appendChild(input);\n }\n\n private renderSelect(item: ToolbarItem): void {\n const select = document.createElement('select');\n select.classList.add('te-select');\n select.title = item.title;\n\n if (item.options) {\n item.options.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt.value;\n option.textContent = opt.label;\n select.appendChild(option);\n });\n }\n\n select.addEventListener('change', () => {\n const value = select.value;\n if (this.savedRange) {\n this.editor.selection.restoreSelection(this.savedRange);\n }\n\n if (item.command === 'formatBlock') {\n this.editor.execute(item.command, value);\n } else if (item.command === 'fontFamily') {\n this.editor.setStyle('font-family', value);\n }\n this.editor.focus();\n });\n\n select.addEventListener('mousedown', () => {\n this.savedRange = this.editor.selection.saveSelection();\n });\n\n this.container.appendChild(select);\n }\n\n private renderColorPicker(item: ToolbarItem): void {\n const input = document.createElement('input');\n input.type = 'color';\n input.classList.add('te-color-picker');\n input.title = item.title;\n input.value = item.value || '#000000';\n\n input.addEventListener('mousedown', () => {\n this.savedRange = this.editor.selection.saveSelection();\n });\n\n input.addEventListener('change', () => {\n if (this.savedRange) {\n this.editor.selection.restoreSelection(this.savedRange);\n }\n if (item.command) {\n this.editor.execute(item.command, input.value);\n }\n this.editor.focus();\n });\n\n this.container.appendChild(input);\n }\n\n public get el(): HTMLElement {\n return this.container;\n }\n\n private updateActiveStates(): void {\n const buttons = this.container.querySelectorAll('.te-button');\n let btnIndex = 0;\n\n this.items.forEach((item) => {\n if (item.type === 'button') {\n const button = buttons[btnIndex++] as HTMLElement;\n if (item.command && document.queryCommandState(item.command)) {\n button.classList.add('active');\n } else {\n button.classList.remove('active');\n }\n }\n });\n }\n}\n","import { CoreEditor, EditorOptions } from './core/Editor';\nimport { Toolbar } from './ui/Toolbar';\nimport './styles/editor.css';\n\nexport class TestEditor extends CoreEditor {\n private toolbar: Toolbar;\n\n constructor(container: HTMLElement, options: EditorOptions = {}) {\n super(container, options);\n \n this.toolbar = new Toolbar(this);\n // Move toolbar to the top of the container\n this.container.insertBefore(this.toolbar.el, this.editableElement);\n }\n}\n\nexport { CoreEditor, type EditorOptions } from './core/Editor';\nexport { SelectionManager } from './core/SelectionManager';\nexport { Toolbar } from './ui/Toolbar';\n"],"names":["SelectionManager","selection","range","element","CoreEditor","container","options","text","span","prop","val","newRange","el","command","value","fragment","property","walker","node","numValue","parent","resultRange","parentSpan","e","url","anchor","html","undo","redo","heading","fontFamily","fontSize","bold","italic","underline","strikethrough","textColor","highlightColor","alignLeft","alignCenter","alignRight","alignJustify","bulletList","orderedList","outdent","indent","horizontalRule","clearFormatting","emoji","link","divider","toolbarItems","EMOJI_LIST","EmojiPicker","onSelect","onClose","query","filtered","handleOutsideClick","emojis","cat","catEmojis","title","item","btn","referenceEl","rect","pickerWidth","top","left","Toolbar","editor","button","input","handleActiveSelection","applyChange","select","opt","option","buttons","btnIndex","TestEditor"],"mappings":"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"}
|