Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@editora/react

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@editora/react - npm Package Compare versions

Comparing version
1.0.3
to
1.0.4
+183
index.d.ts
import * as React from "react";
import type {
Plugin,
Editor,
ToolbarItem,
KeyboardShortcutConfig,
} from "@editora/core";
export interface EditorAPI {
getHTML(): string;
setHTML(html: string): void;
execCommand(name: string, value?: unknown): void;
registerCommand(name: string, fn: (params?: unknown) => void): void;
focus(): void;
blur(): void;
destroy(): void;
onChange(fn: (html: string) => void): () => void;
getState(): unknown;
toolbar?: { items?: unknown[] };
menubar?: unknown;
contextMenu?: unknown;
media?: unknown;
paste?: unknown;
history?: unknown;
language?: unknown;
spellcheck?: unknown;
autosave?: unknown;
accessibility?: unknown;
performance?: unknown;
content?: unknown;
security?: unknown;
secureInput?(html: string, opts: unknown): string;
}
export interface RichTextEditorProps {
id?: string;
className?: string;
value?: string;
defaultValue?: string;
readonly?: boolean;
placeholder?: string;
onChange?: (html: string) => void;
onInit?: (editor: EditorAPI) => void;
onDestroy?: () => void;
plugins?: Plugin[] | string[];
pluginConfig?: Record<string, unknown>;
toolbar?: {
items?: string[] | ToolbarItem[];
floating?: boolean;
sticky?: boolean;
showMoreOptions?: boolean;
};
statusbar?: {
enabled?: boolean;
position?: "top" | "bottom";
};
menubar?: {
enabled: boolean;
items?: string[];
};
contextMenu?: {
enabled?: boolean;
};
media?: {
uploadUrl?: string;
libraryUrl?: string;
maxFileSize?: number;
allowedTypes?: string[];
headers?: Record<string, string>;
withCredentials?: boolean;
};
paste?: {
clean?: boolean;
keepFormatting?: boolean;
convertWord?: boolean;
};
history?: {
maxSteps?: number;
debounceMs?: number;
};
language?: {
locale?: string;
direction?: "ltr" | "rtl";
};
spellcheck?: {
enabled?: boolean;
provider?: "browser" | "local" | "api";
apiUrl?: string;
apiHeaders?: Record<string, string>;
};
autosave?: {
enabled?: boolean;
intervalMs?: number;
storageKey?: string;
provider?: "localStorage" | "api";
apiUrl?: string;
};
accessibility?: {
enableARIA?: boolean;
keyboardNavigation?: boolean;
checker?: boolean;
};
performance?: {
debounceInputMs?: number;
viewportOnlyScan?: boolean;
};
content?: {
allowedTags?: string[];
allowedAttributes?: Record<string, string[]>;
sanitize?: boolean;
};
security?: {
sanitizeOnPaste?: boolean;
sanitizeOnInput?: boolean;
};
floatingToolbar?: boolean | { enabled?: boolean };
mediaConfig?: {
uploadUrl: string;
libraryUrl: string;
maxFileSize: number;
allowedTypes: string[];
};
}
export interface EditorConfig extends RichTextEditorProps {
plugins: Plugin[];
pluginConfig: Record<string, unknown>;
}
export interface InlineMenuOption {
label: string;
value: string;
}
export interface InlineMenuProps {
isOpen: boolean;
options: InlineMenuOption[];
onSelect: (value: string) => void;
onClose: () => void;
anchorRef: React.RefObject<HTMLElement>;
className?: string;
}
export interface UseKeyboardShortcutsOptions extends KeyboardShortcutConfig {
onCommand?: (command: string, params?: unknown) => void;
editorElement?: HTMLElement | null;
}
export interface ToolbarProps {
editor: Editor;
position?: "top" | "bottom";
sticky?: boolean;
floating?: boolean;
readonly?: boolean;
showMoreOptions?: boolean;
itemsOverride?: string[] | ToolbarItem[];
}
export interface EditorContentProps {
editor: Editor;
defaultValue?: string;
value?: string;
readonly?: boolean;
placeholder?: string;
onChange?: (html: string) => void;
}
export const RichTextEditor: React.FC<RichTextEditorProps>;
export const EditoraEditor: React.FC<RichTextEditorProps>;
export const Toolbar: React.FC<ToolbarProps>;
export const EditorContent: React.FC<EditorContentProps>;
export const InlineMenu: React.FC<InlineMenuProps>;
export function useKeyboardShortcuts(options?: UseKeyboardShortcutsOptions): {
getShortcuts: () => unknown[];
getShortcutForCommand: (command: string) => unknown;
getShortcutsHelp: () => string;
enable: () => void;
disable: () => void;
isEnabled: () => boolean;
};
export function mergeConfig(props: RichTextEditorProps): EditorConfig;
+1
-1

@@ -1,1 +0,1 @@

"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;
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),c=require("react"),O=require("@editora/core"),ue=({isOpen:e,options:t,onSelect:f,onClose:l,anchorRef:r,className:o=""})=>{const h=c.useRef(null),[v,u]=c.useState(null),g=()=>{if(!e||!r.current)return;const d=r.current.getBoundingClientRect(),A=h.current?.getBoundingClientRect(),R=A?.width||120,I=A?.height||t.length*36,s=8,F=4,N=window.innerWidth,C=window.innerHeight;let p=d.bottom+F,a=d.left;a+R>N-s&&(a=N-R-s),a<s&&(a=s),p+I>C-s&&(p=d.top-I-F),p<s&&(p=s),u({top:p,left:a})};return c.useLayoutEffect(()=>{if(!e){u(null);return}g();const d=window.requestAnimationFrame(g);return()=>{window.cancelAnimationFrame(d)}},[e,t.length,r]),c.useEffect(()=>{if(!e)return;const d=()=>{g()};return window.addEventListener("resize",d),window.addEventListener("scroll",d,!0),()=>{window.removeEventListener("resize",d),window.removeEventListener("scroll",d,!0)}},[e,t.length,r]),c.useEffect(()=>{const d=R=>{h.current&&!h.current.contains(R.target)&&r.current&&!r.current.contains(R.target)&&l()},A=R=>{R.key==="Escape"&&l()};return e&&(document.addEventListener("mousedown",d),document.addEventListener("keydown",A)),()=>{document.removeEventListener("mousedown",d),document.removeEventListener("keydown",A)}},[e,l,r]),e?i.jsx("div",{ref:h,className:`rte-inline-menu ${o}`,style:{top:v?.top??-9999,left:v?.left??-9999,visibility:v?"visible":"hidden"},children:t.map(d=>i.jsx("div",{className:"rte-inline-menu-item",onClick:()=>{f(d.value),l()},children:d.label},d.value))}):null},$=e=>e.toLowerCase().replace(/[^a-z0-9]/g,""),Ee={undo:"undo",redo:"redo",bold:"toggleBold",italic:"toggleItalic",underline:"toggleUnderline",strikethrough:"toggleStrikethrough",textcolor:"openTextColorPicker",backgroundcolor:"openBackgroundColorPicker",fontsize:"setFontSize",increasefontsize:"increaseFontSize",decreasefontsize:"decreaseFontSize",heading:"setHeading",paragraph:"setHeading",textalignment:"setTextAlignment",direction:"setDirectionLTR",bullist:"toggleBulletList",numlist:"toggleOrderedList",checklist:"toggleChecklist",indent:"increaseIndent",outdent:"decreaseIndent",link:"openLinkDialog",image:"insertImage",video:"insertVideo",table:"insertTable",clearformatting:"clearFormatting"},xe=(e,t)=>{if(!Array.isArray(t)||t.length===0)return e;if(!t.every(u=>typeof u=="string"))return t;const l=new Map,r=new Map;e.forEach(u=>{l.set($(u.command||""),u),r.set($(u.label||""),u)});const o=t.flatMap(u=>u.split(/\s+/)).map(u=>u.trim()).filter(Boolean),h=[];let v=0;return o.forEach(u=>{if(u==="|"){v+=1,h.push({type:"separator",command:`__separator__${v}`,label:"|"});return}const g=$(u),d=Ee[g],A=l.get(g)||(d?l.get($(d)):void 0)||r.get(g)||e.find(R=>$(R.command||"").includes(g));A&&h.push(A)}),h.length>0?h:e},Q=({editor:e,position:t="top",sticky:f=!1,floating:l=!1,readonly:r=!1,showMoreOptions:o=!0,itemsOverride:h})=>{const[v,u]=c.useState(null),[g,d]=c.useState(null),[A,R]=c.useState(null),[I,s]=c.useState(!1),F=c.useRef(null),N=c.useRef(null),C=c.useRef({}),p=c.useRef([]),a=c.useRef(null),L=c.useRef(null),T=c.useRef(null),w=c.useMemo(()=>xe(e.pluginManager.getToolbarItems(),h),[e,h]),k=n=>{F.current=n,n&&!n.collapsed&&(N.current=n)},y=()=>a.current?.closest("[data-editora-editor]")?.querySelector(".rte-content")||null,M=()=>{if(typeof window>"u")return;const n=a.current?.closest("[data-editora-editor]");window.__editoraCommandEditorRoot=n||null},m=()=>{const n=y();if(!n)return null;const b=window.getSelection();if(!b||b.rangeCount===0)return null;const S=b.getRangeAt(0);return n.contains(S.commonAncestorContainer)?S.cloneRange():null},E=()=>{const n=m();n&&k(n)};c.useEffect(()=>{const n=()=>{E()};return document.addEventListener("selectionchange",n),()=>{document.removeEventListener("selectionchange",n)}},[]);const H=n=>["toggleBold","toggleItalic","toggleUnderline","toggleStrikethrough","openTextColorPicker","openBackgroundColorPicker","openLinkDialog","removeLink","toggleCode"].includes(n),B=(n=!1)=>{const b=y();if(!b)return!1;const S=window.getSelection();if(!S)return!1;const x=S.rangeCount>0&&b.contains(S.getRangeAt(0).commonAncestorContainer),j=n?N.current||F.current:F.current||N.current;if(n&&j&&j.collapsed)return!1;if(j&&b.contains(j.commonAncestorContainer))try{return b.focus({preventScroll:!0}),S.removeAllRanges(),S.addRange(j),!0}catch{}return x};c.useEffect(()=>{if(!o){R(null),s(!1),p.current=[];return}let n=null;const b=()=>{if(!a.current||!L.current)return;const j=a.current.clientWidth,G=16,Ce=40,ne=4,ye=Math.max(0,j-G-Ce-ne);let re=0,oe=0;const X=L.current.children;for(let U=0;U<X.length;U++){const J=X[U].getBoundingClientRect().width;J>0&&(p.current[U]=J);const ie=p.current[U]??J,le=(ie>0?ie:40)+ne;if(re+le<=ye)re+=le,oe++;else break}const ae=Math.max(1,Math.min(oe,X.length));R(U=>U===ae?U:ae)},S=()=>{n!==null&&cancelAnimationFrame(n),n=requestAnimationFrame(b)};p.current=[],S();const x=new ResizeObserver(()=>{S()});return a.current&&x.observe(a.current),L.current&&x.observe(L.current),()=>{n!==null&&cancelAnimationFrame(n),x.disconnect()}},[w.length,o]),c.useEffect(()=>{I&&A!==null&&A>=w.length&&s(!1)},[I,A,w.length]);const z=n=>(C.current[n]||(C.current[n]=c.createRef()),C.current[n]),D=(n,b)=>{if(r)return;M(),n==="addComment"||n==="toggleComments"||B(H(n));const j={toggleBold:"bold",toggleItalic:"italic",toggleUnderline:"underline"}[n];if(j){document.execCommand(j,!1),u(null);return}typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(n,b),u(null)},W=n=>{r||(E(),u(v===n?null:n))},_=n=>{r||(E(),d(g===n?null:n),u(null))},P=(n,b)=>{r||(B(),D(n,b),k(null),N.current=null,d(null))},q=(n,b)=>n&&n.startsWith("<svg")&&n.endsWith("</svg>")?i.jsx("span",{dangerouslySetInnerHTML:{__html:n}}):n&&n.length===1&&/^[BIUSH]$/.test(n)?i.jsx("span",{style:{fontWeight:"bold",fontSize:"14px",lineHeight:"1"},children:n}):n||"⚪",we={...f&&{position:"sticky",top:0,zIndex:100,backgroundColor:"#fff",boxShadow:"0 2px 4px rgba(0,0,0,0.1)"},...t==="bottom"&&{order:2}},ee=o&&A!==null&&A<w.length,pe=n=>{r||!n.target.closest(".rte-toolbar-button, .rte-toolbar-dropdown-item, .rte-toolbar-more-button")||(M(),E(),n.preventDefault())},te=n=>n.map((b,S)=>{const x=b.command||"";return i.jsx("div",{className:"rte-toolbar-item",style:{display:o&&A!==null&&S>=A?"none":"flex"},children:b.type==="separator"?i.jsx("div",{className:"rte-toolbar-separator","aria-hidden":"true"}):b.type==="dropdown"?i.jsxs("div",{className:"rte-toolbar-dropdown",children:[i.jsxs("button",{className:"rte-toolbar-button","data-command":x,"data-active":"false",onMouseDown:j=>{j.preventDefault(),E()},onClick:()=>W(x),disabled:r,children:[b.label," ▼"]}),v===x&&i.jsx("div",{className:"rte-toolbar-dropdown-menu",children:b.options?.map(j=>i.jsx("div",{className:"rte-toolbar-dropdown-item",onMouseDown:G=>G.preventDefault(),onClick:()=>D(x,j.value),children:j.label},j.value))})]}):b.type==="inline-menu"?i.jsx("button",{ref:z(x),className:"rte-toolbar-button","data-command":x,"data-active":"false",onMouseDown:j=>{j.preventDefault(),E()},onClick:()=>_(x),disabled:r,title:b.label,children:q(b.icon)}):b.type==="input"?i.jsx("input",{type:"text",className:`rte-toolbar-input ${b.label.toLowerCase().replace(/\s+/g,"-")}`,placeholder:b.placeholder,onChange:j=>D(x,j.target.value),disabled:r,onKeyDown:j=>{j.key==="Enter"&&D(x,j.target.value)},title:b.label}):b.type==="group"?i.jsx("div",{className:`rte-toolbar-group-button ${b.label.toLowerCase().replace(/\s+/g,"-")}`,title:`${b.label}`,children:i.jsx("div",{className:`rte-toolbar-group-items ${b.label.toLowerCase().replace(/\s+/g,"-")}`,children:te(b.items||[])})}):i.jsx("button",{className:"rte-toolbar-button","data-command":x,"data-active":"false",onMouseDown:j=>{j.preventDefault(),E()},onClick:()=>D(x),disabled:r,title:b.label,children:q(b.icon)})},S)});return i.jsxs(i.Fragment,{children:[i.jsxs("div",{className:"rte-toolbar-wrapper",style:we,onMouseDownCapture:pe,children:[i.jsxs("div",{className:"rte-toolbar",ref:a,children:[i.jsx("div",{className:"rte-toolbar-items-container",ref:L,style:o?void 0:{flexWrap:"wrap"},children:te(w)}),ee&&i.jsx("button",{ref:T,className:`rte-toolbar-more-button ${I?"active":""}`,onMouseDown:n=>{n.preventDefault(),E()},onClick:()=>s(!I),disabled:r,title:"Show more options","aria-label":"More toolbar options",children:"☰"})]}),ee&&i.jsx("div",{className:`rte-toolbar-expanded-row ${I?"show":""}`,children:w.map((n,b)=>{if(b<(A||0))return null;const S=n.command||"";return i.jsx("div",{className:"rte-toolbar-item",children:n.type==="separator"?i.jsx("div",{className:"rte-toolbar-separator","aria-hidden":"true"}):n.type==="dropdown"?i.jsxs("div",{className:"rte-toolbar-dropdown",children:[i.jsxs("button",{className:"rte-toolbar-button","data-command":S,"data-active":"false",onMouseDown:x=>{x.preventDefault(),E()},onClick:()=>W(S),disabled:r,children:[n.label," ▼"]}),v===S&&i.jsx("div",{className:"rte-toolbar-dropdown-menu",children:n.options?.map(x=>i.jsx("div",{className:"rte-toolbar-dropdown-item",onMouseDown:j=>j.preventDefault(),onClick:()=>D(S,x.value),children:x.label},x.value))})]}):n.type==="inline-menu"?i.jsx("button",{ref:z(S),className:"rte-toolbar-button","data-command":S,"data-active":"false",onMouseDown:x=>{x.preventDefault(),E()},onClick:()=>_(S),disabled:r,title:n.label,children:q(n.icon)}):n.type==="input"?i.jsx("input",{type:"text",className:"rte-toolbar-input",placeholder:n.placeholder,onChange:x=>D(S,x.target.value),disabled:r,onKeyDown:x=>{x.key==="Enter"&&D(S,x.target.value)},title:n.label}):i.jsx("button",{className:"rte-toolbar-button","data-command":S,"data-active":"false",onMouseDown:x=>{x.preventDefault(),E()},onClick:()=>D(S),disabled:r,title:n.label,children:q(n.icon)})},b)})})]}),w.map(n=>{if(n.type==="inline-menu"){const b=n.command||"";return i.jsx(ue,{isOpen:g===b,options:n.options||[],onSelect:S=>P(b,S),onClose:()=>d(null),anchorRef:z(b)},`menu-${b||"unknown"}`)}return null})]})};function ke(e,t){const f=c.useRef(),l=c.useRef("");return c.useEffect(()=>{if(!t?.enabled)return;const o=t.intervalMs||3e4,h=t.storageKey||"rte-autosave",v=t.provider||"localStorage",u=async()=>{const g=e();if(g!==l.current){if(l.current=g,v==="localStorage")try{localStorage.setItem(h,g),localStorage.setItem(`${h}-timestamp`,Date.now().toString()),console.log("[Autosave] Content saved to localStorage")}catch(d){console.error("[Autosave] Failed to save to localStorage:",d)}else if(v==="api"&&t.apiUrl)try{await fetch(t.apiUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:g,timestamp:Date.now()})}),console.log("[Autosave] Content saved to API")}catch(d){console.error("[Autosave] Failed to save to API:",d)}}};return f.current=setInterval(u,o),()=>{f.current&&clearInterval(f.current)}},[t?.enabled,t?.intervalMs,t?.storageKey,t?.provider,t?.apiUrl,e]),{restore:()=>{if(!t?.enabled)return null;const o=t.storageKey||"rte-autosave";if((t.provider||"localStorage")==="localStorage")try{const v=localStorage.getItem(o),u=localStorage.getItem(`${o}-timestamp`);if(v&&u)return console.log("[Autosave] Restored from localStorage, saved at:",new Date(parseInt(u))),v}catch(v){console.error("[Autosave] Failed to restore from localStorage:",v)}return null}}}const Se=["p","br","strong","em","u","s","strike","del","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"],Re={"*":["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 de(e,t,f){if(t?.sanitize===!1)return e;const l=t?.allowedTags&&t.allowedTags.length>0?t.allowedTags:Se,o=!!t?.allowedAttributes&&Object.keys(t.allowedAttributes).length>0?t.allowedAttributes:Re,h=document.createElement("div");return h.innerHTML=e,fe(h,l,o),h.innerHTML}function fe(e,t,f){const l=Array.from(e.childNodes);for(const r of l)if(r.nodeType===Node.ELEMENT_NODE){const o=r,h=o.tagName.toLowerCase();if(!t.includes(h)){for(;o.firstChild;)e.insertBefore(o.firstChild,o);e.removeChild(o);continue}Le(o,f),fe(o,t,f)}else{if(r.nodeType===Node.TEXT_NODE)continue;e.removeChild(r)}}function Le(e,t){const f=e.tagName.toLowerCase(),l=Array.from(e.attributes),r=t[f]||[],o=t["*"]||[],h=[...r,...o];for(const v of l){const u=v.name.toLowerCase();let g=!1;h.includes(u)&&(g=!0);for(const d of h)if(d.endsWith("*")){const A=d.slice(0,-1);if(u.startsWith(A)){g=!0;break}}(u.startsWith("on")||u==="javascript:"||u==="href"&&v.value.trim().toLowerCase().startsWith("javascript:")||u==="src"&&v.value.trim().toLowerCase().startsWith("javascript:"))&&(g=!1),g||e.removeAttribute(v.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 Ae(e,t,f){return f?.sanitizeOnPaste===!1?e:de(e,t)}function Te(e,t,f){return f?.sanitizeOnInput===!1?e:de(e,t)}const V=e=>(e.textContent||"").replace(/\u200B/g,"").trim().length>0?!1:!e.querySelector("img, video, table, iframe, hr, pre, blockquote, ul, ol"),K=(e,t)=>{const l=!!t&&V(e);e.classList.toggle("rte-content-empty",l)},me=({editor:e,defaultValue:t,value:f,readonly:l=!1,placeholder:r,onChange:o,pasteConfig:h,contentConfig:v,securityConfig:u,performanceConfig:g,accessibilityConfig:d,autosaveConfig:A,contextMenuConfig:R,spellcheckConfig:I})=>{const s=c.useRef(null),F=f!==void 0,N=c.useRef(),{restore:C}=ke(()=>s.current?.innerHTML||"",A);c.useEffect(()=>{if(!s.current)return;const a=C(),L=a??f??t??"";L.trim()?s.current.innerHTML!==L&&(s.current.innerHTML=L):r?s.current.innerHTML="":s.current.innerHTML.trim()||(s.current.innerHTML="<p><br></p>"),K(s.current,r),a&&o&&o(a)},[]),c.useEffect(()=>{!s.current||!F||(f!==s.current.innerHTML&&(s.current.innerHTML=f),K(s.current,r))},[f,F]),c.useEffect(()=>{if(!s.current)return;const a=s.current;if(r){a.setAttribute("data-placeholder",r),V(a)&&(a.innerHTML=""),K(a,r);return}a.removeAttribute("data-placeholder"),K(a,r)},[r]),c.useEffect(()=>{if(!s.current)return;const a=s.current;if(d?.enableARIA!==!1){a.setAttribute("role","textbox"),a.setAttribute("aria-multiline","true"),a.setAttribute("aria-disabled",l?"true":"false");const T=r?.trim();T?a.setAttribute("aria-label",T):a.removeAttribute("aria-label")}else a.removeAttribute("role"),a.removeAttribute("aria-multiline"),a.removeAttribute("aria-label"),a.removeAttribute("aria-disabled")},[d?.enableARIA,r,l]),c.useEffect(()=>{if(!s.current)return;const a=()=>{if(!s.current||l)return;r&&V(s.current)&&(s.current.innerHTML="");let M=s.current.innerHTML;if(u?.sanitizeOnInput!==!1&&v?.sanitize!==!1&&(M=Te(M,v,u),M!==s.current.innerHTML)){const m=window.getSelection(),E=m&&m.rangeCount>0?m.getRangeAt(0):null;if(s.current.innerHTML=M,E&&m)try{m.removeAllRanges(),m.addRange(E)}catch{}}K(s.current,r),o&&(g?.debounceInputMs?(N.current&&clearTimeout(N.current),N.current=setTimeout(()=>{o(M)},g.debounceInputMs)):o(M))},L=M=>{if(l){M.preventDefault();return}M.preventDefault();let m=M.clipboardData?.getData("text/html");const E=M.clipboardData?.getData("text/plain"),H=!!m&&/class=["'][^"']*Mso|xmlns:w=|urn:schemas-microsoft-com:office/i.test(m);if(h?.clean||!h?.keepFormatting){E&&document.execCommand("insertText",!1,E);return}if(h?.convertWord===!1&&H){E&&document.execCommand("insertText",!1,E);return}if(m){u?.sanitizeOnPaste!==!1&&v?.sanitize!==!1&&(m=Ae(m,v,u));const B=window.getSelection();if(B&&B.rangeCount>0){const z=B.getRangeAt(0);z.deleteContents();const D=document.createElement("div");D.innerHTML=m;const W=document.createDocumentFragment();for(;D.firstChild;)W.appendChild(D.firstChild);z.insertNode(W),z.collapse(!1),B.removeAllRanges(),B.addRange(z)}}else E&&document.execCommand("insertText",!1,E)},T=M=>{const m=M.target;(m.tagName==="IMG"||m.tagName==="VIDEO")&&(m.style.resize="both",m.style.overflow="auto",m.style.display="inline-block")},w=M=>{R?.enabled===!1&&M.preventDefault()},k=()=>{s.current&&(r&&V(s.current)&&(s.current.innerHTML=""),K(s.current,r))},y=s.current;return y.addEventListener("input",a),y.addEventListener("paste",L),y.addEventListener("click",T),y.addEventListener("contextmenu",w),y.addEventListener("focus",k),y.addEventListener("blur",k),l||y.focus(),()=>{N.current&&clearTimeout(N.current),y.removeEventListener("input",a),y.removeEventListener("paste",L),y.removeEventListener("click",T),y.removeEventListener("contextmenu",w),y.removeEventListener("focus",k),y.removeEventListener("blur",k)}},[e,o,h,v,u,g,r,R,l]);const p=(I?.enabled??!1)&&(I?.provider??"browser")==="browser";return c.useEffect(()=>{if(!s.current||typeof window>"u"||l||d?.keyboardNavigation===!1)return;const a=new O.KeyboardShortcutManager,L=s.current,T=w=>{a.handleKeyDown(w,(k,y)=>{if(typeof window<"u"&&window.executeEditorCommand){const M=s.current?.closest("[data-editora-editor]");window.__editoraCommandEditorRoot=M||null,window.executeEditorCommand(k,y)}})};return L.addEventListener("keydown",T),()=>{L.removeEventListener("keydown",T)}},[d?.keyboardNavigation,l]),i.jsx("div",{ref:s,contentEditable:!l,suppressContentEditableWarning:!0,spellCheck:l?!1:p,tabIndex:d?.keyboardNavigation===!1?-1:0,"aria-keyshortcuts":d?.keyboardNavigation===!1?void 0:"Ctrl+B Ctrl+I Ctrl+U Ctrl+Z Ctrl+Y","data-viewport-only-scan":g?.viewportOnlyScan?"true":"false","data-a11y-checker":d?.checker?"true":"false","data-readonly":l?"true":"false",className:`rte-content ${l?"rte-content-readonly":""}`,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"}})},Me=({editor:e,isEnabled:t,viewportOnlyScan:f=!0,readonly:l=!1})=>{const[r,o]=c.useState(!1),[h,v]=c.useState({top:0,left:0}),u=c.useRef(null),g=c.useRef(null),d=c.useRef(null),A=c.useRef(null),R=c.useRef(null);c.useEffect(()=>{if(!t||l){o(!1);return}R.current=u.current?.closest("[data-editora-editor]");const s=w=>{if(R.current)return R.current;const k=u.current?.closest("[data-editora-editor]");if(k)return R.current=k,k;const y=w?.commonAncestorContainer,m=(y?y.nodeType===Node.ELEMENT_NODE?y:y.parentElement:null)?.closest("[data-editora-editor]");return m?(R.current=m,m):null},F=w=>w&&w.querySelector(".rte-content, .editora-content")||null,N=w=>{if(!w.anchorNode||!w.focusNode)return!1;try{const k=document.createRange();return k.setStart(w.anchorNode,w.anchorOffset),k.setEnd(w.focusNode,w.focusOffset),k.collapsed}catch{return!1}},C=(w,k)=>{const y=Array.from(k.getClientRects()).filter(m=>m.width>0||m.height>0);return y.length===0?k.getBoundingClientRect():N(w)?y[0]:y[y.length-1]},p=()=>{A.current&&clearTimeout(A.current);const w=window.getSelection();if(!w||w.rangeCount===0){o(!1),d.current=null;return}const k=w.getRangeAt(0);if(k.collapsed){o(!1),d.current=null;return}const y=w.toString().trim(),M=s(k),m=F(M);if(!m||!m.contains(k.commonAncestorContainer)){o(!1),d.current=null;return}if(f){const E=m.getBoundingClientRect(),H=E.bottom>=0&&E.top<=window.innerHeight,B=document.activeElement===m||m.contains(document.activeElement);if(!H&&!B){o(!1),d.current=null;return}}if(y.length>0){const E=C(w,k),H=m.getBoundingClientRect(),B=300;if(E&&H){const z=Math.max(8,E.top-50);let D=E.left+E.width/2;const W=B/2,_=H.left,P=H.right;D-W<_&&(D=_+W+10),D+W>P&&(D=P-W-10),v({top:z,left:D}),o(!0),d.current=k.cloneRange()}}else o(!1),d.current=null},a=w=>{if(g.current&&!g.current.contains(w.target)){const k=s();window.getSelection(),F(k)?.contains(w.target)||(o(!1),d.current=null)}},L=w=>{w.key==="Escape"&&(o(!1),d.current=null)},T=F(s());return document.addEventListener("selectionchange",p),document.addEventListener("mousedown",a),document.addEventListener("keydown",L),T?.addEventListener("mouseup",p),T?.addEventListener("keyup",p),()=>{document.removeEventListener("selectionchange",p),document.removeEventListener("mousedown",a),document.removeEventListener("keydown",L),T?.removeEventListener("mouseup",p),T?.removeEventListener("keyup",p),A.current&&clearTimeout(A.current)}},[t,f,l]);const I=(s,F)=>{if(l||!d.current)return;typeof window<"u"&&(window.__editoraCommandEditorRoot=R.current||null);const N=R.current?.querySelector(".rte-content");N&&N.focus();const C=window.getSelection();if(C&&d.current)try{C.removeAllRanges(),C.addRange(d.current)}catch{}({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 a=window.getSelection();if(a&&a.rangeCount>0){const L=a.getRangeAt(0),T=document.createElement("code");L.surroundContents(T)}},setBlockType:()=>{if(F==="blockquote"){const a=window.getSelection();if(a&&a.rangeCount>0){const L=a.getRangeAt(0);(L.commonAncestorContainer.nodeType===Node.TEXT_NODE?L.commonAncestorContainer.parentElement:L.commonAncestorContainer)?.closest?.("blockquote")?document.execCommand("formatBlock",!1,"p"):document.execCommand("formatBlock",!1,"blockquote")}}else F&&document.execCommand("formatBlock",!1,F)}})[s]?.(),o(!1),d.current=null};return!t||l?i.jsx("span",{ref:u,style:{display:"none"},"aria-hidden":"true"}):i.jsxs(i.Fragment,{children:[i.jsx("span",{ref:u,style:{display:"none"},"aria-hidden":"true"}),r&&i.jsxs("div",{ref:g,className:"floating-toolbar",onMouseDown:s=>s.preventDefault(),style:{position:"fixed",top:`${h.top}px`,left:`${h.left}px`,transform:"translateX(-50%)",zIndex:1e4,display:"flex"},children:[i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("toggleBold"),title:"Bold (Ctrl+B)",children:i.jsx("strong",{children:"B"})}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("toggleItalic"),title:"Italic (Ctrl+I)",children:i.jsx("em",{children:"I"})}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("toggleUnderline"),title:"Underline (Ctrl+U)",children:i.jsx("u",{children:"U"})}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("toggleStrikethrough"),title:"Strikethrough",children:i.jsx("s",{children:"S"})}),i.jsx("div",{className:"floating-toolbar-separator"}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("clearFormatting"),title:"Clear Formatting",children:"⌫"}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("createLink"),title:"Insert Link",children:"🔗"}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("toggleCode"),title:"Code",children:"Code"}),i.jsx("div",{className:"floating-toolbar-separator"}),i.jsx("button",{className:"floating-toolbar-btn",onClick:()=>I("setBlockType","blockquote"),title:"Quote",children:"❝"})]})]})},je=({plugins:e,children:t})=>{const f=e.filter(r=>r.context?.provider);return f.length===0?i.jsx(i.Fragment,{children:t}):f.reduce((r,o)=>{const h=o.context.provider;return i.jsx(h,{children:r},o.name)},i.jsx(i.Fragment,{children:t}))},se=new Set,ce=new Set,Y=e=>!!e&&typeof e=="object"&&typeof e.name=="string",ge=e=>{const t=e?.pluginFactories;return{...(typeof window<"u"?window.EditoraReactPlugins:void 0)||{},...t||{}}},Ie=(e,t)=>{if(!Array.isArray(e))return[];const f=ge(t),l=[],r=[];if(e.forEach(o=>{if(Y(o)){l.push(o);return}if(typeof o!="string")return;const h=f[o];if(typeof h=="function")try{const v=h();if(Y(v)){l.push(v);return}}catch{}r.push(o)}),r.length>0){const o=r.slice().sort().join("|");se.has(o)||(se.add(o),console.warn(`[Editora React] Unresolved string plugin names: ${r.join(", ")}. Pass plugin instances or provide plugin factories via "pluginConfig.pluginFactories" or "window.EditoraReactPlugins".`))}return l},Ne=(e,t,f)=>{if(!t?.checker||e.some(o=>o?.name==="a11yChecker"))return e;const l=ge(f).a11yChecker;if(typeof l=="function")try{const o=l();if(Y(o))return[...e,o]}catch{}const r="accessibility.checker";return ce.has(r)||(ce.add(r),console.warn('[Editora React] accessibility.checker=true requires an "a11yChecker" plugin instance or factory.')),e},De={readonly:!1,placeholder:"",toolbar:{items:[],floating:!1,sticky:!1,showMoreOptions:!0},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 be(e,t){const f={...e};for(const l in t){const r=t[l],o=f[l];r!==void 0&&(typeof r=="object"&&r!==null&&!Array.isArray(r)&&typeof o=="object"&&o!==null&&!Array.isArray(o)?f[l]=be(o,r):f[l]=r)}return f}function he(e){const t=be(De,{readonly:e.readonly,placeholder:e.placeholder,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});if(e.floatingToolbar!==void 0){const l=typeof e.floatingToolbar=="boolean"?e.floatingToolbar:e.floatingToolbar.enabled;t.toolbar={...t.toolbar,floating:l??t.toolbar.floating}}return 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:Ne(Ie(e.plugins,e.pluginConfig),e.accessibility,e.pluginConfig),pluginConfig:e.pluginConfig||{}}}const Z=new Map;typeof window<"u"&&(window.registerEditorCommand=(e,t)=>{Z.set(e,t)},window.executeEditorCommand=(e,t)=>{const f=Z.get(e);return f?f(t):(console.warn(`No handler registered for command: ${e}`),!1)});const Fe=e=>{const t=c.useMemo(()=>he(e),[e.id,e.className,e.value,e.defaultValue,e.readonly,e.placeholder,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]),f=c.useRef(null),l=c.useRef(null),r=c.useRef(e.onInit),o=c.useRef(e.onDestroy),h=c.useRef(e.onChange),v=c.useRef(new Set),u=c.useRef(null),g=c.useRef(null),d=c.useRef(null);c.useEffect(()=>{r.current=e.onInit,o.current=e.onDestroy,h.current=e.onChange});const A=C=>{h.current?.(C),v.current.forEach(p=>{try{p(C)}catch(a){console.error("Editora onChange subscriber failed:",a)}})},R=c.useMemo(()=>{const C=new O.PluginManager;t.plugins.forEach(a=>{C.register(a),a.commands&&typeof window<"u"&&Object.entries(a.commands).forEach(([L,T])=>{Z.set(L,T)})});const p=new O.Editor(C);return f.current=p,p},[t.plugins]);c.useEffect(()=>{const C={getHTML:()=>u.current?.querySelector(".rte-content")?.innerHTML||"",setHTML:p=>{const a=u.current?.querySelector(".rte-content");a&&(a.innerHTML=p)},execCommand:(p,a)=>{typeof window<"u"&&window.executeEditorCommand&&(window.__editoraCommandEditorRoot=u.current||null,window.executeEditorCommand(p,a))},registerCommand:(p,a)=>{typeof window<"u"&&window.registerEditorCommand&&window.registerEditorCommand(p,a)},focus:()=>{u.current?.querySelector(".rte-content")?.focus()},blur:()=>{u.current?.querySelector(".rte-content")?.blur()},destroy:()=>{o.current&&o.current()},onChange:p=>(v.current.add(p),()=>{v.current.delete(p)}),getState:()=>({plugins:t.plugins,config:t}),toolbar:{items:R.toolbar?.items||[]}};return l.current=C,r.current&&r.current(C),()=>{v.current.clear(),o.current&&o.current()}},[]),c.useEffect(()=>{if(t.statusbar.enabled&&d.current&&u.current){g.current||(g.current=new O.StatusBar({enabled:!0,position:t.statusbar.position}),g.current.create(d.current));const C=u.current.querySelector(".rte-content");if(C){const p=()=>{const m=document.activeElement;return!!m&&(m===C||C.contains(m))},a=()=>{const m=C.getBoundingClientRect();return m.bottom>=0&&m.top<=window.innerHeight},L=()=>{const m=window.getSelection();if(!m||m.rangeCount===0)return null;const E=m.getRangeAt(0),H=E.commonAncestorContainer;return C.contains(H)?E:null},T=(m=!1)=>{if(t.performance.viewportOnlyScan!==!1&&!a()&&!p())return;const H=L(),B=!!H||p();if(m&&!B)return;const z=C.textContent||"",{words:D,chars:W}=O.calculateTextStats(z),_=O.countLines(C);let P,q;H&&(P=O.getCursorPosition(C,H),H.collapsed||(q=O.getSelectionInfo(H,P),P=void 0)),g.current?.update({wordCount:D,charCount:W,lineCount:_,cursorPosition:P,selectionInfo:q})},w=()=>T(),k=()=>T(!0),y=()=>T(),M=()=>T();return C.addEventListener("input",w),C.addEventListener("focus",y),C.addEventListener("blur",M),document.addEventListener("selectionchange",k),T(),()=>{C.removeEventListener("input",w),C.removeEventListener("focus",y),C.removeEventListener("blur",M),document.removeEventListener("selectionchange",k)}}}else g.current&&(g.current.destroy(),g.current=null);return()=>{g.current&&(g.current.destroy(),g.current=null)}},[t.statusbar.enabled,t.statusbar.position,t.performance.viewportOnlyScan]);const I=t.toolbar.floating??!1,s=t.toolbar.position||"top",F=t.toolbar.sticky??!1,N=t.toolbar.showMoreOptions??!0;return i.jsx(je,{plugins:t.plugins,children:i.jsxs("div",{ref:u,id:t.id,"data-editora-editor":!0,"data-readonly":t.readonly?"true":"false",className:`rte-editor ${t.className||""}`,lang:t.language.locale,dir:t.language.direction,style:{display:"flex",flexDirection:"column",height:"100%"},children:[s!=="bottom"&&i.jsx(Q,{editor:R,position:s,sticky:F,floating:I,readonly:t.readonly,showMoreOptions:N,itemsOverride:t.toolbar.items}),i.jsx(me,{editor:R,defaultValue:t.defaultValue,value:t.value,readonly:t.readonly,placeholder:t.placeholder,onChange:A,pasteConfig:t.paste,contentConfig:t.content,securityConfig:t.security,performanceConfig:t.performance,accessibilityConfig:t.accessibility,autosaveConfig:t.autosave,contextMenuConfig:t.contextMenu,spellcheckConfig:t.spellcheck}),s==="bottom"&&i.jsx(Q,{editor:R,position:s,sticky:F,floating:I,readonly:t.readonly,showMoreOptions:N,itemsOverride:t.toolbar.items}),i.jsx(Me,{editor:R,isEnabled:I,viewportOnlyScan:t.performance.viewportOnlyScan,readonly:t.readonly}),t.statusbar.enabled&&i.jsx("div",{ref:d,className:"editora-statusbar-container",style:{order:t.statusbar.position==="top"?-1:1}})]})})},ve=e=>i.jsx(Fe,{...e});function He(e={}){const t=c.useRef(null),f=c.useRef(e.onCommand);return c.useEffect(()=>{f.current=e.onCommand}),c.useEffect(()=>{if(typeof window>"u"||e.enabled===!1)return;const l=new O.KeyboardShortcutManager(e);t.current=l;const r=h=>l.handleKeyDown(h,(u,g)=>{f.current&&f.current(u,g),typeof window<"u"&&window.executeEditorCommand&&window.executeEditorCommand(u,g)}),o=e.editorElement||document;return o&&o.addEventListener("keydown",r),()=>{o&&o.removeEventListener("keydown",r)}},[e.editorElement,e.enabled,e.shortcuts,e.customShortcuts]),{getShortcuts:()=>t.current?.getAllShortcuts()||[],getShortcutForCommand:l=>t.current?.getShortcutForCommand(l),getShortcutsHelp:()=>t.current?.getShortcutsHelp()||"",enable:()=>t.current?.enable(),disable:()=>t.current?.disable(),isEnabled:()=>t.current?.isEnabled()||!1}}exports.EditorContent=me;exports.EditoraEditor=ve;exports.InlineMenu=ue;exports.RichTextEditor=ve;exports.Toolbar=Q;exports.mergeConfig=he;exports.useKeyboardShortcuts=He;

@@ -1,55 +0,56 @@

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 = ({
import { jsx as d, jsxs as U, Fragment as J } from "react/jsx-runtime";
import ke, { useRef as T, useState as j, useLayoutEffect as Se, useEffect as z, useMemo as ee } from "react";
import { KeyboardShortcutManager as ge, PluginManager as Le, Editor as Ae, StatusBar as xe, calculateTextStats as Te, countLines as Me, getCursorPosition as Re, getSelectionInfo as Ie } from "@editora/core";
const Ne = ({
isOpen: e,
options: t,
onSelect: m,
onClose: s,
anchorRef: i,
className: r = ""
onSelect: u,
onClose: i,
anchorRef: r,
className: o = ""
}) => {
const g = E(null), [d, h] = N({ top: 0, left: 0 });
return A(() => {
if (e && i.current) {
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 });
const b = T(null), [h, c] = j(null), m = () => {
if (!e || !r.current) return;
const s = r.current.getBoundingClientRect(), x = b.current?.getBoundingClientRect(), L = x?.width || 120, N = x?.height || t.length * 36, l = 8, B = 4, D = window.innerWidth, p = window.innerHeight;
let w = s.bottom + B, a = s.left;
a + L > D - l && (a = D - L - l), a < l && (a = l), w + N > p - l && (w = s.top - N - B), w < l && (w = l), c({ top: w, left: a });
};
return Se(() => {
if (!e) {
c(null);
return;
}
}, [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]), 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();
m();
const s = window.requestAnimationFrame(m);
return () => {
window.cancelAnimationFrame(s);
};
return e && (document.addEventListener("mousedown", o), document.addEventListener("keydown", u)), () => {
document.removeEventListener("mousedown", o), document.removeEventListener("keydown", u);
}, [e, t.length, r]), z(() => {
if (!e) return;
const s = () => {
m();
};
}, [e, s, i]), e ? /* @__PURE__ */ l(
return window.addEventListener("resize", s), window.addEventListener("scroll", s, !0), () => {
window.removeEventListener("resize", s), window.removeEventListener("scroll", s, !0);
};
}, [e, t.length, r]), z(() => {
const s = (L) => {
b.current && !b.current.contains(L.target) && r.current && !r.current.contains(L.target) && i();
}, x = (L) => {
L.key === "Escape" && i();
};
return e && (document.addEventListener("mousedown", s), document.addEventListener("keydown", x)), () => {
document.removeEventListener("mousedown", s), document.removeEventListener("keydown", x);
};
}, [e, i, r]), e ? /* @__PURE__ */ d(
"div",
{
ref: g,
className: `rte-inline-menu ${r}`,
ref: b,
className: `rte-inline-menu ${o}`,
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"
top: h?.top ?? -9999,
left: h?.left ?? -9999,
visibility: h ? "visible" : "hidden"
},
children: t.map((o) => /* @__PURE__ */ l(
children: t.map((s) => /* @__PURE__ */ d(
"div",

@@ -59,88 +60,179 @@ {

onClick: () => {
m(o.value), s();
u(s.value), i();
},
style: {
padding: "8px 12px",
cursor: "pointer",
borderBottom: "1px solid #f0f0f0",
fontSize: "14px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis"
},
onMouseEnter: (u) => {
u.currentTarget.style.backgroundColor = "#f5f5f5";
},
onMouseLeave: (u) => {
u.currentTarget.style.backgroundColor = "transparent";
},
children: o.label
children: s.label
},
o.value
s.value
))
}
) : null;
}, V = ({
}, G = (e) => e.toLowerCase().replace(/[^a-z0-9]/g, ""), De = {
undo: "undo",
redo: "redo",
bold: "toggleBold",
italic: "toggleItalic",
underline: "toggleUnderline",
strikethrough: "toggleStrikethrough",
textcolor: "openTextColorPicker",
backgroundcolor: "openBackgroundColorPicker",
fontsize: "setFontSize",
increasefontsize: "increaseFontSize",
decreasefontsize: "decreaseFontSize",
heading: "setHeading",
paragraph: "setHeading",
textalignment: "setTextAlignment",
direction: "setDirectionLTR",
bullist: "toggleBulletList",
numlist: "toggleOrderedList",
checklist: "toggleChecklist",
indent: "increaseIndent",
outdent: "decreaseIndent",
link: "openLinkDialog",
image: "insertImage",
video: "insertVideo",
table: "insertTable",
clearformatting: "clearFormatting"
}, He = (e, t) => {
if (!Array.isArray(t) || t.length === 0)
return e;
if (!t.every((c) => typeof c == "string"))
return t;
const i = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
e.forEach((c) => {
i.set(G(c.command || ""), c), r.set(G(c.label || ""), c);
});
const o = t.flatMap((c) => c.split(/\s+/)).map((c) => c.trim()).filter(Boolean), b = [];
let h = 0;
return o.forEach((c) => {
if (c === "|") {
h += 1, b.push({
type: "separator",
command: `__separator__${h}`,
label: "|"
});
return;
}
const m = G(c), s = De[m], x = i.get(m) || (s ? i.get(G(s)) : void 0) || r.get(m) || e.find(
(L) => G(L.command || "").includes(m)
);
x && b.push(x);
}), b.length > 0 ? b : e;
}, de = ({
editor: e,
position: t = "top",
sticky: m = !1,
floating: s = !1
sticky: u = !1,
floating: i = !1,
readonly: r = !1,
showMoreOptions: o = !0,
itemsOverride: b
}) => {
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 [h, c] = j(null), [m, s] = j(null), [x, L] = j(null), [N, l] = j(!1), B = T(null), D = T(null), p = T({}), w = T([]), a = T(null), A = T(null), M = T(null), v = ee(
() => He(e.pluginManager.getToolbarItems(), b),
[e, b]
), k = (n) => {
B.current = n, n && !n.collapsed && (D.current = n);
}, C = () => a.current?.closest("[data-editora-editor]")?.querySelector(".rte-content") || null, R = () => {
if (typeof window > "u") return;
const n = a.current?.closest("[data-editora-editor]");
window.__editoraCommandEditorRoot = n || null;
}, f = () => {
const n = C();
if (!n) return null;
const g = window.getSelection();
if (!g || g.rangeCount === 0) return null;
const S = g.getRangeAt(0);
return n.contains(S.commonAncestorContainer) ? S.cloneRange() : null;
}, y = () => {
const n = f();
n && k(n);
};
z(() => {
const n = () => {
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 $ = p.current.children;
for (let z = 0; z < $.length; z++) {
const K = $[z].offsetWidth + U;
if (q + K <= Z)
q += K, P++;
y();
};
return document.addEventListener("selectionchange", n), () => {
document.removeEventListener("selectionchange", n);
};
}, []);
const F = (n) => [
"toggleBold",
"toggleItalic",
"toggleUnderline",
"toggleStrikethrough",
"openTextColorPicker",
"openBackgroundColorPicker",
"openLinkDialog",
"removeLink",
"toggleCode"
].includes(n), W = (n = !1) => {
const g = C();
if (!g) return !1;
const S = window.getSelection();
if (!S) return !1;
const E = S.rangeCount > 0 && g.contains(S.getRangeAt(0).commonAncestorContainer), I = n ? D.current || B.current : B.current || D.current;
if (n && I && I.collapsed)
return !1;
if (I && g.contains(I.commonAncestorContainer))
try {
return g.focus({ preventScroll: !0 }), S.removeAllRanges(), S.addRange(I), !0;
} catch {
}
return E;
};
z(() => {
if (!o) {
L(null), l(!1), w.current = [];
return;
}
let n = null;
const g = () => {
if (!a.current || !A.current) return;
const I = a.current.clientWidth, Q = 16, ye = 40, ae = 4, Ee = Math.max(0, I - Q - ye - ae);
let ie = 0, le = 0;
const Y = A.current.children;
for (let q = 0; q < Y.length; q++) {
const Z = Y[q].getBoundingClientRect().width;
Z > 0 && (w.current[q] = Z);
const se = w.current[q] ?? Z, ue = (se > 0 ? se : 40) + ae;
if (ie + ue <= Ee)
ie += ue, le++;
else
break;
}
v(Math.max(1, P));
}, a = requestAnimationFrame(() => {
n();
}), k = new ResizeObserver(() => {
n();
const ce = Math.max(1, Math.min(le, Y.length));
L((q) => q === ce ? q : ce);
}, S = () => {
n !== null && cancelAnimationFrame(n), n = requestAnimationFrame(g);
};
w.current = [], S();
const E = new ResizeObserver(() => {
S();
});
b.current && k.observe(b.current);
const M = new MutationObserver(() => {
n();
});
return p.current && M.observe(p.current, {
childList: !0,
subtree: !0
}), () => {
cancelAnimationFrame(a), k.disconnect(), M.disconnect();
return a.current && E.observe(a.current), A.current && E.observe(A.current), () => {
n !== null && cancelAnimationFrame(n), E.disconnect();
};
}, [w.length]);
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(h)), o(null);
}, [v.length, o]), z(() => {
N && x !== null && x >= v.length && l(!1);
}, [N, x, v.length]);
const P = (n) => (p.current[n] || (p.current[n] = ke.createRef()), p.current[n]), H = (n, g) => {
if (r) return;
R(), n === "addComment" || n === "toggleComments" || W(F(n));
const I = {
toggleBold: "bold",
toggleItalic: "italic",
toggleUnderline: "underline"
}[n];
if (I) {
document.execCommand(I, !1), c(null);
return;
}
typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(n, a), r(null);
const W = k?.querySelector(".rte-content");
W && W.focus();
}, T = (n) => {
const a = window.getSelection();
a && a.rangeCount > 0 && o(a.getRangeAt(0).cloneRange()), r(i === n ? null : n);
}, L = (n) => {
const a = window.getSelection();
a && a.rangeCount > 0 && o(a.getRangeAt(0).cloneRange()), d(g === n ? null : n), r(null);
}, I = (n, a) => {
if (h) {
const k = window.getSelection();
k && (k.removeAllRanges(), k.addRange(h)), o(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 (s)
return null;
const Q = {
...m && {
typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(n, g), c(null);
}, O = (n) => {
r || (y(), c(h === n ? null : n));
}, $ = (n) => {
r || (y(), s(m === n ? null : n), c(null));
}, _ = (n, g) => {
r || (W(), H(n, g), k(null), D.current = null, s(null));
}, V = (n, g) => n && n.startsWith("<svg") && n.endsWith("</svg>") ? /* @__PURE__ */ d("span", { dangerouslySetInnerHTML: { __html: n } }) : n && n.length === 1 && /^[BIUSH]$/.test(n) ? /* @__PURE__ */ d("span", { style: { fontWeight: "bold", fontSize: "14px", lineHeight: "1" }, children: n }) : n || "⚪", pe = {
...u && {
position: "sticky",

@@ -156,197 +248,260 @@ top: 0,

}
}, O = (n) => n.map((a, k) => /* @__PURE__ */ l(
"div",
{
className: "rte-toolbar-item",
style: {
display: u !== null && k >= u ? "none" : "flex"
},
children: a.type === "dropdown" ? /* @__PURE__ */ R("div", { className: "rte-toolbar-dropdown", children: [
/* @__PURE__ */ R(
}, re = o && x !== null && x < v.length, Ce = (n) => {
r || !n.target.closest(".rte-toolbar-button, .rte-toolbar-dropdown-item, .rte-toolbar-more-button") || (R(), y(), n.preventDefault());
}, oe = (n) => n.map((g, S) => {
const E = g.command || "";
return /* @__PURE__ */ d(
"div",
{
className: "rte-toolbar-item",
style: {
display: o && x !== null && S >= x ? "none" : "flex"
},
children: g.type === "separator" ? /* @__PURE__ */ d("div", { className: "rte-toolbar-separator", "aria-hidden": "true" }) : g.type === "dropdown" ? /* @__PURE__ */ U("div", { className: "rte-toolbar-dropdown", children: [
/* @__PURE__ */ U(
"button",
{
className: "rte-toolbar-button",
"data-command": E,
"data-active": "false",
onMouseDown: (I) => {
I.preventDefault(), y();
},
onClick: () => O(E),
disabled: r,
children: [
g.label,
" ▼"
]
}
),
h === E && /* @__PURE__ */ d("div", { className: "rte-toolbar-dropdown-menu", children: g.options?.map((I) => /* @__PURE__ */ d(
"div",
{
className: "rte-toolbar-dropdown-item",
onMouseDown: (Q) => Q.preventDefault(),
onClick: () => H(E, I.value),
children: I.label
},
I.value
)) })
] }) : g.type === "inline-menu" ? /* @__PURE__ */ d(
"button",
{
ref: P(E),
className: "rte-toolbar-button",
"data-command": a.command,
"data-command": E,
"data-active": "false",
onClick: () => T(a.command),
children: [
a.label,
" ▼"
]
onMouseDown: (I) => {
I.preventDefault(), y();
},
onClick: () => $(E),
disabled: r,
title: g.label,
children: V(g.icon)
}
),
i === a.command && /* @__PURE__ */ l("div", { className: "rte-toolbar-dropdown-menu", children: a.options?.map((M) => /* @__PURE__ */ l(
) : g.type === "input" ? /* @__PURE__ */ d(
"input",
{
type: "text",
className: `rte-toolbar-input ${g.label.toLowerCase().replace(/\s+/g, "-")}`,
placeholder: g.placeholder,
onChange: (I) => H(E, I.target.value),
disabled: r,
onKeyDown: (I) => {
I.key === "Enter" && H(
E,
I.target.value
);
},
title: g.label
}
) : g.type === "group" ? /* @__PURE__ */ d(
"div",
{
className: "rte-toolbar-dropdown-item",
onClick: () => x(a.command, M.value),
children: M.label
},
M.value
)) })
] }) : a.type === "inline-menu" ? /* @__PURE__ */ l(
"button",
{
ref: S(a.command),
className: "rte-toolbar-button",
"data-command": a.command,
"data-active": "false",
onClick: () => L(a.command),
title: a.label,
children: D(a.icon, a.command)
}
) : a.type === "input" ? /* @__PURE__ */ l(
"input",
{
type: "text",
className: `rte-toolbar-input ${a.label.toLowerCase().replace(/\s+/g, "-")}`,
placeholder: a.placeholder,
onChange: (M) => x(a.command, M.target.value),
onKeyDown: (M) => {
M.key === "Enter" && x(
a.command,
M.target.value
);
},
title: a.label
}
) : a.type === "group" ? /* @__PURE__ */ l(
"div",
{
className: `rte-toolbar-group-button ${a.label.toLowerCase().replace(/\s+/g, "-")}`,
title: `${a.label}`,
children: /* @__PURE__ */ l(
"div",
{
className: `rte-toolbar-group-items ${a.label.toLowerCase().replace(/\s+/g, "-")}`,
children: O(a.items || [])
}
)
}
) : /* @__PURE__ */ l(
"button",
{
className: "rte-toolbar-button",
"data-command": a.command,
"data-active": "false",
onClick: () => x(a.command),
title: a.label,
children: D(a.icon, a.command)
}
)
},
k
));
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(
className: `rte-toolbar-group-button ${g.label.toLowerCase().replace(/\s+/g, "-")}`,
title: `${g.label}`,
children: /* @__PURE__ */ d(
"div",
{
className: `rte-toolbar-group-items ${g.label.toLowerCase().replace(/\s+/g, "-")}`,
children: oe(g.items || [])
}
)
}
) : /* @__PURE__ */ d(
"button",
{
ref: y,
className: `rte-toolbar-more-button ${C ? "active" : ""}`,
onClick: () => c(!C),
title: "Show more options",
"aria-label": "More toolbar options",
children: "☰"
className: "rte-toolbar-button",
"data-command": E,
"data-active": "false",
onMouseDown: (I) => {
I.preventDefault(), y();
},
onClick: () => H(E),
disabled: r,
title: g.label,
children: V(g.icon)
}
)
] }),
u !== null && u < w.length && /* @__PURE__ */ l(
"div",
{
className: `rte-toolbar-expanded-row ${C ? "show" : ""}`,
children: w.map(
(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",
{
className: "rte-toolbar-button",
"data-command": n.command,
"data-active": "false",
onClick: () => T(n.command),
children: [
n.label,
" ▼"
]
}
),
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: () => x(n.command, k.value),
children: k.label
},
k.value
)) })
] }) : n.type === "inline-menu" ? /* @__PURE__ */ l(
"button",
},
S
);
});
return /* @__PURE__ */ U(J, { children: [
/* @__PURE__ */ U(
"div",
{
className: "rte-toolbar-wrapper",
style: pe,
onMouseDownCapture: Ce,
children: [
/* @__PURE__ */ U("div", { className: "rte-toolbar", ref: a, children: [
/* @__PURE__ */ d(
"div",
{
ref: S(n.command),
className: "rte-toolbar-button",
"data-command": n.command,
"data-active": "false",
onClick: () => L(n.command),
title: n.label,
children: D(n.icon, n.command)
className: "rte-toolbar-items-container",
ref: A,
style: o ? void 0 : { flexWrap: "wrap" },
children: oe(v)
}
) : n.type === "input" ? /* @__PURE__ */ l(
"input",
),
re && /* @__PURE__ */ d(
"button",
{
type: "text",
className: "rte-toolbar-input",
placeholder: n.placeholder,
onChange: (k) => x(n.command, k.target.value),
onKeyDown: (k) => {
k.key === "Enter" && x(
n.command,
k.target.value
);
ref: M,
className: `rte-toolbar-more-button ${N ? "active" : ""}`,
onMouseDown: (n) => {
n.preventDefault(), y();
},
title: n.label
onClick: () => l(!N),
disabled: r,
title: "Show more options",
"aria-label": "More toolbar options",
children: "☰"
}
) : /* @__PURE__ */ l(
"button",
{
className: "rte-toolbar-button",
"data-command": n.command,
"data-active": "false",
onClick: () => x(n.command),
title: n.label,
children: D(n.icon, n.command)
}
) }, a)
)
] }),
re && /* @__PURE__ */ d(
"div",
{
className: `rte-toolbar-expanded-row ${N ? "show" : ""}`,
children: v.map(
(n, g) => {
if (g < (x || 0)) return null;
const S = n.command || "";
return /* @__PURE__ */ d("div", { className: "rte-toolbar-item", children: n.type === "separator" ? /* @__PURE__ */ d("div", { className: "rte-toolbar-separator", "aria-hidden": "true" }) : n.type === "dropdown" ? /* @__PURE__ */ U("div", { className: "rte-toolbar-dropdown", children: [
/* @__PURE__ */ U(
"button",
{
className: "rte-toolbar-button",
"data-command": S,
"data-active": "false",
onMouseDown: (E) => {
E.preventDefault(), y();
},
onClick: () => O(S),
disabled: r,
children: [
n.label,
" ▼"
]
}
),
h === S && /* @__PURE__ */ d("div", { className: "rte-toolbar-dropdown-menu", children: n.options?.map((E) => /* @__PURE__ */ d(
"div",
{
className: "rte-toolbar-dropdown-item",
onMouseDown: (I) => I.preventDefault(),
onClick: () => H(S, E.value),
children: E.label
},
E.value
)) })
] }) : n.type === "inline-menu" ? /* @__PURE__ */ d(
"button",
{
ref: P(S),
className: "rte-toolbar-button",
"data-command": S,
"data-active": "false",
onMouseDown: (E) => {
E.preventDefault(), y();
},
onClick: () => $(S),
disabled: r,
title: n.label,
children: V(n.icon)
}
) : n.type === "input" ? /* @__PURE__ */ d(
"input",
{
type: "text",
className: "rte-toolbar-input",
placeholder: n.placeholder,
onChange: (E) => H(S, E.target.value),
disabled: r,
onKeyDown: (E) => {
E.key === "Enter" && H(
S,
E.target.value
);
},
title: n.label
}
) : /* @__PURE__ */ d(
"button",
{
className: "rte-toolbar-button",
"data-command": S,
"data-active": "false",
onMouseDown: (E) => {
E.preventDefault(), y();
},
onClick: () => H(S),
disabled: r,
title: n.label,
children: V(n.icon)
}
) }, g);
}
)
}
)
}
)
] }),
w.map((n) => n.type === "inline-menu" ? /* @__PURE__ */ l(
ce,
{
isOpen: g === n.command,
options: n.options || [],
onSelect: (a) => I(n.command, a),
onClose: () => d(null),
anchorRef: S(n.command)
},
`menu-${n.command}`
) : null)
]
}
),
v.map((n) => {
if (n.type === "inline-menu") {
const g = n.command || "";
return /* @__PURE__ */ d(
Ne,
{
isOpen: m === g,
options: n.options || [],
onSelect: (S) => _(g, S),
onClose: () => s(null),
anchorRef: P(g)
},
`menu-${g || "unknown"}`
);
}
return null;
})
] });
};
function se(e, t) {
const m = E(), s = E("");
return A(() => {
function Be(e, t) {
const u = T(), i = T("");
return z(() => {
if (!t?.enabled) return;
const r = t.intervalMs || 3e4, g = t.storageKey || "rte-autosave", d = t.provider || "localStorage", h = async () => {
const o = e();
if (o !== s.current) {
if (s.current = o, d === "localStorage")
const o = t.intervalMs || 3e4, b = t.storageKey || "rte-autosave", h = t.provider || "localStorage", c = async () => {
const m = e();
if (m !== i.current) {
if (i.current = m, h === "localStorage")
try {
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);
localStorage.setItem(b, m), localStorage.setItem(`${b}-timestamp`, Date.now().toString()), console.log("[Autosave] Content saved to localStorage");
} catch (s) {
console.error("[Autosave] Failed to save to localStorage:", s);
}
else if (d === "api" && t.apiUrl)
else if (h === "api" && t.apiUrl)
try {

@@ -358,22 +513,22 @@ await fetch(t.apiUrl, {

},
body: JSON.stringify({ content: o, timestamp: Date.now() })
body: JSON.stringify({ content: m, timestamp: Date.now() })
}), console.log("[Autosave] Content saved to API");
} catch (u) {
console.error("[Autosave] Failed to save to API:", u);
} catch (s) {
console.error("[Autosave] Failed to save to API:", s);
}
}
};
return m.current = setInterval(h, r), () => {
m.current && clearInterval(m.current);
return u.current = setInterval(c, o), () => {
u.current && clearInterval(u.current);
};
}, [t?.enabled, t?.intervalMs, t?.storageKey, t?.provider, t?.apiUrl, e]), { restore: () => {
if (!t?.enabled) return null;
const r = t.storageKey || "rte-autosave";
const o = t.storageKey || "rte-autosave";
if ((t.provider || "localStorage") === "localStorage")
try {
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);
const h = localStorage.getItem(o), c = localStorage.getItem(`${o}-timestamp`);
if (h && c)
return console.log("[Autosave] Restored from localStorage, saved at:", new Date(parseInt(c))), h;
} catch (h) {
console.error("[Autosave] Failed to restore from localStorage:", h);
}

@@ -383,3 +538,3 @@ return null;

}
const de = [
const Fe = [
"p",

@@ -391,2 +546,4 @@ "br",

"s",
"strike",
"del",
"b",

@@ -421,3 +578,3 @@ "i",

"hr"
], ue = {
], ze = {
"*": ["class", "style", "id", "data-*"],

@@ -432,134 +589,184 @@ a: ["href", "target", "rel", "title"],

};
function G(e, t, m) {
function be(e, t, u) {
if (t?.sanitize === !1)
return e;
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;
const i = t?.allowedTags && t.allowedTags.length > 0 ? t.allowedTags : Fe, o = !!t?.allowedAttributes && Object.keys(t.allowedAttributes).length > 0 ? t.allowedAttributes : ze, b = document.createElement("div");
return b.innerHTML = e, he(b, i, o), b.innerHTML;
}
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, g = r.tagName.toLowerCase();
if (!t.includes(g)) {
for (; r.firstChild; )
e.insertBefore(r.firstChild, r);
e.removeChild(r);
function he(e, t, u) {
const i = Array.from(e.childNodes);
for (const r of i)
if (r.nodeType === Node.ELEMENT_NODE) {
const o = r, b = o.tagName.toLowerCase();
if (!t.includes(b)) {
for (; o.firstChild; )
e.insertBefore(o.firstChild, o);
e.removeChild(o);
continue;
}
fe(r, m), X(r, t, m);
We(o, u), he(o, t, u);
} else {
if (i.nodeType === Node.TEXT_NODE)
if (r.nodeType === Node.TEXT_NODE)
continue;
e.removeChild(i);
e.removeChild(r);
}
}
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;
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;
function We(e, t) {
const u = e.tagName.toLowerCase(), i = Array.from(e.attributes), r = t[u] || [], o = t["*"] || [], b = [...r, ...o];
for (const h of i) {
const c = h.name.toLowerCase();
let m = !1;
b.includes(c) && (m = !0);
for (const s of b)
if (s.endsWith("*")) {
const x = s.slice(0, -1);
if (c.startsWith(x)) {
m = !0;
break;
}
}
(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);
(c.startsWith("on") || // Event handlers
c === "javascript:" || c === "href" && h.value.trim().toLowerCase().startsWith("javascript:") || c === "src" && h.value.trim().toLowerCase().startsWith("javascript:")) && (m = !1), m || e.removeAttribute(h.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 me(e, t, m) {
return m?.sanitizeOnPaste === !1 ? e : G(e, t);
function Pe(e, t, u) {
return u?.sanitizeOnPaste === !1 ? e : be(e, t);
}
function ge(e, t, m) {
return m?.sanitizeOnInput === !1 ? e : G(e, t);
function Oe(e, t, u) {
return u?.sanitizeOnInput === !1 ? e : be(e, t);
}
const be = ({
const X = (e) => (e.textContent || "").replace(/\u200B/g, "").trim().length > 0 ? !1 : !e.querySelector("img, video, table, iframe, hr, pre, blockquote, ul, ol"), K = (e, t) => {
const i = !!t && X(e);
e.classList.toggle("rte-content-empty", i);
}, Ue = ({
editor: e,
defaultValue: t,
value: m,
onChange: s,
pasteConfig: i,
contentConfig: r,
securityConfig: g,
performanceConfig: d,
autosaveConfig: h
value: u,
readonly: i = !1,
placeholder: r,
onChange: o,
pasteConfig: b,
contentConfig: h,
securityConfig: c,
performanceConfig: m,
accessibilityConfig: s,
autosaveConfig: x,
contextMenuConfig: L,
spellcheckConfig: N
}) => {
const o = E(null), u = m !== void 0, v = E(), { restore: C } = se(
() => o.current?.innerHTML || "",
h
const l = T(null), B = u !== void 0, D = T(), { restore: p } = Be(
() => l.current?.innerHTML || "",
x
);
return A(() => {
if (!o.current) return;
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 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)
z(() => {
if (!l.current) return;
const a = p(), A = a ?? u ?? t ?? "";
A.trim() ? l.current.innerHTML !== A && (l.current.innerHTML = A) : r ? l.current.innerHTML = "" : l.current.innerHTML.trim() || (l.current.innerHTML = "<p><br></p>"), K(l.current, r), a && o && o(a);
}, []), z(() => {
!l.current || !B || (u !== l.current.innerHTML && (l.current.innerHTML = u), K(l.current, r));
}, [u, B]), z(() => {
if (!l.current) return;
const a = l.current;
if (r) {
a.setAttribute("data-placeholder", r), X(a) && (a.innerHTML = ""), K(a, r);
return;
}
a.removeAttribute("data-placeholder"), K(a, r);
}, [r]), z(() => {
if (!l.current) return;
const a = l.current;
if (s?.enableARIA !== !1) {
a.setAttribute("role", "textbox"), a.setAttribute("aria-multiline", "true"), a.setAttribute("aria-disabled", i ? "true" : "false");
const M = r?.trim();
M ? a.setAttribute("aria-label", M) : a.removeAttribute("aria-label");
} else
a.removeAttribute("role"), a.removeAttribute("aria-multiline"), a.removeAttribute("aria-label"), a.removeAttribute("aria-disabled");
}, [s?.enableARIA, r, i]), z(() => {
if (!l.current) return;
const a = () => {
if (!l.current || i) return;
r && X(l.current) && (l.current.innerHTML = "");
let R = l.current.innerHTML;
if (c?.sanitizeOnInput !== !1 && h?.sanitize !== !1 && (R = Oe(R, h, c), R !== l.current.innerHTML)) {
const f = window.getSelection(), y = f && f.rangeCount > 0 ? f.getRangeAt(0) : null;
if (l.current.innerHTML = R, y && f)
try {
w.removeAllRanges(), w.addRange(S);
f.removeAllRanges(), f.addRange(y);
} catch {
}
}
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) {
S && document.execCommand("insertText", !1, S);
K(l.current, r), o && (m?.debounceInputMs ? (D.current && clearTimeout(D.current), D.current = setTimeout(() => {
o(R);
}, m.debounceInputMs)) : o(R));
}, A = (R) => {
if (i) {
R.preventDefault();
return;
}
if (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 (; L.firstChild; )
I.appendChild(L.firstChild);
T.insertNode(I), T.collapse(!1), x.removeAllRanges(), x.addRange(T);
R.preventDefault();
let f = R.clipboardData?.getData("text/html");
const y = R.clipboardData?.getData("text/plain"), F = !!f && /class=["'][^"']*Mso|xmlns:w=|urn:schemas-microsoft-com:office/i.test(f);
if (b?.clean || !b?.keepFormatting) {
y && document.execCommand("insertText", !1, y);
return;
}
if (b?.convertWord === !1 && F) {
y && document.execCommand("insertText", !1, y);
return;
}
if (f) {
c?.sanitizeOnPaste !== !1 && h?.sanitize !== !1 && (f = Pe(f, h, c));
const W = window.getSelection();
if (W && W.rangeCount > 0) {
const P = W.getRangeAt(0);
P.deleteContents();
const H = document.createElement("div");
H.innerHTML = f;
const O = document.createDocumentFragment();
for (; H.firstChild; )
O.appendChild(H.firstChild);
P.insertNode(O), P.collapse(!1), W.removeAllRanges(), W.addRange(P);
}
} 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");
}, 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);
} else y && document.execCommand("insertText", !1, y);
}, M = (R) => {
const f = R.target;
(f.tagName === "IMG" || f.tagName === "VIDEO") && (f.style.resize = "both", f.style.overflow = "auto", f.style.display = "inline-block");
}, v = (R) => {
L?.enabled === !1 && R.preventDefault();
}, k = () => {
l.current && (r && X(l.current) && (l.current.innerHTML = ""), K(l.current, r));
}, C = l.current;
return C.addEventListener("input", a), C.addEventListener("paste", A), C.addEventListener("click", M), C.addEventListener("contextmenu", v), C.addEventListener("focus", k), C.addEventListener("blur", k), i || C.focus(), () => {
D.current && clearTimeout(D.current), C.removeEventListener("input", a), C.removeEventListener("paste", A), C.removeEventListener("click", M), C.removeEventListener("contextmenu", v), C.removeEventListener("focus", k), C.removeEventListener("blur", k);
};
}, [e, s, i, r, g, d]), A(() => {
if (!o.current || typeof window > "u") return;
const c = new _(), f = o.current, b = (p) => {
c.handleKeyDown(p, (y, w) => {
typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(y, w);
}, [e, o, b, h, c, m, r, L, i]);
const w = (N?.enabled ?? !1) && (N?.provider ?? "browser") === "browser";
return z(() => {
if (!l.current || typeof window > "u" || i || s?.keyboardNavigation === !1)
return;
const a = new ge(), A = l.current, M = (v) => {
a.handleKeyDown(v, (k, C) => {
if (typeof window < "u" && window.executeEditorCommand) {
const R = l.current?.closest("[data-editora-editor]");
window.__editoraCommandEditorRoot = R || null, window.executeEditorCommand(k, C);
}
});
};
return f.addEventListener("keydown", b), () => {
f.removeEventListener("keydown", b);
return A.addEventListener("keydown", M), () => {
A.removeEventListener("keydown", M);
};
}, []), /* @__PURE__ */ l(
}, [s?.keyboardNavigation, i]), /* @__PURE__ */ d(
"div",
{
ref: o,
contentEditable: !0,
ref: l,
contentEditable: !i,
suppressContentEditableWarning: !0,
className: "rte-content",
spellCheck: i ? !1 : w,
tabIndex: s?.keyboardNavigation === !1 ? -1 : 0,
"aria-keyshortcuts": s?.keyboardNavigation === !1 ? void 0 : "Ctrl+B Ctrl+I Ctrl+U Ctrl+Z Ctrl+Y",
"data-viewport-only-scan": m?.viewportOnlyScan ? "true" : "false",
"data-a11y-checker": s?.checker ? "true" : "false",
"data-readonly": i ? "true" : "false",
className: `rte-content ${i ? "rte-content-readonly" : ""}`,
style: {

@@ -579,54 +786,94 @@ minHeight: "200px",

overflowWrap: "break-word"
},
children: /* @__PURE__ */ l("p", { children: /* @__PURE__ */ l("br", {}) })
}
}
);
}, he = ({
}, _e = ({
editor: e,
isEnabled: t
isEnabled: t,
viewportOnlyScan: u = !0,
readonly: i = !1
}) => {
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) {
s(!1);
const [r, o] = j(!1), [b, h] = j({ top: 0, left: 0 }), c = T(null), m = T(null), s = T(null), x = T(null), L = T(null);
z(() => {
if (!t || i) {
o(!1);
return;
}
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;
L.current = c.current?.closest("[data-editora-editor]");
const l = (v) => {
if (L.current) return L.current;
const k = c.current?.closest("[data-editora-editor]");
if (k)
return L.current = k, k;
const C = v?.commonAncestorContainer, f = (C ? C.nodeType === Node.ELEMENT_NODE ? C : C.parentElement : null)?.closest("[data-editora-editor]");
return f ? (L.current = f, f) : null;
}, B = (v) => v && v.querySelector(".rte-content, .editora-content") || null, D = (v) => {
if (!v.anchorNode || !v.focusNode) return !1;
try {
const k = document.createRange();
return k.setStart(v.anchorNode, v.anchorOffset), k.setEnd(v.focusNode, v.focusOffset), k.collapsed;
} catch {
return !1;
}
}, p = (v, k) => {
const C = Array.from(k.getClientRects()).filter((f) => f.width > 0 || f.height > 0);
return C.length === 0 ? k.getBoundingClientRect() : D(v) ? C[0] : C[C.length - 1];
}, w = () => {
x.current && clearTimeout(x.current);
const v = window.getSelection();
if (!v || v.rangeCount === 0) {
o(!1), s.current = null;
return;
}
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;
const k = v.getRangeAt(0);
if (k.collapsed) {
o(!1), s.current = null;
return;
}
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);
const C = v.toString().trim(), R = l(k), f = B(R);
if (!f || !f.contains(k.commonAncestorContainer)) {
o(!1), s.current = null;
return;
}
if (u) {
const y = f.getBoundingClientRect(), F = y.bottom >= 0 && y.top <= window.innerHeight, W = document.activeElement === f || f.contains(document.activeElement);
if (!F && !W) {
o(!1), s.current = null;
return;
}
}
if (C.length > 0) {
const y = p(v, k), F = f.getBoundingClientRect(), W = 300;
if (y && F) {
const P = Math.max(8, y.top - 50);
let H = y.left + y.width / 2;
const O = W / 2, $ = F.left, _ = F.right;
H - O < $ && (H = $ + O + 10), H + O > _ && (H = _ - O - 10), h({ top: P, left: H }), o(!0), s.current = k.cloneRange();
}
} else
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));
o(!1), s.current = null;
}, a = (v) => {
if (m.current && !m.current.contains(v.target)) {
const k = l();
window.getSelection(), B(k)?.contains(v.target) || (o(!1), s.current = null);
}
}, A = (v) => {
v.key === "Escape" && (o(!1), s.current = null);
}, M = B(l());
return document.addEventListener("selectionchange", w), document.addEventListener("mousedown", a), document.addEventListener("keydown", A), M?.addEventListener("mouseup", w), M?.addEventListener("keyup", w), () => {
document.removeEventListener("selectionchange", w), document.removeEventListener("mousedown", a), document.removeEventListener("keydown", A), M?.removeEventListener("mouseup", w), M?.removeEventListener("keyup", w), x.current && clearTimeout(x.current);
};
return document.addEventListener("selectionchange", v), document.addEventListener("mousedown", C), document.addEventListener("keydown", (c) => {
c.key === "Escape" && (s(!1), d.current = null);
}), () => {
document.removeEventListener("selectionchange", v), document.removeEventListener("mousedown", C), h.current && clearTimeout(h.current);
};
}, [t]);
const u = (v, C) => {
if (!d.current) return;
const c = o.current?.querySelector(".rte-content");
c && c.focus(), {
}, [t, u, i]);
const N = (l, B) => {
if (i || !s.current) return;
typeof window < "u" && (window.__editoraCommandEditorRoot = L.current || null);
const D = L.current?.querySelector(".rte-content");
D && D.focus();
const p = window.getSelection();
if (p && s.current)
try {
p.removeAllRanges(), p.addRange(s.current);
} catch {
}
({
toggleBold: () => document.execCommand("bold", !1),

@@ -643,134 +890,183 @@ toggleItalic: () => document.execCommand("italic", !1),

toggleCode: () => {
const b = window.getSelection();
if (b && b.rangeCount > 0) {
const p = b.getRangeAt(0), y = document.createElement("code");
p.surroundContents(y);
const a = window.getSelection();
if (a && a.rangeCount > 0) {
const A = a.getRangeAt(0), M = document.createElement("code");
A.surroundContents(M);
}
},
setBlockType: () => {
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");
if (B === "blockquote") {
const a = window.getSelection();
if (a && a.rangeCount > 0) {
const A = a.getRangeAt(0);
(A.commonAncestorContainer.nodeType === Node.TEXT_NODE ? A.commonAncestorContainer.parentElement : A.commonAncestorContainer)?.closest?.("blockquote") ? document.execCommand("formatBlock", !1, "p") : document.execCommand("formatBlock", !1, "blockquote");
}
} else C && document.execCommand("formatBlock", !1, C);
} else B && document.execCommand("formatBlock", !1, B);
}
}[v]?.(), s(!1), d.current = null, c && c.focus();
})[l]?.(), o(!1), s.current = null;
};
return !t || !m ? null : /* @__PURE__ */ R(
"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: [
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("toggleBold"),
title: "Bold (Ctrl+B)",
children: /* @__PURE__ */ l("strong", { children: "B" })
}
),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("toggleItalic"),
title: "Italic (Ctrl+I)",
children: /* @__PURE__ */ l("em", { children: "I" })
}
),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("toggleUnderline"),
title: "Underline (Ctrl+U)",
children: /* @__PURE__ */ l("u", { children: "U" })
}
),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("toggleStrikethrough"),
title: "Strikethrough",
children: /* @__PURE__ */ l("s", { children: "S" })
}
),
/* @__PURE__ */ l("div", { className: "floating-toolbar-separator" }),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("clearFormatting"),
title: "Clear Formatting",
children: "⌫"
}
),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("createLink"),
title: "Insert Link",
children: "🔗"
}
),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("toggleCode"),
title: "Code",
children: "Code"
}
),
/* @__PURE__ */ l("div", { className: "floating-toolbar-separator" }),
/* @__PURE__ */ l(
"button",
{
className: "floating-toolbar-btn",
onClick: () => u("setBlockType", "blockquote"),
title: "Quote",
children: "❝"
}
)
]
}
);
}, we = ({
return !t || i ? /* @__PURE__ */ d("span", { ref: c, style: { display: "none" }, "aria-hidden": "true" }) : /* @__PURE__ */ U(J, { children: [
/* @__PURE__ */ d("span", { ref: c, style: { display: "none" }, "aria-hidden": "true" }),
r && /* @__PURE__ */ U(
"div",
{
ref: m,
className: "floating-toolbar",
onMouseDown: (l) => l.preventDefault(),
style: {
position: "fixed",
top: `${b.top}px`,
left: `${b.left}px`,
transform: "translateX(-50%)",
zIndex: 1e4,
display: "flex"
},
children: [
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("toggleBold"),
title: "Bold (Ctrl+B)",
children: /* @__PURE__ */ d("strong", { children: "B" })
}
),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("toggleItalic"),
title: "Italic (Ctrl+I)",
children: /* @__PURE__ */ d("em", { children: "I" })
}
),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("toggleUnderline"),
title: "Underline (Ctrl+U)",
children: /* @__PURE__ */ d("u", { children: "U" })
}
),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("toggleStrikethrough"),
title: "Strikethrough",
children: /* @__PURE__ */ d("s", { children: "S" })
}
),
/* @__PURE__ */ d("div", { className: "floating-toolbar-separator" }),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("clearFormatting"),
title: "Clear Formatting",
children: "⌫"
}
),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("createLink"),
title: "Insert Link",
children: "🔗"
}
),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("toggleCode"),
title: "Code",
children: "Code"
}
),
/* @__PURE__ */ d("div", { className: "floating-toolbar-separator" }),
/* @__PURE__ */ d(
"button",
{
className: "floating-toolbar-btn",
onClick: () => N("setBlockType", "blockquote"),
title: "Quote",
children: "❝"
}
)
]
}
)
] });
}, qe = ({
plugins: e,
children: t
}) => {
const m = e.filter((i) => i.context?.provider);
return m.length === 0 ? /* @__PURE__ */ l(B, { children: t }) : m.reduce(
(i, r) => {
const g = r.context.provider;
return /* @__PURE__ */ l(g, { children: i }, r.name);
const u = e.filter((r) => r.context?.provider);
return u.length === 0 ? /* @__PURE__ */ d(J, { children: t }) : u.reduce(
(r, o) => {
const b = o.context.provider;
return /* @__PURE__ */ d(b, { children: r }, o.name);
},
/* @__PURE__ */ l(B, { children: t })
/* @__PURE__ */ d(J, { children: t })
);
}, ve = {
}, fe = /* @__PURE__ */ new Set(), me = /* @__PURE__ */ new Set(), te = (e) => !!e && typeof e == "object" && typeof e.name == "string", ve = (e) => {
const t = e?.pluginFactories;
return {
...(typeof window < "u" ? window.EditoraReactPlugins : void 0) || {},
...t || {}
};
}, $e = (e, t) => {
if (!Array.isArray(e)) return [];
const u = ve(t), i = [], r = [];
if (e.forEach((o) => {
if (te(o)) {
i.push(o);
return;
}
if (typeof o != "string") return;
const b = u[o];
if (typeof b == "function")
try {
const h = b();
if (te(h)) {
i.push(h);
return;
}
} catch {
}
r.push(o);
}), r.length > 0) {
const o = r.slice().sort().join("|");
fe.has(o) || (fe.add(o), console.warn(
`[Editora React] Unresolved string plugin names: ${r.join(
", "
)}. Pass plugin instances or provide plugin factories via "pluginConfig.pluginFactories" or "window.EditoraReactPlugins".`
));
}
return i;
}, Ve = (e, t, u) => {
if (!t?.checker || e.some((o) => o?.name === "a11yChecker")) return e;
const i = ve(u).a11yChecker;
if (typeof i == "function")
try {
const o = i();
if (te(o))
return [...e, o];
} catch {
}
const r = "accessibility.checker";
return me.has(r) || (me.add(r), console.warn(
'[Editora React] accessibility.checker=true requires an "a11yChecker" plugin instance or factory.'
)), e;
}, je = {
readonly: !1,
placeholder: "",
toolbar: {
items: [],
floating: !1,
sticky: !1
sticky: !1,
showMoreOptions: !0
},

@@ -843,12 +1139,14 @@ statusbar: {

};
function J(e, t) {
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);
function we(e, t) {
const u = { ...e };
for (const i in t) {
const r = t[i], o = u[i];
r !== void 0 && (typeof r == "object" && r !== null && !Array.isArray(r) && typeof o == "object" && o !== null && !Array.isArray(o) ? u[i] = we(o, r) : u[i] = r);
}
return m;
return u;
}
function pe(e) {
const t = J(ve, {
function Ke(e) {
const t = we(je, {
readonly: e.readonly,
placeholder: e.placeholder,
toolbar: e.toolbar,

@@ -869,6 +1167,10 @@ statusbar: e.statusbar,

});
return e.floatingToolbar !== void 0 && (t.toolbar = {
...t.toolbar,
floating: e.floatingToolbar.enabled ?? t.toolbar.floating
}), e.mediaConfig && (t.media = {
if (e.floatingToolbar !== void 0) {
const i = typeof e.floatingToolbar == "boolean" ? e.floatingToolbar : e.floatingToolbar.enabled;
t.toolbar = {
...t.toolbar,
floating: i ?? t.toolbar.floating
};
}
return e.mediaConfig && (t.media = {
...t.media,

@@ -888,15 +1190,19 @@ uploadUrl: e.mediaConfig.uploadUrl || t.media.uploadUrl,

onDestroy: e.onDestroy,
plugins: Array.isArray(e.plugins) ? e.plugins.filter((s) => typeof s != "string") : [],
plugins: Ve(
$e(e.plugins, e.pluginConfig),
e.accessibility,
e.pluginConfig
),
pluginConfig: e.pluginConfig || {}
};
}
const F = /* @__PURE__ */ new Map();
const ne = /* @__PURE__ */ new Map();
typeof window < "u" && (window.registerEditorCommand = (e, t) => {
F.set(e, t);
ne.set(e, t);
}, window.executeEditorCommand = (e, t) => {
const m = F.get(e);
return m ? m(t) : (console.warn(`No handler registered for command: ${e}`), !1);
const u = ne.get(e);
return u ? u(t) : (console.warn(`No handler registered for command: ${e}`), !1);
});
const ye = (e) => {
const t = j(() => pe(e), [
const Ge = (e) => {
const t = ee(() => Ke(e), [
e.id,

@@ -906,2 +1212,4 @@ e.className,

e.defaultValue,
e.readonly,
e.placeholder,
e.plugins,

@@ -923,40 +1231,49 @@ e.toolbar,

e.mediaConfig
]), 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;
]), u = T(null), i = T(null), r = T(e.onInit), o = T(e.onDestroy), b = T(e.onChange), h = T(/* @__PURE__ */ new Set()), c = T(null), m = T(null), s = T(null);
z(() => {
r.current = e.onInit, o.current = e.onDestroy, b.current = e.onChange;
});
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 x = (p) => {
b.current?.(p), h.current.forEach((w) => {
try {
w(p);
} catch (a) {
console.error("Editora onChange subscriber failed:", a);
}
});
}, L = ee(() => {
const p = new Le();
t.plugins.forEach((a) => {
p.register(a), a.commands && typeof window < "u" && Object.entries(a.commands).forEach(([A, M]) => {
ne.set(A, M);
});
});
const f = new ne(c);
return m.current = f, f;
const w = new Ae(p);
return u.current = w, w;
}, [t.plugins]);
A(() => {
const c = {
getHTML: () => g.current?.querySelector(".rte-content")?.innerHTML || "",
setHTML: (f) => {
const b = g.current?.querySelector(".rte-content");
b && (b.innerHTML = f);
z(() => {
const p = {
getHTML: () => c.current?.querySelector(".rte-content")?.innerHTML || "",
setHTML: (w) => {
const a = c.current?.querySelector(".rte-content");
a && (a.innerHTML = w);
},
execCommand: (f, b) => {
typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(f, b);
execCommand: (w, a) => {
typeof window < "u" && window.executeEditorCommand && (window.__editoraCommandEditorRoot = c.current || null, window.executeEditorCommand(w, a));
},
registerCommand: (f, b) => {
typeof window < "u" && window.registerEditorCommand && window.registerEditorCommand(f, b);
registerCommand: (w, a) => {
typeof window < "u" && window.registerEditorCommand && window.registerEditorCommand(w, a);
},
focus: () => {
g.current?.querySelector(".rte-content")?.focus();
c.current?.querySelector(".rte-content")?.focus();
},
blur: () => {
g.current?.querySelector(".rte-content")?.blur();
c.current?.querySelector(".rte-content")?.blur();
},
destroy: () => {
r.current && r.current();
o.current && o.current();
},
onChange: (f) => () => {
},
onChange: (w) => (h.current.add(w), () => {
h.current.delete(w);
}),
getState: () => ({

@@ -967,49 +1284,63 @@ plugins: t.plugins,

toolbar: {
items: o.toolbar?.items || []
items: L.toolbar?.items || []
}
};
return s.current = c, i.current && i.current(c), () => {
r.current && r.current();
return i.current = p, r.current && r.current(p), () => {
h.current.clear(), o.current && o.current();
};
}, []), A(() => {
if (t.statusbar.enabled && h.current && g.current) {
d.current || (d.current = new oe({
}, []), z(() => {
if (t.statusbar.enabled && s.current && c.current) {
m.current || (m.current = new xe({
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
}), m.current.create(s.current));
const p = c.current.querySelector(".rte-content");
if (p) {
const w = () => {
const f = document.activeElement;
return !!f && (f === p || p.contains(f));
}, a = () => {
const f = p.getBoundingClientRect();
return f.bottom >= 0 && f.top <= window.innerHeight;
}, A = () => {
const f = window.getSelection();
if (!f || f.rangeCount === 0) return null;
const y = f.getRangeAt(0), F = y.commonAncestorContainer;
return p.contains(F) ? y : null;
}, M = (f = !1) => {
if (t.performance.viewportOnlyScan !== !1 && !a() && !w())
return;
const F = A(), W = !!F || w();
if (f && !W)
return;
const P = p.textContent || "", { words: H, chars: O } = Te(P), $ = Me(p);
let _, V;
F && (_ = Re(p, F), F.collapsed || (V = Ie(F, _), _ = void 0)), m.current?.update({
wordCount: H,
charCount: O,
lineCount: $,
cursorPosition: _,
selectionInfo: V
});
}, v = () => M(), k = () => M(!0), C = () => M(), R = () => M();
return p.addEventListener("input", v), p.addEventListener("focus", C), p.addEventListener("blur", R), document.addEventListener("selectionchange", k), M(), () => {
p.removeEventListener("input", v), p.removeEventListener("focus", C), p.removeEventListener("blur", R), document.removeEventListener("selectionchange", k);
};
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);
m.current && (m.current.destroy(), m.current = null);
return () => {
d.current && (d.current.destroy(), d.current = null);
m.current && (m.current.destroy(), m.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(
}, [t.statusbar.enabled, t.statusbar.position, t.performance.viewportOnlyScan]);
const N = t.toolbar.floating ?? !1, l = t.toolbar.position || "top", B = t.toolbar.sticky ?? !1, D = t.toolbar.showMoreOptions ?? !0;
return /* @__PURE__ */ d(qe, { plugins: t.plugins, children: /* @__PURE__ */ U(
"div",
{
ref: g,
ref: c,
id: t.id,
"data-editora-editor": !0,
"data-readonly": t.readonly ? "true" : "false",
className: `rte-editor ${t.className || ""}`,
lang: t.language.locale,
dir: t.language.direction,

@@ -1022,18 +1353,23 @@ style: {

children: [
v !== "bottom" && /* @__PURE__ */ l(
V,
l !== "bottom" && /* @__PURE__ */ d(
de,
{
editor: o,
position: v,
sticky: C,
floating: u
editor: L,
position: l,
sticky: B,
floating: N,
readonly: t.readonly,
showMoreOptions: D,
itemsOverride: t.toolbar.items
}
),
/* @__PURE__ */ l(
be,
/* @__PURE__ */ d(
Ue,
{
editor: o,
editor: L,
defaultValue: t.defaultValue,
value: t.value,
onChange: t.onChange,
readonly: t.readonly,
placeholder: t.placeholder,
onChange: x,
pasteConfig: t.paste,

@@ -1043,25 +1379,33 @@ contentConfig: t.content,

performanceConfig: t.performance,
autosaveConfig: t.autosave
accessibilityConfig: t.accessibility,
autosaveConfig: t.autosave,
contextMenuConfig: t.contextMenu,
spellcheckConfig: t.spellcheck
}
),
v === "bottom" && /* @__PURE__ */ l(
V,
l === "bottom" && /* @__PURE__ */ d(
de,
{
editor: o,
position: v,
sticky: C,
floating: u
editor: L,
position: l,
sticky: B,
floating: N,
readonly: t.readonly,
showMoreOptions: D,
itemsOverride: t.toolbar.items
}
),
/* @__PURE__ */ l(
he,
/* @__PURE__ */ d(
_e,
{
editor: o,
isEnabled: u
editor: L,
isEnabled: N,
viewportOnlyScan: t.performance.viewportOnlyScan,
readonly: t.readonly
}
),
t.statusbar.enabled && /* @__PURE__ */ l(
t.statusbar.enabled && /* @__PURE__ */ d(
"div",
{
ref: h,
ref: s,
className: "editora-statusbar-container",

@@ -1074,20 +1418,20 @@ style: { order: t.statusbar.position === "top" ? -1 : 1 }

) });
}, Se = (e) => /* @__PURE__ */ l(ye, { ...e });
function Te(e = {}) {
const t = E(null), m = E(e.onCommand);
return A(() => {
m.current = e.onCommand;
}), A(() => {
}, Ze = (e) => /* @__PURE__ */ d(Ge, { ...e });
function et(e = {}) {
const t = T(null), u = T(e.onCommand);
return z(() => {
u.current = e.onCommand;
}), z(() => {
if (typeof window > "u" || e.enabled === !1) return;
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;
return r && r.addEventListener("keydown", i), () => {
r && r.removeEventListener("keydown", i);
const i = new ge(e);
t.current = i;
const r = (b) => i.handleKeyDown(b, (c, m) => {
u.current && u.current(c, m), typeof window < "u" && window.executeEditorCommand && window.executeEditorCommand(c, m);
}), o = e.editorElement || document;
return o && o.addEventListener("keydown", r), () => {
o && o.removeEventListener("keydown", r);
};
}, [e.editorElement, e.enabled, e.shortcuts, e.customShortcuts]), {
getShortcuts: () => t.current?.getAllShortcuts() || [],
getShortcutForCommand: (s) => t.current?.getShortcutForCommand(s),
getShortcutForCommand: (i) => t.current?.getShortcutForCommand(i),
getShortcutsHelp: () => t.current?.getShortcutsHelp() || "",

@@ -1100,9 +1444,9 @@ enable: () => t.current?.enable(),

export {
be as EditorContent,
Se as EditoraEditor,
ce as InlineMenu,
Se as RichTextEditor,
V as Toolbar,
pe as mergeConfig,
Te as useKeyboardShortcuts
Ue as EditorContent,
Ze as EditoraEditor,
Ne as InlineMenu,
Ze as RichTextEditor,
de as Toolbar,
Ke as mergeConfig,
et as useKeyboardShortcuts
};
{
"name": "@editora/react",
"version": "1.0.3",
"version": "1.0.4",
"description": "React components for Editora - Best Free Premium Rich Text Editor. Free React WYSIWYG editor with enterprise features, 30+ free plugins, and accessibility support.",

@@ -38,6 +38,6 @@ "author": "Ajay Kumar <ajaykr089@gmail.com>",

"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"types": "index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"types": "./index.d.ts",
"import": "./dist/index.esm.js",

@@ -49,2 +49,4 @@ "require": "./dist/index.cjs.js"

"dist",
"index.d.ts",
"!dist/**/*.map",
"README.md",

@@ -60,11 +62,21 @@ "LICENSE"

"peerDependencies": {
"@editora/core": "^1.0.0",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
"@editora/core": "^1.0.4",
"@editora/plugins": "^1.0.4",
"@editora/themes": "^1.0.4",
"react": ">=16.8.0 <20",
"react-dom": ">=16.8.0 <20"
},
"peerDependenciesMeta": {
"@editora/plugins": {
"optional": true
},
"@editora/themes": {
"optional": true
}
},
"dependencies": {
"@editora/core": "^1.0.3",
"@editora/light-code-editor": "^1.0.2"
},
"devDependencies": {
"@editora/core": "^1.0.4",
"@types/react": "^18.2.0",

@@ -71,0 +83,0 @@ "@types/react-dom": "^18.2.0",

+55
-13

@@ -20,2 +20,20 @@ # @editora/react

### Runtime Dependency Matrix
- Required: `@editora/react`, `@editora/core`, `react`, `react-dom`
- Optional but recommended: `@editora/plugins` (toolbar/plugin features), `@editora/themes` (default/dark/acme CSS)
- For smaller bundles: prefer `@editora/plugins/lite` or per-plugin subpaths like `@editora/plugins/bold`, and lazy-load heavy plugins (`document-manager`, `media-manager`, `spell-check`) via dynamic imports.
Minimal install:
```bash
npm install @editora/react @editora/core react react-dom
```
Full-featured install:
```bash
npm install @editora/react @editora/core @editora/plugins @editora/themes react react-dom
```
## 🎯 Overview

@@ -107,2 +125,19 @@

### Performance + Accessibility Config
```tsx
<EditoraEditor
plugins={[BoldPlugin(), ItalicPlugin()]}
accessibility={{
enableARIA: true,
keyboardNavigation: true,
checker: true, // auto-enables a11y checker if factory/plugin is available
}}
performance={{
debounceInputMs: 120,
viewportOnlyScan: true,
}}
/>
```
### With Custom Toolbar

@@ -169,3 +204,2 @@

style?: React.CSSProperties;
theme?: 'light' | 'dark' | 'auto';

@@ -272,4 +306,8 @@ // Toolbar

import "@editora/themes/themes/default.css";
import "@editora/themes/themes/dark.css";
import "@editora/themes/themes/acme.css";
<EditoraEditor theme="dark" />
<div data-theme="dark">
<EditoraEditor />
</div>
```

@@ -280,19 +318,23 @@

```css
:root {
--editora-bg: #ffffff;
--editora-text: #000000;
--editora-border: #cccccc;
--editora-primary: #0066cc;
--editora-toolbar-bg: #f5f5f5;
:is([data-theme="custom-brand"], .editora-theme-custom-brand) {
--rte-color-primary: #2563eb;
--rte-color-primary-hover: #1d4ed8;
--rte-color-text-primary: #0f172a;
--rte-color-bg-primary: #ffffff;
--rte-color-border: #cbd5e1;
}
[data-theme="dark"] {
--editora-bg: #1e1e1e;
--editora-text: #ffffff;
--editora-border: #444444;
--editora-primary: #3399ff;
--editora-toolbar-bg: #2d2d2d;
--rte-color-primary: #58a6ff;
}
```
Apply it in React with a wrapper:
```tsx
<div data-theme="custom-brand">
<EditoraEditor />
</div>
```
## 🔌 Plugin Configuration

@@ -299,0 +341,0 @@