@editora/react
Advanced tools
+21
| MIT License | ||
| Copyright (c) 2026 Ajay Kumar | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
@@ -1,1 +0,1 @@ | ||
| "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),c=require("react"),I=require("@editora/core"),K=({isOpen:e,options:t,onSelect:u,onClose:s,anchorRef:i,className:a=""})=>{const g=c.useRef(null),[m,b]=c.useState({top:0,left:0});return c.useEffect(()=>{if(e&&i.current){const r=i.current.getBoundingClientRect(),d=120,w=t.length*36;let h=r.bottom+4,f=r.left;const p=window.innerWidth,x=window.innerHeight;f+d>p&&(f=p-d-8),h+w>x&&(h=r.top-w-4),b({top:h,left:f})}},[e,i,t.length]),c.useEffect(()=>{if(e&&i.current&&g.current){const r=i.current.getBoundingClientRect(),d=g.current.getBoundingClientRect();let w=r.bottom+4,h=r.left;const f=window.innerWidth,p=window.innerHeight;h+d.width>f&&(h=f-d.width-8),w+d.height>p&&(w=r.top-d.height-4),b({top:w,left:h})}},[e]),c.useEffect(()=>{const r=w=>{g.current&&!g.current.contains(w.target)&&i.current&&!i.current.contains(w.target)&&s()},d=w=>{w.key==="Escape"&&s()};return e&&(document.addEventListener("mousedown",r),document.addEventListener("keydown",d)),()=>{document.removeEventListener("mousedown",r),document.removeEventListener("keydown",d)}},[e,s,i]),e?o.jsx("div",{ref:g,className:`rte-inline-menu ${a}`,style:{position:"fixed",top:m.top,left:m.left,zIndex:1e3,background:"white",border:"1px solid #ccc",borderRadius:"4px",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.15)",minWidth:"120px",maxWidth:"200px",pointerEvents:"auto"},children:t.map(r=>o.jsx("div",{className:"rte-inline-menu-item",onClick:()=>{u(r.value),s()},style:{padding:"8px 12px",cursor:"pointer",borderBottom:"1px solid #f0f0f0",fontSize:"14px",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},onMouseEnter:d=>{d.currentTarget.style.backgroundColor="#f5f5f5"},onMouseLeave:d=>{d.currentTarget.style.backgroundColor="transparent"},children:r.label},r.value))}):null},H=({editor:e,position:t="top",sticky:u=!1,floating:s=!1})=>{const[i,a]=c.useState(null),[g,m]=c.useState(null),[b,r]=c.useState(null),[d,w]=c.useState(null),[h,f]=c.useState(!1),p=c.useRef({}),x=c.useRef(null),y=c.useRef(null),C=c.useRef(null),v=e.pluginManager.getToolbarItems();c.useEffect(()=>{const n=()=>{if(!x.current||!y.current)return;const N=x.current.clientWidth,A=16,Q=40,F=4,Y=N-A-Q-F;let B=0,O=0;const U=y.current.children;for(let D=0;D<U.length;D++){const q=U[D].offsetWidth+F;if(B+q<=Y)B+=q,O++;else break}w(Math.max(1,O))},l=requestAnimationFrame(()=>{n()}),E=new ResizeObserver(()=>{n()});x.current&&E.observe(x.current);const k=new MutationObserver(()=>{n()});return y.current&&k.observe(y.current,{childList:!0,subtree:!0}),()=>{cancelAnimationFrame(l),E.disconnect(),k.disconnect()}},[v.length]);const T=n=>(p.current[n]||(p.current[n]=c.createRef()),p.current[n]),S=(n,l)=>{const E=x.current?.closest("[data-editora-editor]"),k=E?.querySelector(".rte-content");if(k&&k.focus(),b&&(n==="setTextAlignment"||n==="setFontFamily"||n==="setBlockType")){const A=window.getSelection();A&&(A.removeAllRanges(),A.addRange(b)),r(null)}typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(n,l),a(null);const N=E?.querySelector(".rte-content");N&&N.focus()},R=n=>{const l=window.getSelection();l&&l.rangeCount>0&&r(l.getRangeAt(0).cloneRange()),a(i===n?null:n)},j=n=>{const l=window.getSelection();l&&l.rangeCount>0&&r(l.getRangeAt(0).cloneRange()),m(g===n?null:n),a(null)},L=(n,l)=>{if(b){const E=window.getSelection();E&&(E.removeAllRanges(),E.addRange(b)),r(null)}S(n,l),m(null)},M=(n,l)=>n&&n.startsWith("<svg")&&n.endsWith("</svg>")?o.jsx("span",{dangerouslySetInnerHTML:{__html:n}}):n&&n.length===1&&/^[BIUSH]$/.test(n)?o.jsx("span",{style:{fontWeight:"bold",fontSize:"14px",lineHeight:"1"},children:n}):n||"⚪";if(s)return null;const J={...u&&{position:"sticky",top:0,zIndex:100,backgroundColor:"#fff",boxShadow:"0 2px 4px rgba(0,0,0,0.1)"},...t==="bottom"&&{order:2}},z=n=>n.map((l,E)=>o.jsx("div",{className:"rte-toolbar-item",style:{display:d!==null&&E>=d?"none":"flex"},children:l.type==="dropdown"?o.jsxs("div",{className:"rte-toolbar-dropdown",children:[o.jsxs("button",{className:"rte-toolbar-button","data-command":l.command,"data-active":"false",onClick:()=>R(l.command),children:[l.label," ▼"]}),i===l.command&&o.jsx("div",{className:"rte-toolbar-dropdown-menu",children:l.options?.map(k=>o.jsx("div",{className:"rte-toolbar-dropdown-item",onClick:()=>S(l.command,k.value),children:k.label},k.value))})]}):l.type==="inline-menu"?o.jsx("button",{ref:T(l.command),className:"rte-toolbar-button","data-command":l.command,"data-active":"false",onClick:()=>j(l.command),title:l.label,children:M(l.icon,l.command)}):l.type==="input"?o.jsx("input",{type:"text",className:`rte-toolbar-input ${l.label.toLowerCase().replace(/\s+/g,"-")}`,placeholder:l.placeholder,onChange:k=>S(l.command,k.target.value),onKeyDown:k=>{k.key==="Enter"&&S(l.command,k.target.value)},title:l.label}):l.type==="group"?o.jsx("div",{className:`rte-toolbar-group-button ${l.label.toLowerCase().replace(/\s+/g,"-")}`,title:`${l.label}`,children:o.jsx("div",{className:`rte-toolbar-group-items ${l.label.toLowerCase().replace(/\s+/g,"-")}`,children:z(l.items||[])})}):o.jsx("button",{className:"rte-toolbar-button","data-command":l.command,"data-active":"false",onClick:()=>S(l.command),title:l.label,children:M(l.icon,l.command)})},E));return o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:"rte-toolbar-wrapper",style:J,children:[o.jsxs("div",{className:"rte-toolbar",ref:x,children:[o.jsx("div",{className:"rte-toolbar-items-container",ref:y,children:z(v)}),d!==null&&d<v.length&&o.jsx("button",{ref:C,className:`rte-toolbar-more-button ${h?"active":""}`,onClick:()=>f(!h),title:"Show more options","aria-label":"More toolbar options",children:"☰"})]}),d!==null&&d<v.length&&o.jsx("div",{className:`rte-toolbar-expanded-row ${h?"show":""}`,children:v.map((n,l)=>l>=(d||0)&&o.jsx("div",{className:"rte-toolbar-item",children:n.type==="dropdown"?o.jsxs("div",{className:"rte-toolbar-dropdown",children:[o.jsxs("button",{className:"rte-toolbar-button","data-command":n.command,"data-active":"false",onClick:()=>R(n.command),children:[n.label," ▼"]}),i===n.command&&o.jsx("div",{className:"rte-toolbar-dropdown-menu",children:n.options?.map(E=>o.jsx("div",{className:"rte-toolbar-dropdown-item",onClick:()=>S(n.command,E.value),children:E.label},E.value))})]}):n.type==="inline-menu"?o.jsx("button",{ref:T(n.command),className:"rte-toolbar-button","data-command":n.command,"data-active":"false",onClick:()=>j(n.command),title:n.label,children:M(n.icon,n.command)}):n.type==="input"?o.jsx("input",{type:"text",className:"rte-toolbar-input",placeholder:n.placeholder,onChange:E=>S(n.command,E.target.value),onKeyDown:E=>{E.key==="Enter"&&S(n.command,E.target.value)},title:n.label}):o.jsx("button",{className:"rte-toolbar-button","data-command":n.command,"data-active":"false",onClick:()=>S(n.command),title:n.label,children:M(n.icon,n.command)})},l))})]}),v.map(n=>n.type==="inline-menu"?o.jsx(K,{isOpen:g===n.command,options:n.options||[],onSelect:l=>L(n.command,l),onClose:()=>m(null),anchorRef:T(n.command)},`menu-${n.command}`):null)]})};function Z(e,t){const u=c.useRef(),s=c.useRef("");return c.useEffect(()=>{if(!t?.enabled)return;const a=t.intervalMs||3e4,g=t.storageKey||"rte-autosave",m=t.provider||"localStorage",b=async()=>{const r=e();if(r!==s.current){if(s.current=r,m==="localStorage")try{localStorage.setItem(g,r),localStorage.setItem(`${g}-timestamp`,Date.now().toString()),console.log("[Autosave] Content saved to localStorage")}catch(d){console.error("[Autosave] Failed to save to localStorage:",d)}else if(m==="api"&&t.apiUrl)try{await fetch(t.apiUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:r,timestamp:Date.now()})}),console.log("[Autosave] Content saved to API")}catch(d){console.error("[Autosave] Failed to save to API:",d)}}};return u.current=setInterval(b,a),()=>{u.current&&clearInterval(u.current)}},[t?.enabled,t?.intervalMs,t?.storageKey,t?.provider,t?.apiUrl,e]),{restore:()=>{if(!t?.enabled)return null;const a=t.storageKey||"rte-autosave";if((t.provider||"localStorage")==="localStorage")try{const m=localStorage.getItem(a),b=localStorage.getItem(`${a}-timestamp`);if(m&&b)return console.log("[Autosave] Restored from localStorage, saved at:",new Date(parseInt(b))),m}catch(m){console.error("[Autosave] Failed to restore from localStorage:",m)}return null}}}const ee=["p","br","strong","em","u","s","b","i","h1","h2","h3","h4","h5","h6","ul","ol","li","a","img","video","audio","table","thead","tbody","tr","th","td","blockquote","pre","code","span","div","sup","sub","hr"],te={"*":["class","style","id","data-*"],a:["href","target","rel","title"],img:["src","alt","width","height","loading"],video:["src","controls","width","height","autoplay","loop","muted"],audio:["src","controls","autoplay","loop","muted"],table:["border","cellpadding","cellspacing"],td:["colspan","rowspan","align","valign"],th:["colspan","rowspan","align","valign"]};function P(e,t,u){if(t?.sanitize===!1)return e;const s=t?.allowedTags&&t.allowedTags.length>0?t.allowedTags:ee,i=t?.allowedAttributes||te,a=document.createElement("div");return a.innerHTML=e,$(a,s,i),a.innerHTML}function $(e,t,u){const s=Array.from(e.childNodes);for(const i of s)if(i.nodeType===Node.ELEMENT_NODE){const a=i,g=a.tagName.toLowerCase();if(!t.includes(g)){for(;a.firstChild;)e.insertBefore(a.firstChild,a);e.removeChild(a);continue}ne(a,u),$(a,t,u)}else{if(i.nodeType===Node.TEXT_NODE)continue;e.removeChild(i)}}function ne(e,t){const u=e.tagName.toLowerCase(),s=Array.from(e.attributes),i=t[u]||[],a=t["*"]||[],g=[...i,...a];for(const m of s){const b=m.name.toLowerCase();let r=!1;g.includes(b)&&(r=!0);for(const d of g)if(d.endsWith("*")){const w=d.slice(0,-1);if(b.startsWith(w)){r=!0;break}}(b.startsWith("on")||b==="javascript:"||b==="href"&&m.value.trim().toLowerCase().startsWith("javascript:")||b==="src"&&m.value.trim().toLowerCase().startsWith("javascript:"))&&(r=!1),r||e.removeAttribute(m.name)}e.hasAttribute("href")&&(e.getAttribute("href")||"").trim().toLowerCase().startsWith("javascript:")&&e.removeAttribute("href"),e.hasAttribute("src")&&(e.getAttribute("src")||"").trim().toLowerCase().startsWith("javascript:")&&e.removeAttribute("src")}function oe(e,t,u){return u?.sanitizeOnPaste===!1?e:P(e,t)}function re(e,t,u){return u?.sanitizeOnInput===!1?e:P(e,t)}const V=({editor:e,defaultValue:t,value:u,onChange:s,pasteConfig:i,contentConfig:a,securityConfig:g,performanceConfig:m,autosaveConfig:b})=>{const r=c.useRef(null),d=u!==void 0,w=c.useRef(),{restore:h}=Z(()=>r.current?.innerHTML||"",b);return c.useEffect(()=>{if(!r.current)return;const f=h(),p=f||u||t;p&&r.current.innerHTML!==p&&(r.current.innerHTML=p,f&&s&&s(f))},[]),c.useEffect(()=>{!r.current||!d||u!==r.current.innerHTML&&(r.current.innerHTML=u)},[u,d]),c.useEffect(()=>{if(!r.current)return;const f=()=>{if(!r.current||!s)return;let C=r.current.innerHTML;if(g?.sanitizeOnInput!==!1&&a?.sanitize!==!1&&(C=re(C,a,g),C!==r.current.innerHTML)){const v=window.getSelection(),T=v&&v.rangeCount>0?v.getRangeAt(0):null;if(r.current.innerHTML=C,T&&v)try{v.removeAllRanges(),v.addRange(T)}catch{}}m?.debounceInputMs?(w.current&&clearTimeout(w.current),w.current=setTimeout(()=>{s(C)},m.debounceInputMs)):s(C)},p=C=>{C.preventDefault();let v=C.clipboardData?.getData("text/html");const T=C.clipboardData?.getData("text/plain");if(i?.clean||!i?.keepFormatting){T&&document.execCommand("insertText",!1,T);return}if(v){g?.sanitizeOnPaste!==!1&&a?.sanitize!==!1&&(v=oe(v,a,g));const S=window.getSelection();if(S&&S.rangeCount>0){const R=S.getRangeAt(0);R.deleteContents();const j=document.createElement("div");j.innerHTML=v;const L=document.createDocumentFragment();for(;j.firstChild;)L.appendChild(j.firstChild);R.insertNode(L),R.collapse(!1),S.removeAllRanges(),S.addRange(R)}}else T&&document.execCommand("insertText",!1,T)},x=C=>{const v=C.target;(v.tagName==="IMG"||v.tagName==="VIDEO")&&(v.style.resize="both",v.style.overflow="auto",v.style.display="inline-block")},y=r.current;return y.addEventListener("input",f),y.addEventListener("paste",p),y.addEventListener("click",x),y.focus(),()=>{w.current&&clearTimeout(w.current),y.removeEventListener("input",f),y.removeEventListener("paste",p),y.removeEventListener("click",x)}},[e,s,i,a,g,m]),c.useEffect(()=>{if(!r.current||typeof window>"u")return;const f=new I.KeyboardShortcutManager,p=r.current,x=y=>{f.handleKeyDown(y,(C,v)=>{typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(C,v)})};return p.addEventListener("keydown",x),()=>{p.removeEventListener("keydown",x)}},[]),o.jsx("div",{ref:r,contentEditable:!0,suppressContentEditableWarning:!0,className:"rte-content",style:{minHeight:"200px",maxHeight:"100%",padding:"16px",outline:"none",border:"1px solid #ddd",borderRadius:"4px",fontSize:"14px",lineHeight:"1.5",overflow:"auto",flex:1,boxSizing:"border-box",wordWrap:"break-word",overflowWrap:"break-word"},children:o.jsx("p",{children:o.jsx("br",{})})})},ae=({editor:e,isEnabled:t})=>{const[u,s]=c.useState(!1),[i,a]=c.useState({top:0,left:0}),g=c.useRef(null),m=c.useRef(null),b=c.useRef(null),r=c.useRef(null);c.useEffect(()=>{if(!t){s(!1);return}r.current=g.current?.closest("[data-editora-editor]");const w=()=>{b.current&&clearTimeout(b.current);const f=window.getSelection();if(!f||f.rangeCount===0){s(!1),m.current=null;return}const p=f.getRangeAt(0),x=f.toString().trim(),y=r.current?.querySelector(".rte-content");if(!y||!y.contains(p.commonAncestorContainer)){s(!1),m.current=null;return}if(x.length>0){const C=p.getBoundingClientRect(),v=y.getBoundingClientRect(),T=300;if(C&&v){const S=C.top-50;let R=C.left+C.width/2;const j=T/2,L=v.left,M=v.right;R-j<L&&(R=L+j+10),R+j>M&&(R=M-j-10),a({top:S,left:R}),b.current=setTimeout(()=>{s(!0),m.current=p.cloneRange()},300)}}else s(!1),m.current=null},h=f=>{g.current&&!g.current.contains(f.target)&&(window.getSelection(),r.current?.querySelector(".rte-content")?.contains(f.target)||(s(!1),m.current=null))};return document.addEventListener("selectionchange",w),document.addEventListener("mousedown",h),document.addEventListener("keydown",f=>{f.key==="Escape"&&(s(!1),m.current=null)}),()=>{document.removeEventListener("selectionchange",w),document.removeEventListener("mousedown",h),b.current&&clearTimeout(b.current)}},[t]);const d=(w,h)=>{if(!m.current)return;const f=r.current?.querySelector(".rte-content");f&&f.focus(),{toggleBold:()=>document.execCommand("bold",!1),toggleItalic:()=>document.execCommand("italic",!1),toggleUnderline:()=>document.execCommand("underline",!1),toggleStrikethrough:()=>document.execCommand("strikeThrough",!1),createLink:()=>{typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand("openLinkDialog")},clearFormatting:()=>{document.execCommand("removeFormat",!1),document.execCommand("unlink",!1)},toggleCode:()=>{const x=window.getSelection();if(x&&x.rangeCount>0){const y=x.getRangeAt(0),C=document.createElement("code");y.surroundContents(C)}},setBlockType:()=>{if(h==="blockquote"){const x=window.getSelection();if(x&&x.rangeCount>0){const y=x.getRangeAt(0);(y.commonAncestorContainer.nodeType===Node.TEXT_NODE?y.commonAncestorContainer.parentElement:y.commonAncestorContainer)?.closest?.("blockquote")?document.execCommand("formatBlock",!1,"p"):document.execCommand("formatBlock",!1,"blockquote")}}else h&&document.execCommand("formatBlock",!1,h)}}[w]?.(),s(!1),m.current=null,f&&f.focus()};return!t||!u?null:o.jsxs("div",{ref:g,className:"floating-toolbar",style:{position:"fixed",top:`${i.top}px`,left:`${i.left}px`,transform:"translateX(-50%)",zIndex:1e3,background:"white",border:"1px solid #e1e5e9",borderRadius:"6px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"6px",display:"flex",gap:"4px",alignItems:"center"},children:[o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("toggleBold"),title:"Bold (Ctrl+B)",children:o.jsx("strong",{children:"B"})}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("toggleItalic"),title:"Italic (Ctrl+I)",children:o.jsx("em",{children:"I"})}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("toggleUnderline"),title:"Underline (Ctrl+U)",children:o.jsx("u",{children:"U"})}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("toggleStrikethrough"),title:"Strikethrough",children:o.jsx("s",{children:"S"})}),o.jsx("div",{className:"floating-toolbar-separator"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("clearFormatting"),title:"Clear Formatting",children:"⌫"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("createLink"),title:"Insert Link",children:"🔗"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("toggleCode"),title:"Code",children:"Code"}),o.jsx("div",{className:"floating-toolbar-separator"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>d("setBlockType","blockquote"),title:"Quote",children:"❝"})]})},le=({plugins:e,children:t})=>{const u=e.filter(i=>i.context?.provider);return u.length===0?o.jsx(o.Fragment,{children:t}):u.reduce((i,a)=>{const g=a.context.provider;return o.jsx(g,{children:i},a.name)},o.jsx(o.Fragment,{children:t}))},ie={toolbar:{items:[],floating:!1,sticky:!1},menubar:{enabled:!1,items:[]},contextMenu:{enabled:!0},media:{uploadUrl:"",libraryUrl:"",maxFileSize:10*1024*1024,allowedTypes:["image/jpeg","image/png","image/gif","image/webp"],headers:{},withCredentials:!1},paste:{clean:!0,keepFormatting:!1,convertWord:!0},history:{maxSteps:100,debounceMs:300},language:{locale:"en",direction:"ltr"},spellcheck:{enabled:!1,provider:"browser",apiUrl:"",apiHeaders:{}},autosave:{enabled:!1,intervalMs:3e4,storageKey:"rte-autosave",provider:"localStorage",apiUrl:""},accessibility:{enableARIA:!0,keyboardNavigation:!0,checker:!1},performance:{debounceInputMs:100,viewportOnlyScan:!0},content:{allowedTags:[],allowedAttributes:{},sanitize:!0},security:{sanitizeOnPaste:!0,sanitizeOnInput:!0}};function _(e,t){const u={...e};for(const s in t){const i=t[s],a=u[s];i!==void 0&&(typeof i=="object"&&i!==null&&!Array.isArray(i)&&typeof a=="object"&&a!==null&&!Array.isArray(a)?u[s]=_(a,i):u[s]=i)}return u}function G(e){const t=_(ie,{toolbar:e.toolbar,menubar:e.menubar,contextMenu:e.contextMenu,media:e.media,paste:e.paste,history:e.history,language:e.language,spellcheck:e.spellcheck,autosave:e.autosave,accessibility:e.accessibility,performance:e.performance,content:e.content,security:e.security});return e.floatingToolbar!==void 0&&(t.toolbar={...t.toolbar,floating:e.floatingToolbar.enabled??t.toolbar.floating}),e.mediaConfig&&(t.media={...t.media,uploadUrl:e.mediaConfig.uploadUrl||t.media.uploadUrl,libraryUrl:e.mediaConfig.libraryUrl||t.media.libraryUrl,maxFileSize:e.mediaConfig.maxFileSize||t.media.maxFileSize,allowedTypes:e.mediaConfig.allowedTypes||t.media.allowedTypes}),{...t,id:e.id,className:e.className,value:e.value,defaultValue:e.defaultValue,onChange:e.onChange,onInit:e.onInit,onDestroy:e.onDestroy,plugins:Array.isArray(e.plugins)?e.plugins.filter(s=>typeof s!="string"):[],pluginConfig:e.pluginConfig||{}}}const W=new Map;typeof window<"u"&&(window.registerEditorCommand=(e,t)=>{W.set(e,t)},window.executeEditorCommand=(e,t)=>{const u=W.get(e);return u?u(t):(console.warn(`No handler registered for command: ${e}`),!1)});const se=e=>{const t=c.useMemo(()=>G(e),[e.id,e.className,e.value,e.defaultValue,e.plugins,e.toolbar,e.menubar,e.contextMenu,e.media,e.paste,e.history,e.language,e.spellcheck,e.autosave,e.accessibility,e.performance,e.content,e.security,e.floatingToolbar,e.mediaConfig]),u=c.useRef(null),s=c.useRef(null),i=c.useRef(e.onInit),a=c.useRef(e.onDestroy),g=c.useRef(null);c.useEffect(()=>{i.current=e.onInit,a.current=e.onDestroy});const m=c.useMemo(()=>{const w=new I.PluginManager;t.plugins.forEach(f=>{w.register(f),f.commands&&typeof window<"u"&&Object.entries(f.commands).forEach(([p,x])=>{W.set(p,x)})});const h=new I.Editor(w);return u.current=h,h},[t.plugins]);c.useEffect(()=>{const w={getHTML:()=>g.current?.querySelector(".rte-content")?.innerHTML||"",setHTML:h=>{const f=g.current?.querySelector(".rte-content");f&&(f.innerHTML=h)},execCommand:(h,f)=>{typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(h,f)},registerCommand:(h,f)=>{typeof window<"u"&&window.registerEditorCommand&&window.registerEditorCommand(h,f)},focus:()=>{g.current?.querySelector(".rte-content")?.focus()},blur:()=>{g.current?.querySelector(".rte-content")?.blur()},destroy:()=>{a.current&&a.current()},onChange:h=>()=>{},getState:()=>({plugins:t.plugins,config:t}),toolbar:{items:m.toolbar?.items||[]}};return s.current=w,i.current&&i.current(w),()=>{a.current&&a.current()}},[]);const b=t.toolbar.floating??!1,r=t.toolbar.position||"top",d=t.toolbar.sticky??!1;return o.jsx(le,{plugins:t.plugins,children:o.jsxs("div",{ref:g,id:t.id,"data-editora-editor":!0,className:`rte-editor ${t.className||""}`,dir:t.language.direction,style:{display:"flex",flexDirection:"column",height:"100%"},children:[r!=="bottom"&&o.jsx(H,{editor:m,position:r,sticky:d,floating:b}),o.jsx(V,{editor:m,defaultValue:t.defaultValue,value:t.value,onChange:t.onChange,pasteConfig:t.paste,contentConfig:t.content,securityConfig:t.security,performanceConfig:t.performance,autosaveConfig:t.autosave}),r==="bottom"&&o.jsx(H,{editor:m,position:r,sticky:d,floating:b}),o.jsx(ae,{editor:m,isEnabled:b})]})})},X=e=>o.jsx(se,{...e});function ce(e={}){const t=c.useRef(null),u=c.useRef(e.onCommand);return c.useEffect(()=>{u.current=e.onCommand}),c.useEffect(()=>{if(typeof window>"u"||e.enabled===!1)return;const s=new I.KeyboardShortcutManager(e);t.current=s;const i=g=>s.handleKeyDown(g,(b,r)=>{u.current&&u.current(b,r),typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(b,r)}),a=e.editorElement||document;return a&&a.addEventListener("keydown",i),()=>{a&&a.removeEventListener("keydown",i)}},[e.editorElement,e.enabled,e.shortcuts,e.customShortcuts]),{getShortcuts:()=>t.current?.getAllShortcuts()||[],getShortcutForCommand:s=>t.current?.getShortcutForCommand(s),getShortcutsHelp:()=>t.current?.getShortcutsHelp()||"",enable:()=>t.current?.enable(),disable:()=>t.current?.disable(),isEnabled:()=>t.current?.isEnabled()||!1}}exports.EditorContent=V;exports.EditoraEditor=X;exports.InlineMenu=K;exports.RichTextEditor=X;exports.Toolbar=H;exports.mergeConfig=G;exports.useKeyboardShortcuts=ce; | ||
| "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),i=require("react"),j=require("@editora/core"),P=({isOpen:e,options:t,onSelect:g,onClose:u,anchorRef:s,className:a=""})=>{const b=i.useRef(null),[d,w]=i.useState({top:0,left:0});return i.useEffect(()=>{if(e&&s.current){const r=s.current.getBoundingClientRect(),f=120,p=t.length*36;let C=r.bottom+4,c=r.left;const m=window.innerWidth,h=window.innerHeight;c+f>m&&(c=m-f-8),C+p>h&&(C=r.top-p-4),w({top:C,left:c})}},[e,s,t.length]),i.useEffect(()=>{if(e&&s.current&&b.current){const r=s.current.getBoundingClientRect(),f=b.current.getBoundingClientRect();let p=r.bottom+4,C=r.left;const c=window.innerWidth,m=window.innerHeight;C+f.width>c&&(C=c-f.width-8),p+f.height>m&&(p=r.top-f.height-4),w({top:p,left:C})}},[e]),i.useEffect(()=>{const r=p=>{b.current&&!b.current.contains(p.target)&&s.current&&!s.current.contains(p.target)&&u()},f=p=>{p.key==="Escape"&&u()};return e&&(document.addEventListener("mousedown",r),document.addEventListener("keydown",f)),()=>{document.removeEventListener("mousedown",r),document.removeEventListener("keydown",f)}},[e,u,s]),e?o.jsx("div",{ref:b,className:`rte-inline-menu ${a}`,style:{position:"fixed",top:d.top,left:d.left,zIndex:1e3,background:"white",border:"1px solid #ccc",borderRadius:"4px",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.15)",minWidth:"120px",maxWidth:"200px",pointerEvents:"auto"},children:t.map(r=>o.jsx("div",{className:"rte-inline-menu-item",onClick:()=>{g(r.value),u()},style:{padding:"8px 12px",cursor:"pointer",borderBottom:"1px solid #f0f0f0",fontSize:"14px",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},onMouseEnter:f=>{f.currentTarget.style.backgroundColor="#f5f5f5"},onMouseLeave:f=>{f.currentTarget.style.backgroundColor="transparent"},children:r.label},r.value))}):null},H=({editor:e,position:t="top",sticky:g=!1,floating:u=!1})=>{const[s,a]=i.useState(null),[b,d]=i.useState(null),[w,r]=i.useState(null),[f,p]=i.useState(null),[C,c]=i.useState(!1),m=i.useRef({}),h=i.useRef(null),x=i.useRef(null),y=i.useRef(null),v=e.pluginManager.getToolbarItems();i.useEffect(()=>{const n=()=>{if(!h.current||!x.current)return;const N=h.current.clientWidth,I=16,Q=40,B=4,Y=N-I-Q-B;let F=0,O=0;const U=x.current.children;for(let D=0;D<U.length;D++){const q=U[D].offsetWidth+B;if(F+q<=Y)F+=q,O++;else break}p(Math.max(1,O))},l=requestAnimationFrame(()=>{n()}),S=new ResizeObserver(()=>{n()});h.current&&S.observe(h.current);const L=new MutationObserver(()=>{n()});return x.current&&L.observe(x.current,{childList:!0,subtree:!0}),()=>{cancelAnimationFrame(l),S.disconnect(),L.disconnect()}},[v.length]);const k=n=>(m.current[n]||(m.current[n]=i.createRef()),m.current[n]),E=(n,l)=>{const S=h.current?.closest("[data-editora-editor]"),L=S?.querySelector(".rte-content");if(L&&L.focus(),w&&(n==="setTextAlignment"||n==="setFontFamily"||n==="setBlockType")){const I=window.getSelection();I&&(I.removeAllRanges(),I.addRange(w)),r(null)}typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(n,l),a(null);const N=S?.querySelector(".rte-content");N&&N.focus()},R=n=>{const l=window.getSelection();l&&l.rangeCount>0&&r(l.getRangeAt(0).cloneRange()),a(s===n?null:n)},T=n=>{const l=window.getSelection();l&&l.rangeCount>0&&r(l.getRangeAt(0).cloneRange()),d(b===n?null:n),a(null)},M=(n,l)=>{if(w){const S=window.getSelection();S&&(S.removeAllRanges(),S.addRange(w)),r(null)}E(n,l),d(null)},A=(n,l)=>n&&n.startsWith("<svg")&&n.endsWith("</svg>")?o.jsx("span",{dangerouslySetInnerHTML:{__html:n}}):n&&n.length===1&&/^[BIUSH]$/.test(n)?o.jsx("span",{style:{fontWeight:"bold",fontSize:"14px",lineHeight:"1"},children:n}):n||"⚪";if(u)return null;const J={...g&&{position:"sticky",top:0,zIndex:100,backgroundColor:"#fff",boxShadow:"0 2px 4px rgba(0,0,0,0.1)"},...t==="bottom"&&{order:2}},z=n=>n.map((l,S)=>o.jsx("div",{className:"rte-toolbar-item",style:{display:f!==null&&S>=f?"none":"flex"},children:l.type==="dropdown"?o.jsxs("div",{className:"rte-toolbar-dropdown",children:[o.jsxs("button",{className:"rte-toolbar-button","data-command":l.command,"data-active":"false",onClick:()=>R(l.command),children:[l.label," ▼"]}),s===l.command&&o.jsx("div",{className:"rte-toolbar-dropdown-menu",children:l.options?.map(L=>o.jsx("div",{className:"rte-toolbar-dropdown-item",onClick:()=>E(l.command,L.value),children:L.label},L.value))})]}):l.type==="inline-menu"?o.jsx("button",{ref:k(l.command),className:"rte-toolbar-button","data-command":l.command,"data-active":"false",onClick:()=>T(l.command),title:l.label,children:A(l.icon,l.command)}):l.type==="input"?o.jsx("input",{type:"text",className:`rte-toolbar-input ${l.label.toLowerCase().replace(/\s+/g,"-")}`,placeholder:l.placeholder,onChange:L=>E(l.command,L.target.value),onKeyDown:L=>{L.key==="Enter"&&E(l.command,L.target.value)},title:l.label}):l.type==="group"?o.jsx("div",{className:`rte-toolbar-group-button ${l.label.toLowerCase().replace(/\s+/g,"-")}`,title:`${l.label}`,children:o.jsx("div",{className:`rte-toolbar-group-items ${l.label.toLowerCase().replace(/\s+/g,"-")}`,children:z(l.items||[])})}):o.jsx("button",{className:"rte-toolbar-button","data-command":l.command,"data-active":"false",onClick:()=>E(l.command),title:l.label,children:A(l.icon,l.command)})},S));return o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:"rte-toolbar-wrapper",style:J,children:[o.jsxs("div",{className:"rte-toolbar",ref:h,children:[o.jsx("div",{className:"rte-toolbar-items-container",ref:x,children:z(v)}),f!==null&&f<v.length&&o.jsx("button",{ref:y,className:`rte-toolbar-more-button ${C?"active":""}`,onClick:()=>c(!C),title:"Show more options","aria-label":"More toolbar options",children:"☰"})]}),f!==null&&f<v.length&&o.jsx("div",{className:`rte-toolbar-expanded-row ${C?"show":""}`,children:v.map((n,l)=>l>=(f||0)&&o.jsx("div",{className:"rte-toolbar-item",children:n.type==="dropdown"?o.jsxs("div",{className:"rte-toolbar-dropdown",children:[o.jsxs("button",{className:"rte-toolbar-button","data-command":n.command,"data-active":"false",onClick:()=>R(n.command),children:[n.label," ▼"]}),s===n.command&&o.jsx("div",{className:"rte-toolbar-dropdown-menu",children:n.options?.map(S=>o.jsx("div",{className:"rte-toolbar-dropdown-item",onClick:()=>E(n.command,S.value),children:S.label},S.value))})]}):n.type==="inline-menu"?o.jsx("button",{ref:k(n.command),className:"rte-toolbar-button","data-command":n.command,"data-active":"false",onClick:()=>T(n.command),title:n.label,children:A(n.icon,n.command)}):n.type==="input"?o.jsx("input",{type:"text",className:"rte-toolbar-input",placeholder:n.placeholder,onChange:S=>E(n.command,S.target.value),onKeyDown:S=>{S.key==="Enter"&&E(n.command,S.target.value)},title:n.label}):o.jsx("button",{className:"rte-toolbar-button","data-command":n.command,"data-active":"false",onClick:()=>E(n.command),title:n.label,children:A(n.icon,n.command)})},l))})]}),v.map(n=>n.type==="inline-menu"?o.jsx(P,{isOpen:b===n.command,options:n.options||[],onSelect:l=>M(n.command,l),onClose:()=>d(null),anchorRef:k(n.command)},`menu-${n.command}`):null)]})};function Z(e,t){const g=i.useRef(),u=i.useRef("");return i.useEffect(()=>{if(!t?.enabled)return;const a=t.intervalMs||3e4,b=t.storageKey||"rte-autosave",d=t.provider||"localStorage",w=async()=>{const r=e();if(r!==u.current){if(u.current=r,d==="localStorage")try{localStorage.setItem(b,r),localStorage.setItem(`${b}-timestamp`,Date.now().toString()),console.log("[Autosave] Content saved to localStorage")}catch(f){console.error("[Autosave] Failed to save to localStorage:",f)}else if(d==="api"&&t.apiUrl)try{await fetch(t.apiUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:r,timestamp:Date.now()})}),console.log("[Autosave] Content saved to API")}catch(f){console.error("[Autosave] Failed to save to API:",f)}}};return g.current=setInterval(w,a),()=>{g.current&&clearInterval(g.current)}},[t?.enabled,t?.intervalMs,t?.storageKey,t?.provider,t?.apiUrl,e]),{restore:()=>{if(!t?.enabled)return null;const a=t.storageKey||"rte-autosave";if((t.provider||"localStorage")==="localStorage")try{const d=localStorage.getItem(a),w=localStorage.getItem(`${a}-timestamp`);if(d&&w)return console.log("[Autosave] Restored from localStorage, saved at:",new Date(parseInt(w))),d}catch(d){console.error("[Autosave] Failed to restore from localStorage:",d)}return null}}}const ee=["p","br","strong","em","u","s","b","i","h1","h2","h3","h4","h5","h6","ul","ol","li","a","img","video","audio","table","thead","tbody","tr","th","td","blockquote","pre","code","span","div","sup","sub","hr"],te={"*":["class","style","id","data-*"],a:["href","target","rel","title"],img:["src","alt","width","height","loading"],video:["src","controls","width","height","autoplay","loop","muted"],audio:["src","controls","autoplay","loop","muted"],table:["border","cellpadding","cellspacing"],td:["colspan","rowspan","align","valign"],th:["colspan","rowspan","align","valign"]};function K(e,t,g){if(t?.sanitize===!1)return e;const u=t?.allowedTags&&t.allowedTags.length>0?t.allowedTags:ee,s=t?.allowedAttributes||te,a=document.createElement("div");return a.innerHTML=e,$(a,u,s),a.innerHTML}function $(e,t,g){const u=Array.from(e.childNodes);for(const s of u)if(s.nodeType===Node.ELEMENT_NODE){const a=s,b=a.tagName.toLowerCase();if(!t.includes(b)){for(;a.firstChild;)e.insertBefore(a.firstChild,a);e.removeChild(a);continue}ne(a,g),$(a,t,g)}else{if(s.nodeType===Node.TEXT_NODE)continue;e.removeChild(s)}}function ne(e,t){const g=e.tagName.toLowerCase(),u=Array.from(e.attributes),s=t[g]||[],a=t["*"]||[],b=[...s,...a];for(const d of u){const w=d.name.toLowerCase();let r=!1;b.includes(w)&&(r=!0);for(const f of b)if(f.endsWith("*")){const p=f.slice(0,-1);if(w.startsWith(p)){r=!0;break}}(w.startsWith("on")||w==="javascript:"||w==="href"&&d.value.trim().toLowerCase().startsWith("javascript:")||w==="src"&&d.value.trim().toLowerCase().startsWith("javascript:"))&&(r=!1),r||e.removeAttribute(d.name)}e.hasAttribute("href")&&(e.getAttribute("href")||"").trim().toLowerCase().startsWith("javascript:")&&e.removeAttribute("href"),e.hasAttribute("src")&&(e.getAttribute("src")||"").trim().toLowerCase().startsWith("javascript:")&&e.removeAttribute("src")}function oe(e,t,g){return g?.sanitizeOnPaste===!1?e:K(e,t)}function re(e,t,g){return g?.sanitizeOnInput===!1?e:K(e,t)}const V=({editor:e,defaultValue:t,value:g,onChange:u,pasteConfig:s,contentConfig:a,securityConfig:b,performanceConfig:d,autosaveConfig:w})=>{const r=i.useRef(null),f=g!==void 0,p=i.useRef(),{restore:C}=Z(()=>r.current?.innerHTML||"",w);return i.useEffect(()=>{if(!r.current)return;const c=C(),m=c||g||t;m&&r.current.innerHTML!==m&&(r.current.innerHTML=m,c&&u&&u(c))},[]),i.useEffect(()=>{!r.current||!f||g!==r.current.innerHTML&&(r.current.innerHTML=g)},[g,f]),i.useEffect(()=>{if(!r.current)return;const c=()=>{if(!r.current||!u)return;let y=r.current.innerHTML;if(b?.sanitizeOnInput!==!1&&a?.sanitize!==!1&&(y=re(y,a,b),y!==r.current.innerHTML)){const v=window.getSelection(),k=v&&v.rangeCount>0?v.getRangeAt(0):null;if(r.current.innerHTML=y,k&&v)try{v.removeAllRanges(),v.addRange(k)}catch{}}d?.debounceInputMs?(p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{u(y)},d.debounceInputMs)):u(y)},m=y=>{y.preventDefault();let v=y.clipboardData?.getData("text/html");const k=y.clipboardData?.getData("text/plain");if(s?.clean||!s?.keepFormatting){k&&document.execCommand("insertText",!1,k);return}if(v){b?.sanitizeOnPaste!==!1&&a?.sanitize!==!1&&(v=oe(v,a,b));const E=window.getSelection();if(E&&E.rangeCount>0){const R=E.getRangeAt(0);R.deleteContents();const T=document.createElement("div");T.innerHTML=v;const M=document.createDocumentFragment();for(;T.firstChild;)M.appendChild(T.firstChild);R.insertNode(M),R.collapse(!1),E.removeAllRanges(),E.addRange(R)}}else k&&document.execCommand("insertText",!1,k)},h=y=>{const v=y.target;(v.tagName==="IMG"||v.tagName==="VIDEO")&&(v.style.resize="both",v.style.overflow="auto",v.style.display="inline-block")},x=r.current;return x.addEventListener("input",c),x.addEventListener("paste",m),x.addEventListener("click",h),x.focus(),()=>{p.current&&clearTimeout(p.current),x.removeEventListener("input",c),x.removeEventListener("paste",m),x.removeEventListener("click",h)}},[e,u,s,a,b,d]),i.useEffect(()=>{if(!r.current||typeof window>"u")return;const c=new j.KeyboardShortcutManager,m=r.current,h=x=>{c.handleKeyDown(x,(y,v)=>{typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(y,v)})};return m.addEventListener("keydown",h),()=>{m.removeEventListener("keydown",h)}},[]),o.jsx("div",{ref:r,contentEditable:!0,suppressContentEditableWarning:!0,className:"rte-content",style:{minHeight:"200px",maxHeight:"100%",padding:"16px",outline:"none",border:"1px solid #ddd",borderRadius:"0px 0px 4px 4px",fontSize:"14px",lineHeight:"1.5",overflow:"auto",flex:1,boxSizing:"border-box",wordWrap:"break-word",overflowWrap:"break-word"},children:o.jsx("p",{children:o.jsx("br",{})})})},ae=({editor:e,isEnabled:t})=>{const[g,u]=i.useState(!1),[s,a]=i.useState({top:0,left:0}),b=i.useRef(null),d=i.useRef(null),w=i.useRef(null),r=i.useRef(null);i.useEffect(()=>{if(!t){u(!1);return}r.current=b.current?.closest("[data-editora-editor]");const p=()=>{w.current&&clearTimeout(w.current);const c=window.getSelection();if(!c||c.rangeCount===0){u(!1),d.current=null;return}const m=c.getRangeAt(0),h=c.toString().trim(),x=r.current?.querySelector(".rte-content");if(!x||!x.contains(m.commonAncestorContainer)){u(!1),d.current=null;return}if(h.length>0){const y=m.getBoundingClientRect(),v=x.getBoundingClientRect(),k=300;if(y&&v){const E=y.top-50;let R=y.left+y.width/2;const T=k/2,M=v.left,A=v.right;R-T<M&&(R=M+T+10),R+T>A&&(R=A-T-10),a({top:E,left:R}),w.current=setTimeout(()=>{u(!0),d.current=m.cloneRange()},300)}}else u(!1),d.current=null},C=c=>{b.current&&!b.current.contains(c.target)&&(window.getSelection(),r.current?.querySelector(".rte-content")?.contains(c.target)||(u(!1),d.current=null))};return document.addEventListener("selectionchange",p),document.addEventListener("mousedown",C),document.addEventListener("keydown",c=>{c.key==="Escape"&&(u(!1),d.current=null)}),()=>{document.removeEventListener("selectionchange",p),document.removeEventListener("mousedown",C),w.current&&clearTimeout(w.current)}},[t]);const f=(p,C)=>{if(!d.current)return;const c=r.current?.querySelector(".rte-content");c&&c.focus(),{toggleBold:()=>document.execCommand("bold",!1),toggleItalic:()=>document.execCommand("italic",!1),toggleUnderline:()=>document.execCommand("underline",!1),toggleStrikethrough:()=>document.execCommand("strikeThrough",!1),createLink:()=>{typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand("openLinkDialog")},clearFormatting:()=>{document.execCommand("removeFormat",!1),document.execCommand("unlink",!1)},toggleCode:()=>{const h=window.getSelection();if(h&&h.rangeCount>0){const x=h.getRangeAt(0),y=document.createElement("code");x.surroundContents(y)}},setBlockType:()=>{if(C==="blockquote"){const h=window.getSelection();if(h&&h.rangeCount>0){const x=h.getRangeAt(0);(x.commonAncestorContainer.nodeType===Node.TEXT_NODE?x.commonAncestorContainer.parentElement:x.commonAncestorContainer)?.closest?.("blockquote")?document.execCommand("formatBlock",!1,"p"):document.execCommand("formatBlock",!1,"blockquote")}}else C&&document.execCommand("formatBlock",!1,C)}}[p]?.(),u(!1),d.current=null,c&&c.focus()};return!t||!g?null:o.jsxs("div",{ref:b,className:"floating-toolbar",style:{position:"fixed",top:`${s.top}px`,left:`${s.left}px`,transform:"translateX(-50%)",zIndex:1e3,background:"white",border:"1px solid #e1e5e9",borderRadius:"6px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",padding:"6px",display:"flex",gap:"4px",alignItems:"center"},children:[o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("toggleBold"),title:"Bold (Ctrl+B)",children:o.jsx("strong",{children:"B"})}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("toggleItalic"),title:"Italic (Ctrl+I)",children:o.jsx("em",{children:"I"})}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("toggleUnderline"),title:"Underline (Ctrl+U)",children:o.jsx("u",{children:"U"})}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("toggleStrikethrough"),title:"Strikethrough",children:o.jsx("s",{children:"S"})}),o.jsx("div",{className:"floating-toolbar-separator"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("clearFormatting"),title:"Clear Formatting",children:"⌫"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("createLink"),title:"Insert Link",children:"🔗"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("toggleCode"),title:"Code",children:"Code"}),o.jsx("div",{className:"floating-toolbar-separator"}),o.jsx("button",{className:"floating-toolbar-btn",onClick:()=>f("setBlockType","blockquote"),title:"Quote",children:"❝"})]})},le=({plugins:e,children:t})=>{const g=e.filter(s=>s.context?.provider);return g.length===0?o.jsx(o.Fragment,{children:t}):g.reduce((s,a)=>{const b=a.context.provider;return o.jsx(b,{children:s},a.name)},o.jsx(o.Fragment,{children:t}))},ie={toolbar:{items:[],floating:!1,sticky:!1},statusbar:{enabled:!1,position:"bottom"},menubar:{enabled:!1,items:[]},contextMenu:{enabled:!0},media:{uploadUrl:"",libraryUrl:"",maxFileSize:10*1024*1024,allowedTypes:["image/jpeg","image/png","image/gif","image/webp"],headers:{},withCredentials:!1},paste:{clean:!0,keepFormatting:!1,convertWord:!0},history:{maxSteps:100,debounceMs:300},language:{locale:"en",direction:"ltr"},spellcheck:{enabled:!1,provider:"browser",apiUrl:"",apiHeaders:{}},autosave:{enabled:!1,intervalMs:3e4,storageKey:"rte-autosave",provider:"localStorage",apiUrl:""},accessibility:{enableARIA:!0,keyboardNavigation:!0,checker:!1},performance:{debounceInputMs:100,viewportOnlyScan:!0},content:{allowedTags:[],allowedAttributes:{},sanitize:!0},security:{sanitizeOnPaste:!0,sanitizeOnInput:!0}};function _(e,t){const g={...e};for(const u in t){const s=t[u],a=g[u];s!==void 0&&(typeof s=="object"&&s!==null&&!Array.isArray(s)&&typeof a=="object"&&a!==null&&!Array.isArray(a)?g[u]=_(a,s):g[u]=s)}return g}function G(e){const t=_(ie,{toolbar:e.toolbar,statusbar:e.statusbar,menubar:e.menubar,contextMenu:e.contextMenu,media:e.media,paste:e.paste,history:e.history,language:e.language,spellcheck:e.spellcheck,autosave:e.autosave,accessibility:e.accessibility,performance:e.performance,content:e.content,security:e.security});return e.floatingToolbar!==void 0&&(t.toolbar={...t.toolbar,floating:e.floatingToolbar.enabled??t.toolbar.floating}),e.mediaConfig&&(t.media={...t.media,uploadUrl:e.mediaConfig.uploadUrl||t.media.uploadUrl,libraryUrl:e.mediaConfig.libraryUrl||t.media.libraryUrl,maxFileSize:e.mediaConfig.maxFileSize||t.media.maxFileSize,allowedTypes:e.mediaConfig.allowedTypes||t.media.allowedTypes}),{...t,id:e.id,className:e.className,value:e.value,defaultValue:e.defaultValue,onChange:e.onChange,onInit:e.onInit,onDestroy:e.onDestroy,plugins:Array.isArray(e.plugins)?e.plugins.filter(u=>typeof u!="string"):[],pluginConfig:e.pluginConfig||{}}}const W=new Map;typeof window<"u"&&(window.registerEditorCommand=(e,t)=>{W.set(e,t)},window.executeEditorCommand=(e,t)=>{const g=W.get(e);return g?g(t):(console.warn(`No handler registered for command: ${e}`),!1)});const se=e=>{const t=i.useMemo(()=>G(e),[e.id,e.className,e.value,e.defaultValue,e.plugins,e.toolbar,e.menubar,e.contextMenu,e.media,e.paste,e.history,e.language,e.spellcheck,e.autosave,e.accessibility,e.performance,e.content,e.security,e.floatingToolbar,e.mediaConfig]),g=i.useRef(null),u=i.useRef(null),s=i.useRef(e.onInit),a=i.useRef(e.onDestroy),b=i.useRef(null),d=i.useRef(null),w=i.useRef(null);i.useEffect(()=>{s.current=e.onInit,a.current=e.onDestroy});const r=i.useMemo(()=>{const c=new j.PluginManager;t.plugins.forEach(h=>{c.register(h),h.commands&&typeof window<"u"&&Object.entries(h.commands).forEach(([x,y])=>{W.set(x,y)})});const m=new j.Editor(c);return g.current=m,m},[t.plugins]);i.useEffect(()=>{const c={getHTML:()=>b.current?.querySelector(".rte-content")?.innerHTML||"",setHTML:m=>{const h=b.current?.querySelector(".rte-content");h&&(h.innerHTML=m)},execCommand:(m,h)=>{typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(m,h)},registerCommand:(m,h)=>{typeof window<"u"&&window.registerEditorCommand&&window.registerEditorCommand(m,h)},focus:()=>{b.current?.querySelector(".rte-content")?.focus()},blur:()=>{b.current?.querySelector(".rte-content")?.blur()},destroy:()=>{a.current&&a.current()},onChange:m=>()=>{},getState:()=>({plugins:t.plugins,config:t}),toolbar:{items:r.toolbar?.items||[]}};return u.current=c,s.current&&s.current(c),()=>{a.current&&a.current()}},[]),i.useEffect(()=>{if(t.statusbar.enabled&&w.current&&b.current){d.current||(d.current=new j.StatusBar({enabled:!0,position:t.statusbar.position}),d.current.create(w.current));const c=b.current.querySelector(".rte-content");if(c){const m=()=>{const h=c.textContent||"",{words:x,chars:y}=j.calculateTextStats(h),v=j.countLines(c),k=window.getSelection();let E,R;if(k&&k.rangeCount>0){const T=k.getRangeAt(0);E=j.getCursorPosition(c,T),T.collapsed||(R=j.getSelectionInfo(T,E),E=void 0)}d.current?.update({wordCount:x,charCount:y,lineCount:v,cursorPosition:E,selectionInfo:R})};return c.addEventListener("input",m),c.addEventListener("selectionchange",m),document.addEventListener("selectionchange",m),m(),()=>{c.removeEventListener("input",m),c.removeEventListener("selectionchange",m),document.removeEventListener("selectionchange",m)}}}else d.current&&(d.current.destroy(),d.current=null);return()=>{d.current&&(d.current.destroy(),d.current=null)}},[t.statusbar.enabled,t.statusbar.position]);const f=t.toolbar.floating??!1,p=t.toolbar.position||"top",C=t.toolbar.sticky??!1;return o.jsx(le,{plugins:t.plugins,children:o.jsxs("div",{ref:b,id:t.id,"data-editora-editor":!0,className:`rte-editor ${t.className||""}`,dir:t.language.direction,style:{display:"flex",flexDirection:"column",height:"100%"},children:[p!=="bottom"&&o.jsx(H,{editor:r,position:p,sticky:C,floating:f}),o.jsx(V,{editor:r,defaultValue:t.defaultValue,value:t.value,onChange:t.onChange,pasteConfig:t.paste,contentConfig:t.content,securityConfig:t.security,performanceConfig:t.performance,autosaveConfig:t.autosave}),p==="bottom"&&o.jsx(H,{editor:r,position:p,sticky:C,floating:f}),o.jsx(ae,{editor:r,isEnabled:f}),t.statusbar.enabled&&o.jsx("div",{ref:w,className:"editora-statusbar-container",style:{order:t.statusbar.position==="top"?-1:1}})]})})},X=e=>o.jsx(se,{...e});function ce(e={}){const t=i.useRef(null),g=i.useRef(e.onCommand);return i.useEffect(()=>{g.current=e.onCommand}),i.useEffect(()=>{if(typeof window>"u"||e.enabled===!1)return;const u=new j.KeyboardShortcutManager(e);t.current=u;const s=b=>u.handleKeyDown(b,(w,r)=>{g.current&&g.current(w,r),typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(w,r)}),a=e.editorElement||document;return a&&a.addEventListener("keydown",s),()=>{a&&a.removeEventListener("keydown",s)}},[e.editorElement,e.enabled,e.shortcuts,e.customShortcuts]),{getShortcuts:()=>t.current?.getAllShortcuts()||[],getShortcutForCommand:u=>t.current?.getShortcutForCommand(u),getShortcutsHelp:()=>t.current?.getShortcutsHelp()||"",enable:()=>t.current?.enable(),disable:()=>t.current?.disable(),isEnabled:()=>t.current?.isEnabled()||!1}}exports.EditorContent=V;exports.EditoraEditor=X;exports.InlineMenu=P;exports.RichTextEditor=X;exports.Toolbar=H;exports.mergeConfig=G;exports.useKeyboardShortcuts=ce; |
+381
-336
@@ -1,45 +0,45 @@ | ||
| import { jsx as l, jsxs as N, Fragment as F } from "react/jsx-runtime"; | ||
| import ee, { useRef as E, useState as R, useEffect as T, useMemo as j } from "react"; | ||
| import { KeyboardShortcutManager as _, PluginManager as te, Editor as ne } from "@editora/core"; | ||
| const oe = ({ | ||
| import { jsx as l, jsxs as R, Fragment as B } from "react/jsx-runtime"; | ||
| import ee, { useRef as E, useState as N, useEffect as A, useMemo as j } from "react"; | ||
| import { KeyboardShortcutManager as _, PluginManager as te, Editor as ne, StatusBar as oe, calculateTextStats as re, countLines as ae, getCursorPosition as le, getSelectionInfo as ie } from "@editora/core"; | ||
| const ce = ({ | ||
| isOpen: e, | ||
| options: t, | ||
| onSelect: d, | ||
| onClose: c, | ||
| onSelect: m, | ||
| onClose: s, | ||
| anchorRef: i, | ||
| className: r = "" | ||
| }) => { | ||
| const m = E(null), [f, g] = R({ top: 0, left: 0 }); | ||
| return T(() => { | ||
| const g = E(null), [d, h] = N({ top: 0, left: 0 }); | ||
| return A(() => { | ||
| if (e && i.current) { | ||
| const o = i.current.getBoundingClientRect(), s = 120, h = t.length * 36; | ||
| let b = o.bottom + 4, u = o.left; | ||
| const v = window.innerWidth, p = window.innerHeight; | ||
| u + s > v && (u = v - s - 8), b + h > p && (b = o.top - h - 4), g({ top: b, left: u }); | ||
| const o = i.current.getBoundingClientRect(), u = 120, v = t.length * 36; | ||
| let C = o.bottom + 4, c = o.left; | ||
| const f = window.innerWidth, b = window.innerHeight; | ||
| c + u > f && (c = f - u - 8), C + v > b && (C = o.top - v - 4), h({ top: C, left: c }); | ||
| } | ||
| }, [e, i, t.length]), T(() => { | ||
| if (e && i.current && m.current) { | ||
| const o = i.current.getBoundingClientRect(), s = m.current.getBoundingClientRect(); | ||
| let h = o.bottom + 4, b = o.left; | ||
| const u = window.innerWidth, v = window.innerHeight; | ||
| b + s.width > u && (b = u - s.width - 8), h + s.height > v && (h = o.top - s.height - 4), g({ top: h, left: b }); | ||
| }, [e, i, t.length]), A(() => { | ||
| if (e && i.current && g.current) { | ||
| const o = i.current.getBoundingClientRect(), u = g.current.getBoundingClientRect(); | ||
| let v = o.bottom + 4, C = o.left; | ||
| const c = window.innerWidth, f = window.innerHeight; | ||
| C + u.width > c && (C = c - u.width - 8), v + u.height > f && (v = o.top - u.height - 4), h({ top: v, left: C }); | ||
| } | ||
| }, [e]), T(() => { | ||
| const o = (h) => { | ||
| m.current && !m.current.contains(h.target) && i.current && !i.current.contains(h.target) && c(); | ||
| }, s = (h) => { | ||
| h.key === "Escape" && c(); | ||
| }, [e]), A(() => { | ||
| const o = (v) => { | ||
| g.current && !g.current.contains(v.target) && i.current && !i.current.contains(v.target) && s(); | ||
| }, u = (v) => { | ||
| v.key === "Escape" && s(); | ||
| }; | ||
| return e && (document.addEventListener("mousedown", o), document.addEventListener("keydown", s)), () => { | ||
| document.removeEventListener("mousedown", o), document.removeEventListener("keydown", s); | ||
| return e && (document.addEventListener("mousedown", o), document.addEventListener("keydown", u)), () => { | ||
| document.removeEventListener("mousedown", o), document.removeEventListener("keydown", u); | ||
| }; | ||
| }, [e, c, i]), e ? /* @__PURE__ */ l( | ||
| }, [e, s, i]), e ? /* @__PURE__ */ l( | ||
| "div", | ||
| { | ||
| ref: m, | ||
| ref: g, | ||
| className: `rte-inline-menu ${r}`, | ||
| style: { | ||
| position: "fixed", | ||
| top: f.top, | ||
| left: f.left, | ||
| top: d.top, | ||
| left: d.left, | ||
| zIndex: 1e3, | ||
@@ -59,3 +59,3 @@ background: "white", | ||
| onClick: () => { | ||
| d(o.value), c(); | ||
| m(o.value), s(); | ||
| }, | ||
@@ -71,7 +71,7 @@ style: { | ||
| }, | ||
| onMouseEnter: (s) => { | ||
| s.currentTarget.style.backgroundColor = "#f5f5f5"; | ||
| onMouseEnter: (u) => { | ||
| u.currentTarget.style.backgroundColor = "#f5f5f5"; | ||
| }, | ||
| onMouseLeave: (s) => { | ||
| s.currentTarget.style.backgroundColor = "transparent"; | ||
| onMouseLeave: (u) => { | ||
| u.currentTarget.style.backgroundColor = "transparent"; | ||
| }, | ||
@@ -87,12 +87,12 @@ children: o.label | ||
| position: t = "top", | ||
| sticky: d = !1, | ||
| floating: c = !1 | ||
| sticky: m = !1, | ||
| floating: s = !1 | ||
| }) => { | ||
| const [i, r] = R(null), [m, f] = R(null), [g, o] = R(null), [s, h] = R(null), [b, u] = R(!1), v = E({}), p = E(null), y = E(null), C = E(null), w = e.pluginManager.getToolbarItems(); | ||
| T(() => { | ||
| const [i, r] = N(null), [g, d] = N(null), [h, o] = N(null), [u, v] = N(null), [C, c] = N(!1), f = E({}), b = E(null), p = E(null), y = E(null), w = e.pluginManager.getToolbarItems(); | ||
| A(() => { | ||
| const n = () => { | ||
| if (!p.current || !y.current) return; | ||
| const W = p.current.clientWidth, H = 16, Y = 40, U = 4, Z = W - H - Y - U; | ||
| if (!b.current || !p.current) return; | ||
| const W = b.current.clientWidth, H = 16, Y = 40, U = 4, Z = W - H - Y - U; | ||
| let q = 0, P = 0; | ||
| const $ = y.current.children; | ||
| const $ = p.current.children; | ||
| for (let z = 0; z < $.length; z++) { | ||
@@ -105,45 +105,45 @@ const K = $[z].offsetWidth + U; | ||
| } | ||
| h(Math.max(1, P)); | ||
| v(Math.max(1, P)); | ||
| }, a = requestAnimationFrame(() => { | ||
| n(); | ||
| }), x = new ResizeObserver(() => { | ||
| }), k = new ResizeObserver(() => { | ||
| n(); | ||
| }); | ||
| p.current && x.observe(p.current); | ||
| const S = new MutationObserver(() => { | ||
| b.current && k.observe(b.current); | ||
| const M = new MutationObserver(() => { | ||
| n(); | ||
| }); | ||
| return y.current && S.observe(y.current, { | ||
| return p.current && M.observe(p.current, { | ||
| childList: !0, | ||
| subtree: !0 | ||
| }), () => { | ||
| cancelAnimationFrame(a), x.disconnect(), S.disconnect(); | ||
| cancelAnimationFrame(a), k.disconnect(), M.disconnect(); | ||
| }; | ||
| }, [w.length]); | ||
| const L = (n) => (v.current[n] || (v.current[n] = ee.createRef()), v.current[n]), k = (n, a) => { | ||
| const x = p.current?.closest("[data-editora-editor]"), S = x?.querySelector(".rte-content"); | ||
| if (S && S.focus(), g && (n === "setTextAlignment" || n === "setFontFamily" || n === "setBlockType")) { | ||
| const S = (n) => (f.current[n] || (f.current[n] = ee.createRef()), f.current[n]), x = (n, a) => { | ||
| const k = b.current?.closest("[data-editora-editor]"), M = k?.querySelector(".rte-content"); | ||
| if (M && M.focus(), h && (n === "setTextAlignment" || n === "setFontFamily" || n === "setBlockType")) { | ||
| const H = window.getSelection(); | ||
| H && (H.removeAllRanges(), H.addRange(g)), o(null); | ||
| H && (H.removeAllRanges(), H.addRange(h)), o(null); | ||
| } | ||
| typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(n, a), r(null); | ||
| const W = x?.querySelector(".rte-content"); | ||
| const W = k?.querySelector(".rte-content"); | ||
| W && W.focus(); | ||
| }, A = (n) => { | ||
| }, T = (n) => { | ||
| const a = window.getSelection(); | ||
| a && a.rangeCount > 0 && o(a.getRangeAt(0).cloneRange()), r(i === n ? null : n); | ||
| }, M = (n) => { | ||
| }, L = (n) => { | ||
| const a = window.getSelection(); | ||
| a && a.rangeCount > 0 && o(a.getRangeAt(0).cloneRange()), f(m === n ? null : n), r(null); | ||
| a && a.rangeCount > 0 && o(a.getRangeAt(0).cloneRange()), d(g === n ? null : n), r(null); | ||
| }, I = (n, a) => { | ||
| if (g) { | ||
| const x = window.getSelection(); | ||
| x && (x.removeAllRanges(), x.addRange(g)), o(null); | ||
| if (h) { | ||
| const k = window.getSelection(); | ||
| k && (k.removeAllRanges(), k.addRange(h)), o(null); | ||
| } | ||
| k(n, a), f(null); | ||
| x(n, a), d(null); | ||
| }, D = (n, a) => n && n.startsWith("<svg") && n.endsWith("</svg>") ? /* @__PURE__ */ l("span", { dangerouslySetInnerHTML: { __html: n } }) : n && n.length === 1 && /^[BIUSH]$/.test(n) ? /* @__PURE__ */ l("span", { style: { fontWeight: "bold", fontSize: "14px", lineHeight: "1" }, children: n }) : n || "⚪"; | ||
| if (c) | ||
| if (s) | ||
| return null; | ||
| const Q = { | ||
| ...d && { | ||
| ...m && { | ||
| position: "sticky", | ||
@@ -159,3 +159,3 @@ top: 0, | ||
| } | ||
| }, O = (n) => n.map((a, x) => /* @__PURE__ */ l( | ||
| }, O = (n) => n.map((a, k) => /* @__PURE__ */ l( | ||
| "div", | ||
@@ -165,6 +165,6 @@ { | ||
| style: { | ||
| display: s !== null && x >= s ? "none" : "flex" | ||
| display: u !== null && k >= u ? "none" : "flex" | ||
| }, | ||
| children: a.type === "dropdown" ? /* @__PURE__ */ N("div", { className: "rte-toolbar-dropdown", children: [ | ||
| /* @__PURE__ */ N( | ||
| children: a.type === "dropdown" ? /* @__PURE__ */ R("div", { className: "rte-toolbar-dropdown", children: [ | ||
| /* @__PURE__ */ R( | ||
| "button", | ||
@@ -175,3 +175,3 @@ { | ||
| "data-active": "false", | ||
| onClick: () => A(a.command), | ||
| onClick: () => T(a.command), | ||
| children: [ | ||
@@ -183,10 +183,10 @@ a.label, | ||
| ), | ||
| i === a.command && /* @__PURE__ */ l("div", { className: "rte-toolbar-dropdown-menu", children: a.options?.map((S) => /* @__PURE__ */ l( | ||
| i === a.command && /* @__PURE__ */ l("div", { className: "rte-toolbar-dropdown-menu", children: a.options?.map((M) => /* @__PURE__ */ l( | ||
| "div", | ||
| { | ||
| className: "rte-toolbar-dropdown-item", | ||
| onClick: () => k(a.command, S.value), | ||
| children: S.label | ||
| onClick: () => x(a.command, M.value), | ||
| children: M.label | ||
| }, | ||
| S.value | ||
| M.value | ||
| )) }) | ||
@@ -196,7 +196,7 @@ ] }) : a.type === "inline-menu" ? /* @__PURE__ */ l( | ||
| { | ||
| ref: L(a.command), | ||
| ref: S(a.command), | ||
| className: "rte-toolbar-button", | ||
| "data-command": a.command, | ||
| "data-active": "false", | ||
| onClick: () => M(a.command), | ||
| onClick: () => L(a.command), | ||
| title: a.label, | ||
@@ -211,7 +211,7 @@ children: D(a.icon, a.command) | ||
| placeholder: a.placeholder, | ||
| onChange: (S) => k(a.command, S.target.value), | ||
| onKeyDown: (S) => { | ||
| S.key === "Enter" && k( | ||
| onChange: (M) => x(a.command, M.target.value), | ||
| onKeyDown: (M) => { | ||
| M.key === "Enter" && x( | ||
| a.command, | ||
| S.target.value | ||
| M.target.value | ||
| ); | ||
@@ -240,3 +240,3 @@ }, | ||
| "data-active": "false", | ||
| onClick: () => k(a.command), | ||
| onClick: () => x(a.command), | ||
| title: a.label, | ||
@@ -247,14 +247,14 @@ children: D(a.icon, a.command) | ||
| }, | ||
| x | ||
| k | ||
| )); | ||
| return /* @__PURE__ */ N(F, { children: [ | ||
| /* @__PURE__ */ N("div", { className: "rte-toolbar-wrapper", style: Q, children: [ | ||
| /* @__PURE__ */ N("div", { className: "rte-toolbar", ref: p, children: [ | ||
| /* @__PURE__ */ l("div", { className: "rte-toolbar-items-container", ref: y, children: O(w) }), | ||
| s !== null && s < w.length && /* @__PURE__ */ l( | ||
| return /* @__PURE__ */ R(B, { children: [ | ||
| /* @__PURE__ */ R("div", { className: "rte-toolbar-wrapper", style: Q, children: [ | ||
| /* @__PURE__ */ R("div", { className: "rte-toolbar", ref: b, children: [ | ||
| /* @__PURE__ */ l("div", { className: "rte-toolbar-items-container", ref: p, children: O(w) }), | ||
| u !== null && u < w.length && /* @__PURE__ */ l( | ||
| "button", | ||
| { | ||
| ref: C, | ||
| className: `rte-toolbar-more-button ${b ? "active" : ""}`, | ||
| onClick: () => u(!b), | ||
| ref: y, | ||
| className: `rte-toolbar-more-button ${C ? "active" : ""}`, | ||
| onClick: () => c(!C), | ||
| title: "Show more options", | ||
@@ -266,9 +266,9 @@ "aria-label": "More toolbar options", | ||
| ] }), | ||
| s !== null && s < w.length && /* @__PURE__ */ l( | ||
| u !== null && u < w.length && /* @__PURE__ */ l( | ||
| "div", | ||
| { | ||
| className: `rte-toolbar-expanded-row ${b ? "show" : ""}`, | ||
| className: `rte-toolbar-expanded-row ${C ? "show" : ""}`, | ||
| children: w.map( | ||
| (n, a) => a >= (s || 0) && /* @__PURE__ */ l("div", { className: "rte-toolbar-item", children: n.type === "dropdown" ? /* @__PURE__ */ N("div", { className: "rte-toolbar-dropdown", children: [ | ||
| /* @__PURE__ */ N( | ||
| (n, a) => a >= (u || 0) && /* @__PURE__ */ l("div", { className: "rte-toolbar-item", children: n.type === "dropdown" ? /* @__PURE__ */ R("div", { className: "rte-toolbar-dropdown", children: [ | ||
| /* @__PURE__ */ R( | ||
| "button", | ||
@@ -279,3 +279,3 @@ { | ||
| "data-active": "false", | ||
| onClick: () => A(n.command), | ||
| onClick: () => T(n.command), | ||
| children: [ | ||
@@ -287,10 +287,10 @@ n.label, | ||
| ), | ||
| i === n.command && /* @__PURE__ */ l("div", { className: "rte-toolbar-dropdown-menu", children: n.options?.map((x) => /* @__PURE__ */ l( | ||
| i === n.command && /* @__PURE__ */ l("div", { className: "rte-toolbar-dropdown-menu", children: n.options?.map((k) => /* @__PURE__ */ l( | ||
| "div", | ||
| { | ||
| className: "rte-toolbar-dropdown-item", | ||
| onClick: () => k(n.command, x.value), | ||
| children: x.label | ||
| onClick: () => x(n.command, k.value), | ||
| children: k.label | ||
| }, | ||
| x.value | ||
| k.value | ||
| )) }) | ||
@@ -300,7 +300,7 @@ ] }) : n.type === "inline-menu" ? /* @__PURE__ */ l( | ||
| { | ||
| ref: L(n.command), | ||
| ref: S(n.command), | ||
| className: "rte-toolbar-button", | ||
| "data-command": n.command, | ||
| "data-active": "false", | ||
| onClick: () => M(n.command), | ||
| onClick: () => L(n.command), | ||
| title: n.label, | ||
@@ -315,7 +315,7 @@ children: D(n.icon, n.command) | ||
| placeholder: n.placeholder, | ||
| onChange: (x) => k(n.command, x.target.value), | ||
| onKeyDown: (x) => { | ||
| x.key === "Enter" && k( | ||
| onChange: (k) => x(n.command, k.target.value), | ||
| onKeyDown: (k) => { | ||
| k.key === "Enter" && x( | ||
| n.command, | ||
| x.target.value | ||
| k.target.value | ||
| ); | ||
@@ -331,3 +331,3 @@ }, | ||
| "data-active": "false", | ||
| onClick: () => k(n.command), | ||
| onClick: () => x(n.command), | ||
| title: n.label, | ||
@@ -342,9 +342,9 @@ children: D(n.icon, n.command) | ||
| w.map((n) => n.type === "inline-menu" ? /* @__PURE__ */ l( | ||
| oe, | ||
| ce, | ||
| { | ||
| isOpen: m === n.command, | ||
| isOpen: g === n.command, | ||
| options: n.options || [], | ||
| onSelect: (a) => I(n.command, a), | ||
| onClose: () => f(null), | ||
| anchorRef: L(n.command) | ||
| onClose: () => d(null), | ||
| anchorRef: S(n.command) | ||
| }, | ||
@@ -355,16 +355,16 @@ `menu-${n.command}` | ||
| }; | ||
| function re(e, t) { | ||
| const d = E(), c = E(""); | ||
| return T(() => { | ||
| function se(e, t) { | ||
| const m = E(), s = E(""); | ||
| return A(() => { | ||
| if (!t?.enabled) return; | ||
| const r = t.intervalMs || 3e4, m = t.storageKey || "rte-autosave", f = t.provider || "localStorage", g = async () => { | ||
| const r = t.intervalMs || 3e4, g = t.storageKey || "rte-autosave", d = t.provider || "localStorage", h = async () => { | ||
| const o = e(); | ||
| if (o !== c.current) { | ||
| if (c.current = o, f === "localStorage") | ||
| if (o !== s.current) { | ||
| if (s.current = o, d === "localStorage") | ||
| try { | ||
| localStorage.setItem(m, o), localStorage.setItem(`${m}-timestamp`, Date.now().toString()), console.log("[Autosave] Content saved to localStorage"); | ||
| } catch (s) { | ||
| console.error("[Autosave] Failed to save to localStorage:", s); | ||
| localStorage.setItem(g, o), localStorage.setItem(`${g}-timestamp`, Date.now().toString()), console.log("[Autosave] Content saved to localStorage"); | ||
| } catch (u) { | ||
| console.error("[Autosave] Failed to save to localStorage:", u); | ||
| } | ||
| else if (f === "api" && t.apiUrl) | ||
| else if (d === "api" && t.apiUrl) | ||
| try { | ||
@@ -378,9 +378,9 @@ await fetch(t.apiUrl, { | ||
| }), console.log("[Autosave] Content saved to API"); | ||
| } catch (s) { | ||
| console.error("[Autosave] Failed to save to API:", s); | ||
| } catch (u) { | ||
| console.error("[Autosave] Failed to save to API:", u); | ||
| } | ||
| } | ||
| }; | ||
| return d.current = setInterval(g, r), () => { | ||
| d.current && clearInterval(d.current); | ||
| return m.current = setInterval(h, r), () => { | ||
| m.current && clearInterval(m.current); | ||
| }; | ||
@@ -392,7 +392,7 @@ }, [t?.enabled, t?.intervalMs, t?.storageKey, t?.provider, t?.apiUrl, e]), { restore: () => { | ||
| try { | ||
| const f = localStorage.getItem(r), g = localStorage.getItem(`${r}-timestamp`); | ||
| if (f && g) | ||
| return console.log("[Autosave] Restored from localStorage, saved at:", new Date(parseInt(g))), f; | ||
| } catch (f) { | ||
| console.error("[Autosave] Failed to restore from localStorage:", f); | ||
| const d = localStorage.getItem(r), h = localStorage.getItem(`${r}-timestamp`); | ||
| if (d && h) | ||
| return console.log("[Autosave] Restored from localStorage, saved at:", new Date(parseInt(h))), d; | ||
| } catch (d) { | ||
| console.error("[Autosave] Failed to restore from localStorage:", d); | ||
| } | ||
@@ -402,3 +402,3 @@ return null; | ||
| } | ||
| const ae = [ | ||
| const de = [ | ||
| "p", | ||
@@ -439,3 +439,3 @@ "br", | ||
| "hr" | ||
| ], le = { | ||
| ], ue = { | ||
| "*": ["class", "style", "id", "data-*"], | ||
@@ -450,14 +450,14 @@ a: ["href", "target", "rel", "title"], | ||
| }; | ||
| function G(e, t, d) { | ||
| function G(e, t, m) { | ||
| if (t?.sanitize === !1) | ||
| return e; | ||
| const c = t?.allowedTags && t.allowedTags.length > 0 ? t.allowedTags : ae, i = t?.allowedAttributes || le, r = document.createElement("div"); | ||
| return r.innerHTML = e, X(r, c, i), r.innerHTML; | ||
| const s = t?.allowedTags && t.allowedTags.length > 0 ? t.allowedTags : de, i = t?.allowedAttributes || ue, r = document.createElement("div"); | ||
| return r.innerHTML = e, X(r, s, i), r.innerHTML; | ||
| } | ||
| function X(e, t, d) { | ||
| const c = Array.from(e.childNodes); | ||
| for (const i of c) | ||
| function X(e, t, m) { | ||
| const s = Array.from(e.childNodes); | ||
| for (const i of s) | ||
| if (i.nodeType === Node.ELEMENT_NODE) { | ||
| const r = i, m = r.tagName.toLowerCase(); | ||
| if (!t.includes(m)) { | ||
| const r = i, g = r.tagName.toLowerCase(); | ||
| if (!t.includes(g)) { | ||
| for (; r.firstChild; ) | ||
@@ -468,3 +468,3 @@ e.insertBefore(r.firstChild, r); | ||
| } | ||
| ie(r, d), X(r, t, d); | ||
| fe(r, m), X(r, t, m); | ||
| } else { | ||
@@ -476,12 +476,12 @@ if (i.nodeType === Node.TEXT_NODE) | ||
| } | ||
| function ie(e, t) { | ||
| const d = e.tagName.toLowerCase(), c = Array.from(e.attributes), i = t[d] || [], r = t["*"] || [], m = [...i, ...r]; | ||
| for (const f of c) { | ||
| const g = f.name.toLowerCase(); | ||
| function fe(e, t) { | ||
| const m = e.tagName.toLowerCase(), s = Array.from(e.attributes), i = t[m] || [], r = t["*"] || [], g = [...i, ...r]; | ||
| for (const d of s) { | ||
| const h = d.name.toLowerCase(); | ||
| let o = !1; | ||
| m.includes(g) && (o = !0); | ||
| for (const s of m) | ||
| if (s.endsWith("*")) { | ||
| const h = s.slice(0, -1); | ||
| if (g.startsWith(h)) { | ||
| g.includes(h) && (o = !0); | ||
| for (const u of g) | ||
| if (u.endsWith("*")) { | ||
| const v = u.slice(0, -1); | ||
| if (h.startsWith(v)) { | ||
| o = !0; | ||
@@ -491,88 +491,88 @@ break; | ||
| } | ||
| (g.startsWith("on") || // Event handlers | ||
| g === "javascript:" || g === "href" && f.value.trim().toLowerCase().startsWith("javascript:") || g === "src" && f.value.trim().toLowerCase().startsWith("javascript:")) && (o = !1), o || e.removeAttribute(f.name); | ||
| (h.startsWith("on") || // Event handlers | ||
| h === "javascript:" || h === "href" && d.value.trim().toLowerCase().startsWith("javascript:") || h === "src" && d.value.trim().toLowerCase().startsWith("javascript:")) && (o = !1), o || e.removeAttribute(d.name); | ||
| } | ||
| e.hasAttribute("href") && (e.getAttribute("href") || "").trim().toLowerCase().startsWith("javascript:") && e.removeAttribute("href"), e.hasAttribute("src") && (e.getAttribute("src") || "").trim().toLowerCase().startsWith("javascript:") && e.removeAttribute("src"); | ||
| } | ||
| function ce(e, t, d) { | ||
| return d?.sanitizeOnPaste === !1 ? e : G(e, t); | ||
| function me(e, t, m) { | ||
| return m?.sanitizeOnPaste === !1 ? e : G(e, t); | ||
| } | ||
| function se(e, t, d) { | ||
| return d?.sanitizeOnInput === !1 ? e : G(e, t); | ||
| function ge(e, t, m) { | ||
| return m?.sanitizeOnInput === !1 ? e : G(e, t); | ||
| } | ||
| const de = ({ | ||
| const be = ({ | ||
| editor: e, | ||
| defaultValue: t, | ||
| value: d, | ||
| onChange: c, | ||
| value: m, | ||
| onChange: s, | ||
| pasteConfig: i, | ||
| contentConfig: r, | ||
| securityConfig: m, | ||
| performanceConfig: f, | ||
| autosaveConfig: g | ||
| securityConfig: g, | ||
| performanceConfig: d, | ||
| autosaveConfig: h | ||
| }) => { | ||
| const o = E(null), s = d !== void 0, h = E(), { restore: b } = re( | ||
| const o = E(null), u = m !== void 0, v = E(), { restore: C } = se( | ||
| () => o.current?.innerHTML || "", | ||
| g | ||
| h | ||
| ); | ||
| return T(() => { | ||
| return A(() => { | ||
| if (!o.current) return; | ||
| const u = b(), v = u || d || t; | ||
| v && o.current.innerHTML !== v && (o.current.innerHTML = v, u && c && c(u)); | ||
| }, []), T(() => { | ||
| !o.current || !s || d !== o.current.innerHTML && (o.current.innerHTML = d); | ||
| }, [d, s]), T(() => { | ||
| const c = C(), f = c || m || t; | ||
| f && o.current.innerHTML !== f && (o.current.innerHTML = f, c && s && s(c)); | ||
| }, []), A(() => { | ||
| !o.current || !u || m !== o.current.innerHTML && (o.current.innerHTML = m); | ||
| }, [m, u]), A(() => { | ||
| if (!o.current) return; | ||
| const u = () => { | ||
| if (!o.current || !c) return; | ||
| let C = o.current.innerHTML; | ||
| if (m?.sanitizeOnInput !== !1 && r?.sanitize !== !1 && (C = se(C, r, m), C !== o.current.innerHTML)) { | ||
| const w = window.getSelection(), L = w && w.rangeCount > 0 ? w.getRangeAt(0) : null; | ||
| if (o.current.innerHTML = C, L && w) | ||
| const c = () => { | ||
| if (!o.current || !s) return; | ||
| let y = o.current.innerHTML; | ||
| if (g?.sanitizeOnInput !== !1 && r?.sanitize !== !1 && (y = ge(y, r, g), y !== o.current.innerHTML)) { | ||
| const w = window.getSelection(), S = w && w.rangeCount > 0 ? w.getRangeAt(0) : null; | ||
| if (o.current.innerHTML = y, S && w) | ||
| try { | ||
| w.removeAllRanges(), w.addRange(L); | ||
| w.removeAllRanges(), w.addRange(S); | ||
| } catch { | ||
| } | ||
| } | ||
| f?.debounceInputMs ? (h.current && clearTimeout(h.current), h.current = setTimeout(() => { | ||
| c(C); | ||
| }, f.debounceInputMs)) : c(C); | ||
| }, v = (C) => { | ||
| C.preventDefault(); | ||
| let w = C.clipboardData?.getData("text/html"); | ||
| const L = C.clipboardData?.getData("text/plain"); | ||
| d?.debounceInputMs ? (v.current && clearTimeout(v.current), v.current = setTimeout(() => { | ||
| s(y); | ||
| }, d.debounceInputMs)) : s(y); | ||
| }, f = (y) => { | ||
| y.preventDefault(); | ||
| let w = y.clipboardData?.getData("text/html"); | ||
| const S = y.clipboardData?.getData("text/plain"); | ||
| if (i?.clean || !i?.keepFormatting) { | ||
| L && document.execCommand("insertText", !1, L); | ||
| S && document.execCommand("insertText", !1, S); | ||
| return; | ||
| } | ||
| if (w) { | ||
| m?.sanitizeOnPaste !== !1 && r?.sanitize !== !1 && (w = ce(w, r, m)); | ||
| const k = window.getSelection(); | ||
| if (k && k.rangeCount > 0) { | ||
| const A = k.getRangeAt(0); | ||
| A.deleteContents(); | ||
| const M = document.createElement("div"); | ||
| M.innerHTML = w; | ||
| g?.sanitizeOnPaste !== !1 && r?.sanitize !== !1 && (w = me(w, r, g)); | ||
| const x = window.getSelection(); | ||
| if (x && x.rangeCount > 0) { | ||
| const T = x.getRangeAt(0); | ||
| T.deleteContents(); | ||
| const L = document.createElement("div"); | ||
| L.innerHTML = w; | ||
| const I = document.createDocumentFragment(); | ||
| for (; M.firstChild; ) | ||
| I.appendChild(M.firstChild); | ||
| A.insertNode(I), A.collapse(!1), k.removeAllRanges(), k.addRange(A); | ||
| for (; L.firstChild; ) | ||
| I.appendChild(L.firstChild); | ||
| T.insertNode(I), T.collapse(!1), x.removeAllRanges(), x.addRange(T); | ||
| } | ||
| } else L && document.execCommand("insertText", !1, L); | ||
| }, p = (C) => { | ||
| const w = C.target; | ||
| } else S && document.execCommand("insertText", !1, S); | ||
| }, b = (y) => { | ||
| const w = y.target; | ||
| (w.tagName === "IMG" || w.tagName === "VIDEO") && (w.style.resize = "both", w.style.overflow = "auto", w.style.display = "inline-block"); | ||
| }, y = o.current; | ||
| return y.addEventListener("input", u), y.addEventListener("paste", v), y.addEventListener("click", p), y.focus(), () => { | ||
| h.current && clearTimeout(h.current), y.removeEventListener("input", u), y.removeEventListener("paste", v), y.removeEventListener("click", p); | ||
| }, p = o.current; | ||
| return p.addEventListener("input", c), p.addEventListener("paste", f), p.addEventListener("click", b), p.focus(), () => { | ||
| v.current && clearTimeout(v.current), p.removeEventListener("input", c), p.removeEventListener("paste", f), p.removeEventListener("click", b); | ||
| }; | ||
| }, [e, c, i, r, m, f]), T(() => { | ||
| }, [e, s, i, r, g, d]), A(() => { | ||
| if (!o.current || typeof window > "u") return; | ||
| const u = new _(), v = o.current, p = (y) => { | ||
| u.handleKeyDown(y, (C, w) => { | ||
| typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(C, w); | ||
| const c = new _(), f = o.current, b = (p) => { | ||
| c.handleKeyDown(p, (y, w) => { | ||
| typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(y, w); | ||
| }); | ||
| }; | ||
| return v.addEventListener("keydown", p), () => { | ||
| v.removeEventListener("keydown", p); | ||
| return f.addEventListener("keydown", b), () => { | ||
| f.removeEventListener("keydown", b); | ||
| }; | ||
@@ -592,3 +592,3 @@ }, []), /* @__PURE__ */ l( | ||
| border: "1px solid #ddd", | ||
| borderRadius: "4px", | ||
| borderRadius: "0px 0px 4px 4px", | ||
| fontSize: "14px", | ||
@@ -605,50 +605,50 @@ lineHeight: "1.5", | ||
| ); | ||
| }, ue = ({ | ||
| }, he = ({ | ||
| editor: e, | ||
| isEnabled: t | ||
| }) => { | ||
| const [d, c] = R(!1), [i, r] = R({ top: 0, left: 0 }), m = E(null), f = E(null), g = E(null), o = E(null); | ||
| T(() => { | ||
| const [m, s] = N(!1), [i, r] = N({ top: 0, left: 0 }), g = E(null), d = E(null), h = E(null), o = E(null); | ||
| A(() => { | ||
| if (!t) { | ||
| c(!1); | ||
| s(!1); | ||
| return; | ||
| } | ||
| o.current = m.current?.closest("[data-editora-editor]"); | ||
| const h = () => { | ||
| g.current && clearTimeout(g.current); | ||
| const u = window.getSelection(); | ||
| if (!u || u.rangeCount === 0) { | ||
| c(!1), f.current = null; | ||
| o.current = g.current?.closest("[data-editora-editor]"); | ||
| const v = () => { | ||
| h.current && clearTimeout(h.current); | ||
| const c = window.getSelection(); | ||
| if (!c || c.rangeCount === 0) { | ||
| s(!1), d.current = null; | ||
| return; | ||
| } | ||
| const v = u.getRangeAt(0), p = u.toString().trim(), y = o.current?.querySelector(".rte-content"); | ||
| if (!y || !y.contains(v.commonAncestorContainer)) { | ||
| c(!1), f.current = null; | ||
| const f = c.getRangeAt(0), b = c.toString().trim(), p = o.current?.querySelector(".rte-content"); | ||
| if (!p || !p.contains(f.commonAncestorContainer)) { | ||
| s(!1), d.current = null; | ||
| return; | ||
| } | ||
| if (p.length > 0) { | ||
| const C = v.getBoundingClientRect(), w = y.getBoundingClientRect(), L = 300; | ||
| if (C && w) { | ||
| const k = C.top - 50; | ||
| let A = C.left + C.width / 2; | ||
| const M = L / 2, I = w.left, D = w.right; | ||
| A - M < I && (A = I + M + 10), A + M > D && (A = D - M - 10), r({ top: k, left: A }), g.current = setTimeout(() => { | ||
| c(!0), f.current = v.cloneRange(); | ||
| if (b.length > 0) { | ||
| const y = f.getBoundingClientRect(), w = p.getBoundingClientRect(), S = 300; | ||
| if (y && w) { | ||
| const x = y.top - 50; | ||
| let T = y.left + y.width / 2; | ||
| const L = S / 2, I = w.left, D = w.right; | ||
| T - L < I && (T = I + L + 10), T + L > D && (T = D - L - 10), r({ top: x, left: T }), h.current = setTimeout(() => { | ||
| s(!0), d.current = f.cloneRange(); | ||
| }, 300); | ||
| } | ||
| } else | ||
| c(!1), f.current = null; | ||
| }, b = (u) => { | ||
| m.current && !m.current.contains(u.target) && (window.getSelection(), o.current?.querySelector(".rte-content")?.contains(u.target) || (c(!1), f.current = null)); | ||
| s(!1), d.current = null; | ||
| }, C = (c) => { | ||
| g.current && !g.current.contains(c.target) && (window.getSelection(), o.current?.querySelector(".rte-content")?.contains(c.target) || (s(!1), d.current = null)); | ||
| }; | ||
| return document.addEventListener("selectionchange", h), document.addEventListener("mousedown", b), document.addEventListener("keydown", (u) => { | ||
| u.key === "Escape" && (c(!1), f.current = null); | ||
| return document.addEventListener("selectionchange", v), document.addEventListener("mousedown", C), document.addEventListener("keydown", (c) => { | ||
| c.key === "Escape" && (s(!1), d.current = null); | ||
| }), () => { | ||
| document.removeEventListener("selectionchange", h), document.removeEventListener("mousedown", b), g.current && clearTimeout(g.current); | ||
| document.removeEventListener("selectionchange", v), document.removeEventListener("mousedown", C), h.current && clearTimeout(h.current); | ||
| }; | ||
| }, [t]); | ||
| const s = (h, b) => { | ||
| if (!f.current) return; | ||
| const u = o.current?.querySelector(".rte-content"); | ||
| u && u.focus(), { | ||
| const u = (v, C) => { | ||
| if (!d.current) return; | ||
| const c = o.current?.querySelector(".rte-content"); | ||
| c && c.focus(), { | ||
| toggleBold: () => document.execCommand("bold", !1), | ||
@@ -665,23 +665,23 @@ toggleItalic: () => document.execCommand("italic", !1), | ||
| toggleCode: () => { | ||
| const p = window.getSelection(); | ||
| if (p && p.rangeCount > 0) { | ||
| const y = p.getRangeAt(0), C = document.createElement("code"); | ||
| y.surroundContents(C); | ||
| const b = window.getSelection(); | ||
| if (b && b.rangeCount > 0) { | ||
| const p = b.getRangeAt(0), y = document.createElement("code"); | ||
| p.surroundContents(y); | ||
| } | ||
| }, | ||
| setBlockType: () => { | ||
| if (b === "blockquote") { | ||
| const p = window.getSelection(); | ||
| if (p && p.rangeCount > 0) { | ||
| const y = p.getRangeAt(0); | ||
| (y.commonAncestorContainer.nodeType === Node.TEXT_NODE ? y.commonAncestorContainer.parentElement : y.commonAncestorContainer)?.closest?.("blockquote") ? document.execCommand("formatBlock", !1, "p") : document.execCommand("formatBlock", !1, "blockquote"); | ||
| if (C === "blockquote") { | ||
| const b = window.getSelection(); | ||
| if (b && b.rangeCount > 0) { | ||
| const p = b.getRangeAt(0); | ||
| (p.commonAncestorContainer.nodeType === Node.TEXT_NODE ? p.commonAncestorContainer.parentElement : p.commonAncestorContainer)?.closest?.("blockquote") ? document.execCommand("formatBlock", !1, "p") : document.execCommand("formatBlock", !1, "blockquote"); | ||
| } | ||
| } else b && document.execCommand("formatBlock", !1, b); | ||
| } else C && document.execCommand("formatBlock", !1, C); | ||
| } | ||
| }[h]?.(), c(!1), f.current = null, u && u.focus(); | ||
| }[v]?.(), s(!1), d.current = null, c && c.focus(); | ||
| }; | ||
| return !t || !d ? null : /* @__PURE__ */ N( | ||
| return !t || !m ? null : /* @__PURE__ */ R( | ||
| "div", | ||
| { | ||
| ref: m, | ||
| ref: g, | ||
| className: "floating-toolbar", | ||
@@ -708,3 +708,3 @@ style: { | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("toggleBold"), | ||
| onClick: () => u("toggleBold"), | ||
| title: "Bold (Ctrl+B)", | ||
@@ -718,3 +718,3 @@ children: /* @__PURE__ */ l("strong", { children: "B" }) | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("toggleItalic"), | ||
| onClick: () => u("toggleItalic"), | ||
| title: "Italic (Ctrl+I)", | ||
@@ -728,3 +728,3 @@ children: /* @__PURE__ */ l("em", { children: "I" }) | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("toggleUnderline"), | ||
| onClick: () => u("toggleUnderline"), | ||
| title: "Underline (Ctrl+U)", | ||
@@ -738,3 +738,3 @@ children: /* @__PURE__ */ l("u", { children: "U" }) | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("toggleStrikethrough"), | ||
| onClick: () => u("toggleStrikethrough"), | ||
| title: "Strikethrough", | ||
@@ -749,3 +749,3 @@ children: /* @__PURE__ */ l("s", { children: "S" }) | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("clearFormatting"), | ||
| onClick: () => u("clearFormatting"), | ||
| title: "Clear Formatting", | ||
@@ -759,3 +759,3 @@ children: "⌫" | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("createLink"), | ||
| onClick: () => u("createLink"), | ||
| title: "Insert Link", | ||
@@ -769,3 +769,3 @@ children: "🔗" | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("toggleCode"), | ||
| onClick: () => u("toggleCode"), | ||
| title: "Code", | ||
@@ -780,3 +780,3 @@ children: "Code" | ||
| className: "floating-toolbar-btn", | ||
| onClick: () => s("setBlockType", "blockquote"), | ||
| onClick: () => u("setBlockType", "blockquote"), | ||
| title: "Quote", | ||
@@ -789,15 +789,15 @@ children: "❝" | ||
| ); | ||
| }, fe = ({ | ||
| }, we = ({ | ||
| plugins: e, | ||
| children: t | ||
| }) => { | ||
| const d = e.filter((i) => i.context?.provider); | ||
| return d.length === 0 ? /* @__PURE__ */ l(F, { children: t }) : d.reduce( | ||
| const m = e.filter((i) => i.context?.provider); | ||
| return m.length === 0 ? /* @__PURE__ */ l(B, { children: t }) : m.reduce( | ||
| (i, r) => { | ||
| const m = r.context.provider; | ||
| return /* @__PURE__ */ l(m, { children: i }, r.name); | ||
| const g = r.context.provider; | ||
| return /* @__PURE__ */ l(g, { children: i }, r.name); | ||
| }, | ||
| /* @__PURE__ */ l(F, { children: t }) | ||
| /* @__PURE__ */ l(B, { children: t }) | ||
| ); | ||
| }, me = { | ||
| }, ve = { | ||
| toolbar: { | ||
@@ -808,2 +808,6 @@ items: [], | ||
| }, | ||
| statusbar: { | ||
| enabled: !1, | ||
| position: "bottom" | ||
| }, | ||
| menubar: { | ||
@@ -872,12 +876,13 @@ enabled: !1, | ||
| function J(e, t) { | ||
| const d = { ...e }; | ||
| for (const c in t) { | ||
| const i = t[c], r = d[c]; | ||
| i !== void 0 && (typeof i == "object" && i !== null && !Array.isArray(i) && typeof r == "object" && r !== null && !Array.isArray(r) ? d[c] = J(r, i) : d[c] = i); | ||
| const m = { ...e }; | ||
| for (const s in t) { | ||
| const i = t[s], r = m[s]; | ||
| i !== void 0 && (typeof i == "object" && i !== null && !Array.isArray(i) && typeof r == "object" && r !== null && !Array.isArray(r) ? m[s] = J(r, i) : m[s] = i); | ||
| } | ||
| return d; | ||
| return m; | ||
| } | ||
| function ge(e) { | ||
| const t = J(me, { | ||
| function pe(e) { | ||
| const t = J(ve, { | ||
| toolbar: e.toolbar, | ||
| statusbar: e.statusbar, | ||
| menubar: e.menubar, | ||
@@ -914,15 +919,15 @@ contextMenu: e.contextMenu, | ||
| onDestroy: e.onDestroy, | ||
| plugins: Array.isArray(e.plugins) ? e.plugins.filter((c) => typeof c != "string") : [], | ||
| plugins: Array.isArray(e.plugins) ? e.plugins.filter((s) => typeof s != "string") : [], | ||
| pluginConfig: e.pluginConfig || {} | ||
| }; | ||
| } | ||
| const B = /* @__PURE__ */ new Map(); | ||
| const F = /* @__PURE__ */ new Map(); | ||
| typeof window < "u" && (window.registerEditorCommand = (e, t) => { | ||
| B.set(e, t); | ||
| F.set(e, t); | ||
| }, window.executeEditorCommand = (e, t) => { | ||
| const d = B.get(e); | ||
| return d ? d(t) : (console.warn(`No handler registered for command: ${e}`), !1); | ||
| const m = F.get(e); | ||
| return m ? m(t) : (console.warn(`No handler registered for command: ${e}`), !1); | ||
| }); | ||
| const be = (e) => { | ||
| const t = j(() => ge(e), [ | ||
| const ye = (e) => { | ||
| const t = j(() => pe(e), [ | ||
| e.id, | ||
@@ -948,34 +953,34 @@ e.className, | ||
| e.mediaConfig | ||
| ]), d = E(null), c = E(null), i = E(e.onInit), r = E(e.onDestroy), m = E(null); | ||
| T(() => { | ||
| ]), m = E(null), s = E(null), i = E(e.onInit), r = E(e.onDestroy), g = E(null), d = E(null), h = E(null); | ||
| A(() => { | ||
| i.current = e.onInit, r.current = e.onDestroy; | ||
| }); | ||
| const f = j(() => { | ||
| const h = new te(); | ||
| t.plugins.forEach((u) => { | ||
| h.register(u), u.commands && typeof window < "u" && Object.entries(u.commands).forEach(([v, p]) => { | ||
| B.set(v, p); | ||
| const o = j(() => { | ||
| const c = new te(); | ||
| t.plugins.forEach((b) => { | ||
| c.register(b), b.commands && typeof window < "u" && Object.entries(b.commands).forEach(([p, y]) => { | ||
| F.set(p, y); | ||
| }); | ||
| }); | ||
| const b = new ne(h); | ||
| return d.current = b, b; | ||
| const f = new ne(c); | ||
| return m.current = f, f; | ||
| }, [t.plugins]); | ||
| T(() => { | ||
| const h = { | ||
| getHTML: () => m.current?.querySelector(".rte-content")?.innerHTML || "", | ||
| setHTML: (b) => { | ||
| const u = m.current?.querySelector(".rte-content"); | ||
| u && (u.innerHTML = b); | ||
| A(() => { | ||
| const c = { | ||
| getHTML: () => g.current?.querySelector(".rte-content")?.innerHTML || "", | ||
| setHTML: (f) => { | ||
| const b = g.current?.querySelector(".rte-content"); | ||
| b && (b.innerHTML = f); | ||
| }, | ||
| execCommand: (b, u) => { | ||
| typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(b, u); | ||
| execCommand: (f, b) => { | ||
| typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(f, b); | ||
| }, | ||
| registerCommand: (b, u) => { | ||
| typeof window < "u" && window.registerEditorCommand && window.registerEditorCommand(b, u); | ||
| registerCommand: (f, b) => { | ||
| typeof window < "u" && window.registerEditorCommand && window.registerEditorCommand(f, b); | ||
| }, | ||
| focus: () => { | ||
| m.current?.querySelector(".rte-content")?.focus(); | ||
| g.current?.querySelector(".rte-content")?.focus(); | ||
| }, | ||
| blur: () => { | ||
| m.current?.querySelector(".rte-content")?.blur(); | ||
| g.current?.querySelector(".rte-content")?.blur(); | ||
| }, | ||
@@ -985,3 +990,3 @@ destroy: () => { | ||
| }, | ||
| onChange: (b) => () => { | ||
| onChange: (f) => () => { | ||
| }, | ||
@@ -993,14 +998,46 @@ getState: () => ({ | ||
| toolbar: { | ||
| items: f.toolbar?.items || [] | ||
| items: o.toolbar?.items || [] | ||
| } | ||
| }; | ||
| return c.current = h, i.current && i.current(h), () => { | ||
| return s.current = c, i.current && i.current(c), () => { | ||
| r.current && r.current(); | ||
| }; | ||
| }, []); | ||
| const g = t.toolbar.floating ?? !1, o = t.toolbar.position || "top", s = t.toolbar.sticky ?? !1; | ||
| return /* @__PURE__ */ l(fe, { plugins: t.plugins, children: /* @__PURE__ */ N( | ||
| }, []), A(() => { | ||
| if (t.statusbar.enabled && h.current && g.current) { | ||
| d.current || (d.current = new oe({ | ||
| enabled: !0, | ||
| position: t.statusbar.position | ||
| }), d.current.create(h.current)); | ||
| const c = g.current.querySelector(".rte-content"); | ||
| if (c) { | ||
| const f = () => { | ||
| const b = c.textContent || "", { words: p, chars: y } = re(b), w = ae(c), S = window.getSelection(); | ||
| let x, T; | ||
| if (S && S.rangeCount > 0) { | ||
| const L = S.getRangeAt(0); | ||
| x = le(c, L), L.collapsed || (T = ie(L, x), x = void 0); | ||
| } | ||
| d.current?.update({ | ||
| wordCount: p, | ||
| charCount: y, | ||
| lineCount: w, | ||
| cursorPosition: x, | ||
| selectionInfo: T | ||
| }); | ||
| }; | ||
| return c.addEventListener("input", f), c.addEventListener("selectionchange", f), document.addEventListener("selectionchange", f), f(), () => { | ||
| c.removeEventListener("input", f), c.removeEventListener("selectionchange", f), document.removeEventListener("selectionchange", f); | ||
| }; | ||
| } | ||
| } else | ||
| d.current && (d.current.destroy(), d.current = null); | ||
| return () => { | ||
| d.current && (d.current.destroy(), d.current = null); | ||
| }; | ||
| }, [t.statusbar.enabled, t.statusbar.position]); | ||
| const u = t.toolbar.floating ?? !1, v = t.toolbar.position || "top", C = t.toolbar.sticky ?? !1; | ||
| return /* @__PURE__ */ l(we, { plugins: t.plugins, children: /* @__PURE__ */ R( | ||
| "div", | ||
| { | ||
| ref: m, | ||
| ref: g, | ||
| id: t.id, | ||
@@ -1016,15 +1053,15 @@ "data-editora-editor": !0, | ||
| children: [ | ||
| o !== "bottom" && /* @__PURE__ */ l( | ||
| v !== "bottom" && /* @__PURE__ */ l( | ||
| V, | ||
| { | ||
| editor: f, | ||
| position: o, | ||
| sticky: s, | ||
| floating: g | ||
| editor: o, | ||
| position: v, | ||
| sticky: C, | ||
| floating: u | ||
| } | ||
| ), | ||
| /* @__PURE__ */ l( | ||
| de, | ||
| be, | ||
| { | ||
| editor: f, | ||
| editor: o, | ||
| defaultValue: t.defaultValue, | ||
@@ -1040,17 +1077,25 @@ value: t.value, | ||
| ), | ||
| o === "bottom" && /* @__PURE__ */ l( | ||
| v === "bottom" && /* @__PURE__ */ l( | ||
| V, | ||
| { | ||
| editor: f, | ||
| position: o, | ||
| sticky: s, | ||
| floating: g | ||
| editor: o, | ||
| position: v, | ||
| sticky: C, | ||
| floating: u | ||
| } | ||
| ), | ||
| /* @__PURE__ */ l( | ||
| ue, | ||
| he, | ||
| { | ||
| editor: f, | ||
| isEnabled: g | ||
| editor: o, | ||
| isEnabled: u | ||
| } | ||
| ), | ||
| t.statusbar.enabled && /* @__PURE__ */ l( | ||
| "div", | ||
| { | ||
| ref: h, | ||
| className: "editora-statusbar-container", | ||
| style: { order: t.statusbar.position === "top" ? -1 : 1 } | ||
| } | ||
| ) | ||
@@ -1060,13 +1105,13 @@ ] | ||
| ) }); | ||
| }, ye = (e) => /* @__PURE__ */ l(be, { ...e }); | ||
| function Ce(e = {}) { | ||
| const t = E(null), d = E(e.onCommand); | ||
| return T(() => { | ||
| d.current = e.onCommand; | ||
| }), T(() => { | ||
| }, Se = (e) => /* @__PURE__ */ l(ye, { ...e }); | ||
| function Te(e = {}) { | ||
| const t = E(null), m = E(e.onCommand); | ||
| return A(() => { | ||
| m.current = e.onCommand; | ||
| }), A(() => { | ||
| if (typeof window > "u" || e.enabled === !1) return; | ||
| const c = new _(e); | ||
| t.current = c; | ||
| const i = (m) => c.handleKeyDown(m, (g, o) => { | ||
| d.current && d.current(g, o), typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(g, o); | ||
| const s = new _(e); | ||
| t.current = s; | ||
| const i = (g) => s.handleKeyDown(g, (h, o) => { | ||
| m.current && m.current(h, o), typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(h, o); | ||
| }), r = e.editorElement || document; | ||
@@ -1078,3 +1123,3 @@ return r && r.addEventListener("keydown", i), () => { | ||
| getShortcuts: () => t.current?.getAllShortcuts() || [], | ||
| getShortcutForCommand: (c) => t.current?.getShortcutForCommand(c), | ||
| getShortcutForCommand: (s) => t.current?.getShortcutForCommand(s), | ||
| getShortcutsHelp: () => t.current?.getShortcutsHelp() || "", | ||
@@ -1087,9 +1132,9 @@ enable: () => t.current?.enable(), | ||
| export { | ||
| de as EditorContent, | ||
| ye as EditoraEditor, | ||
| oe as InlineMenu, | ||
| ye as RichTextEditor, | ||
| be as EditorContent, | ||
| Se as EditoraEditor, | ||
| ce as InlineMenu, | ||
| Se as RichTextEditor, | ||
| V as Toolbar, | ||
| ge as mergeConfig, | ||
| Ce as useKeyboardShortcuts | ||
| pe as mergeConfig, | ||
| Te as useKeyboardShortcuts | ||
| }; |
+4
-4
| { | ||
| "name": "@editora/react", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "React components for Editora - Best Free Premium Rich Text Editor. Free React WYSIWYG editor with enterprise features, 30+ free plugins, and accessibility support.", | ||
@@ -63,4 +63,4 @@ "author": "Ajay Kumar <ajaykr089@gmail.com>", | ||
| "dependencies": { | ||
| "@editora/core": "^1.0.1", | ||
| "@editora/light-code-editor": "^1.0.1" | ||
| "@editora/core": "^1.0.2", | ||
| "@editora/light-code-editor": "^1.0.2" | ||
| }, | ||
@@ -76,3 +76,3 @@ "devDependencies": { | ||
| }, | ||
| "gitHead": "694494db58b809f0dcf24501696284faa1ab68a5" | ||
| "gitHead": "b4a92679b7a31308632c48abd5e536476d58b0c7" | ||
| } |
+9
-0
| # @editora/react | ||
| <div align="center"> | ||
| <img src="../../images/editora_logo_blocks.svg" alt="Editora Logo" width="200" height="auto"> | ||
| </div> | ||
| <div align="center"> | ||
| <img src="../../images/features-overview-2.png" alt="Editora React - Advanced Tables" width="600" style="border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);"> | ||
| <p><em>React components for Editora Rich Text Editor with hooks-based API</em></p> | ||
| </div> | ||
| React components for Editora Rich Text Editor - A modern, extensible WYSIWYG editor. | ||
@@ -4,0 +13,0 @@ |
| .floating-toolbar{user-select:none;-webkit-user-select:none;font-family:system-ui,-apple-system,sans-serif;font-size:14px;animation:fadeInUp .15s ease-out}@keyframes fadeInUp{0%{opacity:0;transform:translate(-50%) translateY(10px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.floating-toolbar-btn{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:4px;color:#495057;cursor:pointer;font-size:14px;font-weight:500;transition:all .15s ease;outline:none}.floating-toolbar-btn:hover{background:#f8f9fa;color:#212529}.floating-toolbar-btn:active{background:#e9ecef;transform:scale(.95)}.floating-toolbar-btn.floating-toolbar-toggle{color:#dc3545;font-weight:700}.floating-toolbar-btn.floating-toolbar-toggle:hover{background:#f8d7da;color:#721c24}.floating-toolbar-separator{width:1px;height:20px;background:#e1e5e9;margin:0 2px}@media(max-width:768px){.floating-toolbar{padding:"4px";gap:"2px"}.floating-toolbar-btn{width:28px;height:28px;font-size:12px}}.floating-toolbar{pointer-events:auto}.floating-toolbar{max-width:calc(100vw - 20px);overflow-x:auto}@media(prefers-color-scheme:dark){.floating-toolbar{background:#2d3748;border-color:#4a5568;color:#e2e8f0}.floating-toolbar-btn:hover{background:#4a5568;color:#f7fafc}.floating-toolbar-btn:active{background:#718096}.floating-toolbar-separator{background:#4a5568}} |
71773
4.51%1181
3.87%506
1.81%Updated