open-text-editor-latest 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/index.cjs.js +41 -0
- package/dist/index.es.js +1146 -0
- package/dist/index.umd.js +41 -0
- package/dist/vite.svg +1 -0
- package/docs/PUBLISH.md +27 -0
- package/docs/editor/developer.md +31 -0
- package/package.json +71 -0
- package/src/editor/OpenTextEditor.jsx +1021 -0
- package/src/editor/README.md +15 -0
- package/src/editor/assets/.gitkeep +0 -0
- package/src/editor/index.jsx +4 -0
- package/src/editor/plugins/formatting.js +10 -0
- package/src/editor/plugins/history.js +9 -0
- package/src/editor/plugins/image.js +9 -0
- package/src/editor/plugins/index.js +25 -0
- package/src/editor/plugins/table.js +9 -0
- package/src/editor/styles/editor.css +8 -0
- package/src/editor/tests/.gitkeep +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
(function(l,T){typeof exports=="object"&&typeof module<"u"?module.exports=T(require("react")):typeof define=="function"&&define.amd?define(["react"],T):(l=typeof globalThis<"u"?globalThis:l||self,l.OpenTextEditor=T(l.React))})(this,(function(l){"use strict";var T={exports:{}},J={};var ke;function Oe(){if(ke)return J;ke=1;var m=Symbol.for("react.transitional.element"),b=Symbol.for("react.fragment");function k(j,w,i){var S=null;if(i!==void 0&&(S=""+i),w.key!==void 0&&(S=""+w.key),"key"in w){i={};for(var N in w)N!=="key"&&(i[N]=w[N])}else i=w;return w=i.ref,{$$typeof:m,type:j,key:S,ref:w!==void 0?w:null,props:i}}return J.Fragment=b,J.jsx=k,J.jsxs=k,J}var Q={};var we;function De(){return we||(we=1,process.env.NODE_ENV!=="production"&&(function(){function m(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===de?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case U:return"Fragment";case ie:return"Profiler";case le:return"StrictMode";case W:return"Suspense";case be:return"SuspenseList";case ce:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case ae:return"Portal";case A:return e.displayName||"Context";case he:return(e._context.displayName||"Context")+".Consumer";case ge:var s=e.render;return e=e.displayName,e||(e=s.displayName||s.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case K:return s=e.displayName||null,s!==null?s:m(e.type)||"Memo";case V:s=e._payload,e=e._init;try{return m(e(s))}catch{}}return null}function b(e){return""+e}function k(e){try{b(e);var s=!1}catch{s=!0}if(s){s=console;var c=s.error,f=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return c.call(s,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",f),b(e)}}function j(e){if(e===U)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===V)return"<...>";try{var s=m(e);return s?"<"+s+">":"<...>"}catch{return"<...>"}}function w(){var e=q.A;return e===null?null:e.getOwner()}function i(){return Error("react-stack-top-frame")}function S(e){if(ee.call(e,"key")){var s=Object.getOwnPropertyDescriptor(e,"key").get;if(s&&s.isReactWarning)return!1}return e.key!==void 0}function N(e,s){function c(){Y||(Y=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",s))}c.isReactWarning=!0,Object.defineProperty(e,"key",{get:c,configurable:!0})}function F(){var e=m(this.type);return r[e]||(r[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function B(e,s,c,f,R,z){var v=c.ref;return e={$$typeof:Z,type:e,key:s,props:c,_owner:f},(v!==void 0?v:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:F}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:R}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:z}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function E(e,s,c,f,R,z){var v=s.children;if(v!==void 0)if(f)if(xe(v)){for(f=0;f<v.length;f++)_(v[f]);Object.freeze&&Object.freeze(v)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else _(v);if(ee.call(s,"key")){v=m(e);var C=Object.keys(s).filter(function(ue){return ue!=="key"});f=0<C.length?"{key: someKey, "+C.join(": ..., ")+": ...}":"{key: someKey}",L[v+f]||(C=0<C.length?"{"+C.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
2
|
+
let props = %s;
|
|
3
|
+
<%s {...props} />
|
|
4
|
+
React keys must be passed directly to JSX without using spread:
|
|
5
|
+
let props = %s;
|
|
6
|
+
<%s key={someKey} {...props} />`,f,v,C,v),L[v+f]=!0)}if(v=null,c!==void 0&&(k(c),v=""+c),S(s)&&(k(s.key),v=""+s.key),"key"in s){c={};for(var P in s)P!=="key"&&(c[P]=s[P])}else c=s;return v&&N(c,typeof e=="function"?e.displayName||e.name||"Unknown":e),B(e,v,c,w(),R,z)}function _(e){se(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===V&&(e._payload.status==="fulfilled"?se(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function se(e){return typeof e=="object"&&e!==null&&e.$$typeof===Z}var I=l,Z=Symbol.for("react.transitional.element"),ae=Symbol.for("react.portal"),U=Symbol.for("react.fragment"),le=Symbol.for("react.strict_mode"),ie=Symbol.for("react.profiler"),he=Symbol.for("react.consumer"),A=Symbol.for("react.context"),ge=Symbol.for("react.forward_ref"),W=Symbol.for("react.suspense"),be=Symbol.for("react.suspense_list"),K=Symbol.for("react.memo"),V=Symbol.for("react.lazy"),ce=Symbol.for("react.activity"),de=Symbol.for("react.client.reference"),q=I.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ee=Object.prototype.hasOwnProperty,xe=Array.isArray,te=console.createTask?console.createTask:function(){return null};I={react_stack_bottom_frame:function(e){return e()}};var Y,r={},oe=I.react_stack_bottom_frame.bind(I,i)(),X=te(j(i)),L={};Q.Fragment=U,Q.jsx=function(e,s,c){var f=1e4>q.recentlyCreatedOwnerStacks++;return E(e,s,c,!1,f?Error("react-stack-top-frame"):oe,f?te(j(e)):X)},Q.jsxs=function(e,s,c){var f=1e4>q.recentlyCreatedOwnerStacks++;return E(e,s,c,!0,f?Error("react-stack-top-frame"):oe,f?te(j(e)):X)}})()),Q}var je;function Ie(){return je||(je=1,process.env.NODE_ENV==="production"?T.exports=Oe():T.exports=De()),T.exports}var o=Ie();const _e=(...m)=>m.filter((b,k,j)=>!!b&&b.trim()!==""&&j.indexOf(b)===k).join(" ").trim();const Pe=m=>m.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();const Fe=m=>m.replace(/^([A-Z])|[\s-_]+(\w)/g,(b,k,j)=>j?j.toUpperCase():k.toLowerCase());const Ne=m=>{const b=Fe(m);return b.charAt(0).toUpperCase()+b.slice(1)};var Be={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};const Ue=m=>{for(const b in m)if(b.startsWith("aria-")||b==="role"||b==="title")return!0;return!1};const We=l.forwardRef(({color:m="currentColor",size:b=24,strokeWidth:k=2,absoluteStrokeWidth:j,className:w="",children:i,iconNode:S,...N},F)=>l.createElement("svg",{ref:F,...Be,width:b,height:b,stroke:m,strokeWidth:j?Number(k)*24/Number(b):k,className:_e("lucide",w),...!i&&!Ue(N)&&{"aria-hidden":"true"},...N},[...S.map(([B,E])=>l.createElement(B,E)),...Array.isArray(i)?i:[i]]));const u=(m,b)=>{const k=l.forwardRef(({className:j,...w},i)=>l.createElement(We,{ref:i,iconNode:b,className:_e(`lucide-${Pe(Ne(m))}`,`lucide-${m}`,j),...w}));return k.displayName=Ne(m),k};const Ve=u("arrow-down",[["path",{d:"M12 5v14",key:"s699le"}],["path",{d:"m19 12-7 7-7-7",key:"1idqje"}]]);const Ye=u("arrow-left",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]);const Xe=u("arrow-right",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]);const Ge=u("arrow-up",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);const $e=u("bold",[["path",{d:"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8",key:"mg9rjx"}]]);const re=u("chevron-down",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);const Je=u("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]]);const Qe=u("file-code",[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10 12.5 8 15l2 2.5",key:"1tg20x"}],["path",{d:"m14 12.5 2 2.5-2 2.5",key:"yinavb"}]]);const Ze=u("highlighter",[["path",{d:"m9 11-6 6v3h9l3-3",key:"1a3l36"}],["path",{d:"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4",key:"14a9rk"}]]);const Ke=u("image",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]]);const qe=u("italic",[["line",{x1:"19",x2:"10",y1:"4",y2:"4",key:"15jd3p"}],["line",{x1:"14",x2:"5",y1:"20",y2:"20",key:"bu0au3"}],["line",{x1:"15",x2:"9",y1:"4",y2:"20",key:"uljnxc"}]]);const et=u("link",[["path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",key:"1cjeqo"}],["path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71",key:"19qd67"}]]);const tt=u("list-indent-decrease",[["path",{d:"M21 5H11",key:"us1j55"}],["path",{d:"M21 12H11",key:"wd7e0v"}],["path",{d:"M21 19H11",key:"saa85w"}],["path",{d:"m7 8-4 4 4 4",key:"o5hrat"}]]);const ot=u("list-indent-increase",[["path",{d:"M21 5H11",key:"us1j55"}],["path",{d:"M21 12H11",key:"wd7e0v"}],["path",{d:"M21 19H11",key:"saa85w"}],["path",{d:"m3 8 4 4-4 4",key:"1a3j6y"}]]);const nt=u("list-ordered",[["path",{d:"M11 5h10",key:"1cz7ny"}],["path",{d:"M11 12h10",key:"1438ji"}],["path",{d:"M11 19h10",key:"11t30w"}],["path",{d:"M4 4h1v5",key:"10yrso"}],["path",{d:"M4 9h2",key:"r1h2o0"}],["path",{d:"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02",key:"xtkcd5"}]]);const rt=u("list",[["path",{d:"M3 5h.01",key:"18ugdj"}],["path",{d:"M3 12h.01",key:"nlz23k"}],["path",{d:"M3 19h.01",key:"noohij"}],["path",{d:"M8 5h13",key:"1pao27"}],["path",{d:"M8 12h13",key:"1za7za"}],["path",{d:"M8 19h13",key:"m83p4d"}]]);const st=u("minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]);const at=u("quote",[["path",{d:"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z",key:"rib7q0"}],["path",{d:"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z",key:"1ymkrd"}]]);const lt=u("redo",[["path",{d:"M21 7v6h-6",key:"3ptur4"}],["path",{d:"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7",key:"1kgawr"}]]);const it=u("remove-formatting",[["path",{d:"M4 7V4h16v3",key:"9msm58"}],["path",{d:"M5 20h6",key:"1h6pxn"}],["path",{d:"M13 4 8 20",key:"kqq6aj"}],["path",{d:"m15 15 5 5",key:"me55sn"}],["path",{d:"m20 15-5 5",key:"11p7ol"}]]);const ct=u("strikethrough",[["path",{d:"M16 4H9a3 3 0 0 0-2.83 4",key:"43sutm"}],["path",{d:"M14 12a4 4 0 0 1 0 8H6",key:"nlfj13"}],["line",{x1:"4",x2:"20",y1:"12",y2:"12",key:"1e0a9i"}]]);const dt=u("subscript",[["path",{d:"m4 5 8 8",key:"1eunvl"}],["path",{d:"m12 5-8 8",key:"1ah0jp"}],["path",{d:"M20 19h-4c0-1.5.44-2 1.5-2.5S20 15.33 20 14c0-.47-.17-.93-.48-1.29a2.11 2.11 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07",key:"e8ta8j"}]]);const ut=u("superscript",[["path",{d:"m4 19 8-8",key:"hr47gm"}],["path",{d:"m12 19-8-8",key:"1dhhmo"}],["path",{d:"M20 12h-4c0-1.5.442-2 1.5-2.5S20 8.334 20 7.002c0-.472-.17-.93-.484-1.29a2.105 2.105 0 0 0-2.617-.436c-.42.239-.738.614-.899 1.06",key:"1dfcux"}]]);const ft=u("table",[["path",{d:"M12 3v18",key:"108xh3"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}],["path",{d:"M3 15h18",key:"5xshup"}]]);const Ce=u("text-align-center",[["path",{d:"M21 5H3",key:"1fi0y6"}],["path",{d:"M17 12H7",key:"16if0g"}],["path",{d:"M19 19H5",key:"vjpgq2"}]]);const Re=u("text-align-end",[["path",{d:"M21 5H3",key:"1fi0y6"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M21 19H7",key:"4cu937"}]]);const Me=u("text-align-start",[["path",{d:"M21 5H3",key:"1fi0y6"}],["path",{d:"M15 12H3",key:"6jk70r"}],["path",{d:"M17 19H3",key:"z6ezky"}]]);const pe=u("trash-2",[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]]);const mt=u("type",[["path",{d:"M12 4v16",key:"1654pz"}],["path",{d:"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2",key:"e0r10z"}],["path",{d:"M9 20h6",key:"s66wpe"}]]);const pt=u("underline",[["path",{d:"M6 4v6a6 6 0 0 0 12 0V4",key:"9kb039"}],["line",{x1:"4",x2:"20",y1:"20",y2:"20",key:"nun2al"}]]);const ht=u("undo",[["path",{d:"M3 7v6h6",key:"1v2h90"}],["path",{d:"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13",key:"1r6uu6"}]]);const gt=u("x",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),bt="";return l.forwardRef(({initialValue:m=bt,onChange:b,className:k="w-full h-full",placeholder:j="Start typing..."},w)=>{const i=l.useRef(null),S=l.useRef(null),N=l.useRef(null),F=l.useRef(null),B=l.useRef(null),E=l.useRef(null),[_,se]=l.useState({}),[I,Z]=l.useState(!1),[ae,U]=l.useState(!1),[le,ie]=l.useState(!1),[he,A]=l.useState("Normal"),[ge,W]=l.useState("Sans Serif"),[be,K]=l.useState("16px"),[V,ce]=l.useState(!1),[de,q]=l.useState(3),[ee,xe]=l.useState(3),[te,Y]=l.useState(!0),[r,oe]=l.useState(!1),[X,L]=l.useState(m||""),[e,s]=l.useState(null),[c,f]=l.useState(null),[R,z]=l.useState(null),[v,C]=l.useState([]),[P,ue]=l.useState(!1),[fe,Se]=l.useState(!1),G=l.useRef({startX:0,startWidth:0,target:null}),$=l.useRef({startX:0,startWidth:0,target:null}),me=()=>{if(E.current){const t=window.getSelection();t.removeAllRanges(),t.addRange(E.current)}else i.current?.focus()};l.useImperativeHandle(w,()=>({focus:()=>i.current?.focus(),getHtml:()=>i.current?.innerHTML||"",setHtml:t=>{i.current&&(i.current.innerHTML=t,L(t),ne())},insertHtml:t=>{me(),h("insertHTML",t)},execCommand:(t,n)=>{me(),h(t,n)},insertTable:(t,n)=>{Te(t,n)},tableAction:t=>{me(),H(t)}})),l.useEffect(()=>{i.current&&!r&&(m&&m!==i.current.innerHTML?(i.current.innerHTML=m,L(m),Y(!1)):!m&&!i.current.innerHTML&&(i.current.innerHTML="<p><br/></p>",L("<p><br/></p>"),Y(!0)))},[m,r]);const ne=()=>{if(ve(),M(),i.current){const t=i.current.textContent;Y(!t||t.trim()===""),b&&b(i.current.innerHTML)}},xt=t=>{const n=t.target.value;L(n),b&&b(n)},yt=()=>{r?oe(!1):(i.current&&(L(i.current.innerHTML),s(null),z(null),f(null),C([])),oe(!0))};l.useEffect(()=>{!r&&i.current&&i.current.innerHTML!==X&&(i.current.innerHTML=X||"<p><br/></p>",ne())},[r]);const h=(t,n=null)=>{r||(document.execCommand(t,!1,n),ne(),i.current?.focus())},vt=(t,n)=>{h("formatBlock",t),A(n),Z(!1)},kt=(t,n)=>{h("fontName",t),W(n),U(!1)},wt=(t,n)=>{h("fontSize",t),K(n),ie(!1)},jt=t=>{const n=t.target.files[0];if(n){const a=new FileReader;a.onload=d=>{const p=`<img src="${d.target.result}" style="width: 300px; max-width: 100%; height: auto; border-radius: 4px; display: inline-block; cursor: pointer; border: 1px solid transparent;" draggable="true" />`;h("insertHTML",p)},a.readAsDataURL(n)}t.target.value=""},_t=()=>{const t=prompt("Enter URL:");t&&h("createLink",t)},Te=(t,n)=>{me();const a=t!==void 0?t:de,d=n!==void 0?n:ee,p=parseInt(a)||3,y=parseInt(d)||3,g=`
|
|
7
|
+
<table style="border-collapse: collapse; width: 100%; margin: 1em 0; border: 1px solid #e5e7eb; table-layout: fixed;">
|
|
8
|
+
<tbody>
|
|
9
|
+
${Array(p).fill(0).map(()=>`
|
|
10
|
+
<tr>
|
|
11
|
+
${Array(y).fill(0).map(()=>`
|
|
12
|
+
<td style="border: 1px solid #d1d5db; padding: 8px; min-width: 30px; position: relative; width: ${100/y}%;">
|
|
13
|
+
<br />
|
|
14
|
+
</td>
|
|
15
|
+
`).join("")}
|
|
16
|
+
</tr>
|
|
17
|
+
`).join("")}
|
|
18
|
+
</tbody>
|
|
19
|
+
</table>
|
|
20
|
+
<p><br/></p>
|
|
21
|
+
`;h("insertHTML",g),ce(!1)},H=t=>{if(!c||!e||e.tagName!=="TABLE")return;const n=c.closest("tr");if(!n)return;const a=e,d=a.querySelector("tbody");n.rowIndex;const p=c.cellIndex;if(p===-1)return;const y=()=>{const g=document.createElement("td");return g.style.border="1px solid #d1d5db",g.style.padding="8px",g.style.minWidth="30px",g.innerHTML="<br>",g};if(t==="row-above"){const g=n.cloneNode(!1);Array.from(n.children).forEach(()=>g.appendChild(y())),d.insertBefore(g,n)}else if(t==="row-below"){const g=n.cloneNode(!1);Array.from(n.children).forEach(()=>g.appendChild(y())),d.insertBefore(g,n.nextSibling)}else t==="col-left"?Array.from(a.rows).forEach(g=>{const D=g.children[p];D&&g.insertBefore(y(),D)}):t==="col-right"?Array.from(a.rows).forEach(g=>{const D=g.children[p];D&&g.insertBefore(y(),D.nextSibling)}):t==="del-row"?(n.remove(),d.children.length===0?(a.remove(),s(null),f(null)):c.isConnected||f(null)):t==="del-col"?(Array.from(a.rows).forEach(g=>{g.children[p]&&g.children[p].remove()}),a.rows[0]&&a.rows[0].children.length===0?(a.remove(),s(null),f(null)):c.isConnected||f(null)):t==="del-table"&&(a.remove(),s(null),f(null));ne(),M()},M=l.useCallback(()=>{if(!i.current||r)return;if(e&&e.isConnected){const n=e.getBoundingClientRect(),a=i.current.getBoundingClientRect();z({top:n.top-a.top,left:n.left-a.left,width:n.width,height:n.height})}else z(null);const t=e?.tagName==="TABLE"?e:c?.closest("table");if(t&&t.isConnected){const n=t.getBoundingClientRect(),a=i.current.getBoundingClientRect(),d=[],p=t.rows[0];p&&Array.from(p.cells).forEach(y=>{const g=y.getBoundingClientRect();d.push({left:g.left-a.left+g.width,top:n.top-a.top,height:n.height,cell:y})}),C(d)}else C([])},[e,c,r]);l.useEffect(()=>{document.execCommand("enableObjectResizing",!1,"false");const t=()=>{M()},n=()=>{M()},a=i.current;return a&&a.addEventListener("scroll",t),window.addEventListener("resize",n),()=>{a&&a.removeEventListener("scroll",t),window.removeEventListener("resize",n)}},[M]);const Nt=t=>{if(r)return;const n=t.target,a=n.closest("td")||n.closest("th"),d=n.closest("table"),p=n.tagName==="IMG"?n:n.closest("img");if(a){f(a);const y=a.closest("table");y&&e!==y&&s(y)}else fe||f(null);if(p){e!==p&&s(p);return}if(d&&d!==i.current){e!==d&&s(d);return}!P&&!fe&&e&&!d&&!p&&!a&&(s(null),z(null),f(null),C([])),ve()},Ct=t=>{if(r)return;const n=t.target,a=n.tagName==="IMG"?n:n.closest("img"),d=n.closest("td")||n.closest("th"),p=n.closest("table");if(a){t.preventDefault(),e!==a&&s(a),setTimeout(M,0);return}if(d||p){t.preventDefault();const y=p||(d?d.closest("table"):null);d&&f(d),y&&e!==y&&s(y),setTimeout(M,0)}},Rt=t=>{t.preventDefault(),t.stopPropagation(),e&&(ue(!0),G.current={startX:t.clientX,startWidth:e.offsetWidth,target:e},document.addEventListener("mousemove",Ee),document.addEventListener("mouseup",Ae))},Ee=t=>{if(!G.current.target)return;const n=t.clientX-G.current.startX,a=Math.max(50,G.current.startWidth+n);G.current.target.style.width=`${a}px`,M()},Ae=()=>{ue(!1),G.current={startX:0,startWidth:0,target:null},document.removeEventListener("mousemove",Ee),document.removeEventListener("mouseup",Ae)},Mt=(t,n)=>{t.preventDefault(),t.stopPropagation(),n&&(Se(!0),$.current={startX:t.clientX,startWidth:n.offsetWidth,target:n},document.addEventListener("mousemove",Le),document.addEventListener("mouseup",ze))},Le=t=>{if(!$.current.target)return;const n=t.clientX-$.current.startX,a=Math.max(20,$.current.startWidth+n);$.current.target.style.width=`${a}px`,M()},ze=()=>{Se(!1),$.current={startX:0,startWidth:0,target:null},document.removeEventListener("mousemove",Le),document.removeEventListener("mouseup",ze)},ye=t=>{e&&(e.style.display="",e.style.float="",e.style.margin="",e.style.outline="none",t==="left"?(e.style.float="left",e.style.margin="0 1rem 1rem 0"):t==="right"?(e.style.float="right",e.style.margin="0 0 1rem 1rem"):t==="center"?(e.style.display="block",e.style.marginLeft="auto",e.style.marginRight="auto"):e.style.display="inline-block",setTimeout(M,0))},ve=()=>{if(!i.current||r)return;const t=window.getSelection();if(t.rangeCount>0){const a=t.getRangeAt(0);if(i.current.contains(a.commonAncestorContainer)){E.current=a.cloneRange();let d=a.commonAncestorContainer;d.nodeType===3&&(d=d.parentNode);const p=d.closest("td")||d.closest("th"),y=d.closest("table");p&&c!==p&&f(p),y?e!==y&&s(y):!P&&!fe&&!d.closest("img")&&e&&e.tagName==="TABLE"&&(s(null),f(null));const g=document.queryCommandValue("fontSize"),D={1:"10px",2:"13px",3:"16px",4:"18px",5:"24px",6:"32px",7:"48px"};g&&D[g]?K(D[g]):K("16px");const He=document.queryCommandValue("fontName");He.includes("Serif")?W("Serif"):He.includes("Mono")?W("Monospace"):W("Sans Serif")}}const n={bold:document.queryCommandState("bold"),italic:document.queryCommandState("italic"),underline:document.queryCommandState("underline"),strikethrough:document.queryCommandState("strikethrough"),subscript:document.queryCommandState("subscript"),superscript:document.queryCommandState("superscript"),justifyLeft:document.queryCommandState("justifyLeft"),justifyCenter:document.queryCommandState("justifyCenter"),justifyRight:document.queryCommandState("justifyRight"),justifyFull:document.queryCommandState("justifyFull"),insertUnorderedList:document.queryCommandState("insertUnorderedList"),insertOrderedList:document.queryCommandState("insertOrderedList")};if(se(n),t.rangeCount>0)try{const a=t.getRangeAt(0).commonAncestorContainer,p=(a.nodeType===3?a.parentNode:a)?.tagName?.toLowerCase();A(p==="h1"?"Heading 1":p==="h2"?"Heading 2":p==="h3"?"Heading 3":p==="blockquote"?"Quote":"Normal")}catch{}};l.useEffect(()=>{const t=()=>ve();return document.addEventListener("selectionchange",t),()=>document.removeEventListener("selectionchange",t)},[c,e,P,fe,r]);const x=({onClick:t,isActive:n,icon:a,title:d,hasArrow:p=!1,disabled:y=!1})=>o.jsxs("button",{type:"button",onClick:t,disabled:y,title:d,className:`p-1.5 rounded-md transition-colors duration-150 flex items-center justify-center gap-1
|
|
22
|
+
${n?"bg-indigo-100 text-indigo-700":"text-gray-600 hover:bg-gray-100 hover:text-gray-900"}
|
|
23
|
+
${y?"opacity-30 cursor-not-allowed":""}
|
|
24
|
+
`,children:[o.jsx(a,{size:18,strokeWidth:2.5}),p&&o.jsx(re,{size:12,className:"opacity-50"})]}),O=()=>o.jsx("div",{className:"w-px h-6 bg-gray-300 mx-1 self-center"});return o.jsxs("div",{className:`bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden flex flex-col font-sans text-gray-800 min-h-[300px] ${k}`,children:[o.jsxs("div",{className:"flex flex-wrap items-center gap-0.5 p-2 border-b border-gray-200 bg-white sticky top-0 z-20 select-none shadow-sm",children:[o.jsx(x,{onClick:yt,isActive:r,icon:Qe,title:r?"Switch to Visual Editor":"View Source / HTML"}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center",children:[o.jsx(x,{onClick:()=>h("undo"),icon:ht,title:"Undo",disabled:r}),o.jsx(x,{onClick:()=>h("redo"),icon:lt,title:"Redo",disabled:r})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center gap-1",children:[o.jsxs("div",{className:"relative",children:[o.jsxs("button",{disabled:r,onClick:()=>Z(!I),className:`flex items-center justify-between gap-2 px-2 py-1.5 text-sm font-medium rounded-md min-w-[100px] ${r?"text-gray-300 cursor-not-allowed":"text-gray-700 hover:bg-gray-100"}`,children:[o.jsx("span",{className:"truncate",children:he}),o.jsx(re,{size:14})]}),I&&!r&&o.jsx("div",{className:"absolute top-full left-0 mt-1 w-40 bg-white border border-gray-200 rounded shadow-lg py-1 z-30",children:[{label:"Normal",tag:"P"},{label:"Heading 1",tag:"H1"},{label:"Heading 2",tag:"H2"},{label:"Heading 3",tag:"H3"},{label:"Quote",tag:"BLOCKQUOTE"}].map(t=>o.jsx("button",{onClick:()=>vt(t.tag,t.label),className:"block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 hover:text-indigo-600",children:t.label},t.tag))})]}),o.jsxs("div",{className:"relative hidden md:block",children:[o.jsxs("button",{disabled:r,onClick:()=>U(!ae),className:`flex items-center justify-between gap-2 px-2 py-1.5 text-sm font-medium rounded-md min-w-[130px] ${r?"text-gray-300 cursor-not-allowed":"text-gray-700 hover:bg-gray-100"}`,children:[o.jsx("span",{className:"truncate",children:ge}),o.jsx(re,{size:14})]}),ae&&!r&&o.jsx("div",{className:"absolute top-full left-0 mt-1 w-48 bg-white border border-gray-200 rounded shadow-lg py-1 z-30 max-h-60 overflow-y-auto",children:[{label:"Sans Serif",value:"ui-sans-serif, system-ui, sans-serif"},{label:"Serif",value:"ui-serif, Georgia, serif"},{label:"Monospace",value:"ui-monospace, monospace"},{label:"Arial",value:"Arial, Helvetica, sans-serif"},{label:"Arial Black",value:'"Arial Black", Gadget, sans-serif'},{label:"Comic Sans MS",value:'"Comic Sans MS", "Comic Sans", cursive'},{label:"Courier New",value:'"Courier New", Courier, monospace'},{label:"Georgia",value:"Georgia, serif"},{label:"Impact",value:"Impact, Charcoal, sans-serif"},{label:"Lucida Console",value:'"Lucida Console", Monaco, monospace'},{label:"Tahoma",value:"Tahoma, Geneva, sans-serif"},{label:"Times New Roman",value:'"Times New Roman", Times, serif'},{label:"Trebuchet MS",value:'"Trebuchet MS", Helvetica, sans-serif'},{label:"Verdana",value:"Verdana, Geneva, sans-serif"}].map(t=>o.jsx("button",{onClick:()=>kt(t.value,t.label),className:"block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 hover:text-indigo-600",style:{fontFamily:t.value},children:t.label},t.value))})]}),o.jsxs("div",{className:"relative hidden md:block",children:[o.jsxs("button",{disabled:r,onClick:()=>ie(!le),className:`flex items-center justify-between gap-2 px-2 py-1.5 text-sm font-medium rounded-md min-w-[70px] ${r?"text-gray-300 cursor-not-allowed":"text-gray-700 hover:bg-gray-100"}`,children:[o.jsx("span",{className:"truncate",children:be}),o.jsx(re,{size:14})]}),le&&!r&&o.jsx("div",{className:"absolute top-full left-0 mt-1 w-24 bg-white border border-gray-200 rounded shadow-lg py-1 z-30 max-h-60 overflow-y-auto",children:[{label:"10px",value:"1"},{label:"13px",value:"2"},{label:"16px",value:"3"},{label:"18px",value:"4"},{label:"24px",value:"5"},{label:"32px",value:"6"},{label:"48px",value:"7"}].map(t=>o.jsx("button",{onClick:()=>wt(t.value,t.label),className:"block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 hover:text-indigo-600",children:t.label},t.value))})]})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center",children:[o.jsx(x,{onClick:()=>h("bold"),isActive:_.bold,icon:$e,title:"Bold",disabled:r}),o.jsx(x,{onClick:()=>h("italic"),isActive:_.italic,icon:qe,title:"Italic",disabled:r}),o.jsx(x,{onClick:()=>h("underline"),isActive:_.underline,icon:pt,title:"Underline",disabled:r}),o.jsx(x,{onClick:()=>h("strikethrough"),isActive:_.strikethrough,icon:ct,title:"Strikethrough",disabled:r})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center",children:[o.jsx(x,{onClick:()=>h("subscript"),isActive:_.subscript,icon:dt,title:"Subscript",disabled:r}),o.jsx(x,{onClick:()=>h("superscript"),isActive:_.superscript,icon:ut,title:"Superscript",disabled:r}),o.jsx(x,{onClick:()=>h("formatBlock","PRE"),icon:Je,title:"Code Block",disabled:r}),o.jsx(x,{onClick:()=>h("formatBlock","BLOCKQUOTE"),icon:at,title:"Blockquote",disabled:r})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center relative",children:[o.jsxs("div",{className:"relative",children:[o.jsx(x,{onClick:()=>F.current.click(),icon:mt,title:"Text Color",disabled:r}),o.jsx("input",{type:"color",ref:F,disabled:r,className:"absolute inset-0 opacity-0 w-full h-full cursor-pointer",onChange:t=>h("foreColor",t.target.value)})]}),o.jsxs("div",{className:"relative",children:[o.jsx(x,{onClick:()=>B.current.click(),icon:Ze,title:"Highlight Color",disabled:r}),o.jsx("input",{type:"color",ref:B,disabled:r,defaultValue:"#ffff00",className:"absolute inset-0 opacity-0 w-full h-full cursor-pointer",onChange:t=>h("hiliteColor",t.target.value)})]})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center",children:[o.jsx(x,{onClick:()=>h("justifyLeft"),isActive:_.justifyLeft,icon:Me,title:"Align Left",disabled:r}),o.jsx(x,{onClick:()=>h("justifyCenter"),isActive:_.justifyCenter,icon:Ce,title:"Align Center",disabled:r}),o.jsx(x,{onClick:()=>h("justifyRight"),isActive:_.justifyRight,icon:Re,title:"Align Right",disabled:r}),o.jsx("div",{className:"mx-1"}),o.jsx(x,{onClick:()=>h("insertUnorderedList"),isActive:_.insertUnorderedList,icon:rt,title:"Bullet List",disabled:r}),o.jsx(x,{onClick:()=>h("insertOrderedList"),isActive:_.insertOrderedList,icon:nt,title:"Numbered List",disabled:r})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center",children:[o.jsx(x,{onClick:()=>h("indent"),icon:ot,title:"Indent",disabled:r}),o.jsx(x,{onClick:()=>h("outdent"),icon:tt,title:"Outdent",disabled:r})]}),o.jsx(O,{}),o.jsxs("div",{className:"flex items-center",children:[o.jsx(x,{onClick:_t,icon:et,title:"Insert Link",disabled:r}),o.jsxs("div",{className:"relative",children:[o.jsx(x,{onClick:()=>N.current?.click(),icon:Ke,title:"Upload Image",disabled:r}),o.jsx("input",{type:"file",accept:"image/*",ref:N,onChange:jt,className:"hidden",disabled:r})]}),o.jsx(x,{onClick:()=>h("insertHorizontalRule"),icon:st,title:"Horizontal Line",disabled:r}),o.jsxs("div",{className:"relative",children:[o.jsx(x,{onClick:()=>ce(!V),icon:ft,title:"Insert Table",disabled:r}),V&&!r&&o.jsxs("div",{className:"absolute top-full left-0 mt-2 p-3 bg-white border border-gray-200 shadow-xl rounded-lg z-30 w-48",onClick:t=>t.stopPropagation(),children:[o.jsx("h4",{className:"text-xs font-semibold text-gray-500 mb-2 uppercase tracking-wider",children:"Table Size"}),o.jsxs("div",{className:"flex flex-col gap-2 mb-3",children:[o.jsxs("label",{className:"text-sm flex justify-between",children:["Rows: ",o.jsx("input",{type:"number",min:"1",max:"10",value:de,onChange:t=>q(t.target.value),className:"w-12 border border-gray-300 rounded px-1 text-right"})]}),o.jsxs("label",{className:"text-sm flex justify-between",children:["Cols: ",o.jsx("input",{type:"number",min:"1",max:"10",value:ee,onChange:t=>xe(t.target.value),className:"w-12 border border-gray-300 rounded px-1 text-right"})]})]}),o.jsx("button",{onClick:()=>Te(),className:"w-full bg-indigo-600 text-white text-xs font-bold py-1.5 rounded hover:bg-indigo-700 transition-colors",children:"Insert Table"})]})]})]}),o.jsx("div",{className:"flex-grow"}),o.jsxs("div",{className:"flex items-center border-l border-gray-200 pl-2",children:[o.jsx(x,{onClick:()=>h("removeFormat"),icon:it,title:"Clear Formatting",disabled:r}),o.jsx("div",{className:"ml-1 pl-1 border-l border-gray-200 hidden md:block",children:o.jsx(x,{onClick:()=>{},icon:gt,title:"Close"})})]})]}),o.jsx("div",{className:"flex-grow overflow-hidden flex flex-col relative",children:r?o.jsx("textarea",{ref:S,value:X,onChange:xt,className:"flex-grow p-4 w-full h-full resize-none font-mono text-sm bg-gray-50 text-gray-800 outline-none",spellCheck:"false"}):o.jsxs(o.Fragment,{children:[o.jsx("div",{ref:i,contentEditable:!0,suppressContentEditableWarning:!0,className:"flex-grow p-4 md:p-8 overflow-y-auto outline-none prose prose-indigo max-w-none prose-lg relative z-0",onInput:ne,onClick:Nt,onContextMenu:Ct,onKeyDown:t=>{t.key==="Tab"&&(t.preventDefault(),h("insertHTML"," "))}}),te&&o.jsx("div",{className:"absolute top-4 left-4 md:top-8 md:left-8 right-4 md:right-8 pointer-events-none",children:o.jsx("div",{className:"prose prose-indigo max-w-none prose-lg text-gray-400",children:o.jsx("p",{children:j})})}),e&&R&&o.jsxs("div",{className:"absolute pointer-events-none z-50",style:{top:R.top,left:R.left,width:R.width,height:R.height,border:"2px solid #3b82f6",boxSizing:"border-box"},children:[o.jsxs("div",{className:"absolute -top-10 left-1/2 transform -translate-x-1/2 bg-white shadow-lg border border-gray-200 rounded-md flex p-1 pointer-events-auto gap-1 whitespace-nowrap",children:[e.tagName==="IMG"&&o.jsxs(o.Fragment,{children:[o.jsx("button",{onMouseDown:t=>{t.preventDefault(),ye("left")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Align Left",children:o.jsx(Me,{size:16})}),o.jsx("button",{onMouseDown:t=>{t.preventDefault(),ye("center")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Align Center",children:o.jsx(Ce,{size:16})}),o.jsx("button",{onMouseDown:t=>{t.preventDefault(),ye("right")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Align Right",children:o.jsx(Re,{size:16})})]}),e.tagName==="TABLE"&&c&&o.jsxs(o.Fragment,{children:[o.jsx("button",{onMouseDown:t=>{t.preventDefault(),H("row-above")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Insert Row Above",children:o.jsx(Ge,{size:16})}),o.jsx("button",{onMouseDown:t=>{t.preventDefault(),H("row-below")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Insert Row Below",children:o.jsx(Ve,{size:16})}),o.jsx("div",{className:"w-px h-4 bg-gray-300 mx-1 self-center"}),o.jsx("button",{onMouseDown:t=>{t.preventDefault(),H("col-left")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Insert Col Left",children:o.jsx(Ye,{size:16})}),o.jsx("button",{onMouseDown:t=>{t.preventDefault(),H("col-right")},className:"p-1 hover:bg-gray-100 rounded text-gray-600",title:"Insert Col Right",children:o.jsx(Xe,{size:16})}),o.jsx("div",{className:"w-px h-4 bg-gray-300 mx-1 self-center"}),o.jsxs("button",{onMouseDown:t=>{t.preventDefault(),H("del-row")},className:"p-1 hover:bg-red-50 text-red-500 rounded font-xs flex items-center",title:"Delete Row",children:[o.jsx(pe,{size:14,className:"mr-0.5"}),"R"]}),o.jsxs("button",{onMouseDown:t=>{t.preventDefault(),H("del-col")},className:"p-1 hover:bg-red-50 text-red-500 rounded font-xs flex items-center",title:"Delete Column",children:[o.jsx(pe,{size:14,className:"mr-0.5"}),"C"]})]}),o.jsx("div",{className:"w-px h-4 bg-gray-300 mx-1 self-center"}),o.jsx("button",{onMouseDown:t=>{t.preventDefault(),e.tagName==="TABLE"?H("del-table"):e.remove(),s(null)},className:"p-1 hover:bg-red-50 text-red-500 rounded",title:e.tagName==="TABLE"?"Delete Table":"Delete",children:o.jsx(pe,{size:16})})]}),o.jsx("div",{className:"absolute bottom-1 right-1 w-4 h-4 bg-blue-500 rounded-full cursor-nwse-resize pointer-events-auto shadow-sm hover:scale-125 transition-transform border-2 border-white z-50",onMouseDown:Rt})]}),v.map((t,n)=>o.jsx("div",{className:"absolute z-50 cursor-col-resize flex items-center justify-center hover:bg-blue-400 hover:opacity-50 transition-colors",style:{top:t.top,left:t.left-4,width:"8px",height:t.height,pointerEvents:"auto"},onMouseDown:a=>Mt(a,t.cell),title:"Resize Column",children:o.jsx("div",{className:"w-0.5 h-full bg-blue-500 opacity-0 hover:opacity-100 transition-opacity"})},n))]})}),o.jsx("style",{children:`
|
|
25
|
+
.prose { display: flow-root; }
|
|
26
|
+
.prose p { display: flow-root; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.4; }
|
|
27
|
+
.prose table { width: auto; max-width: 100%; table-layout: fixed; border-collapse: collapse; margin: 1em 0; }
|
|
28
|
+
.prose td, .prose th { border: 1px solid #d1d5db; padding: 0.75rem; vertical-align: top; position: relative; }
|
|
29
|
+
.prose th { background-color: #f3f4f6; font-weight: 600; }
|
|
30
|
+
.prose h1 { font-size: 2.25em; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.1; font-weight: 800; color: #111827; }
|
|
31
|
+
.prose h2 { font-size: 1.75em; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2; font-weight: 700; color: #1f2937; }
|
|
32
|
+
.prose h3 { font-size: 1.5em; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.3; font-weight: 600; color: #374151; }
|
|
33
|
+
.prose ul { list-style-type: disc; padding-left: 1.5em; margin: 0.5em 0; }
|
|
34
|
+
.prose ol { list-style-type: decimal; padding-left: 1.5em; margin: 0.5em 0; }
|
|
35
|
+
.prose li { margin: 0.5em 0; }
|
|
36
|
+
.prose blockquote { border-left: 4px solid #6366f1; padding-left: 1rem; margin: 1rem 0; font-style: italic; color: #4b5563; background: #f9fafb; padding: 1rem; border-radius: 0 0.5rem 0.5rem 0; }
|
|
37
|
+
.prose pre { background-color: #1e293b; color: #e2e8f0; padding: 1rem; border-radius: 0.5rem; overflow-x: auto; font-family: monospace; }
|
|
38
|
+
.prose img { border-radius: 0.5rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
|
|
39
|
+
.prose hr { border: 0; border-top: 1px solid #e5e7eb; margin: 2em 0; }
|
|
40
|
+
::selection { background-color: #c7d2fe; color: #1e1b4b; }
|
|
41
|
+
`})]})})}));
|
package/dist/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
package/docs/PUBLISH.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Publishing to npm
|
|
2
|
+
|
|
3
|
+
Steps to publish a new version of `open-text-editor`:
|
|
4
|
+
|
|
5
|
+
1. Update version in `package.json` (semver).
|
|
6
|
+
2. Commit your changes and push to the repository.
|
|
7
|
+
3. Ensure you are logged in to npm: `npm login`.
|
|
8
|
+
4. Run the build script (prepare runs automatically for `npm publish`):
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm run build:lib
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
5. Publish:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm publish --access public
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Notes:
|
|
21
|
+
- The library build externalizes `react` and `react-dom` so they are peer dependencies. Consumers must install React separately.
|
|
22
|
+
- If you want to test a local tarball before publishing:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm pack
|
|
26
|
+
npm install -g ./open-text-editor-0.1.0.tgz
|
|
27
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Developer Guide — Plugins & Extensibility
|
|
2
|
+
|
|
3
|
+
This document explains how to create and register plugins for `open-text-editor`.
|
|
4
|
+
|
|
5
|
+
Plugin contract
|
|
6
|
+
- Export a default function that receives an `editorApi` and returns an object with:
|
|
7
|
+
- `name` — plugin id string
|
|
8
|
+
- `install(editor)` — called when plugin is enabled; attach commands, buttons, event listeners here
|
|
9
|
+
|
|
10
|
+
Example plugin skeleton
|
|
11
|
+
```js
|
|
12
|
+
export default function myPlugin(editorApi) {
|
|
13
|
+
return {
|
|
14
|
+
name: 'my-plugin',
|
|
15
|
+
install(editor) {
|
|
16
|
+
// add command
|
|
17
|
+
editor.execCommand = editor.execCommand || editorApi.execCommand
|
|
18
|
+
// add toolbar button by calling editorApi.addToolbarButton(...)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Registering plugins
|
|
25
|
+
- Built-in plugins live in `src/editor/plugins` and are available through the registry `import plugins from 'open-text-editor/src/editor/plugins'`.
|
|
26
|
+
- Consumers can supply plugins by passing them to the editor constructor or mounting API (future API plans). For now, import and compose in your app.
|
|
27
|
+
|
|
28
|
+
Best practices
|
|
29
|
+
- Keep plugins small and focused.
|
|
30
|
+
- Prefer declarative UI for toolbar buttons (icon, tooltip, command).
|
|
31
|
+
- Clean up event listeners and DOM mutations during uninstall.
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "open-text-editor-latest",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "A lightweight, pluggable React contentEditable rich text editor",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"build": "vite build",
|
|
10
|
+
"build:lib": "vite build --config build/vite.lib.config.js",
|
|
11
|
+
"prepare": "npm run build:lib",
|
|
12
|
+
"prepublishOnly": "npm run build:lib",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"preview": "vite preview"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@tailwindcss/vite": "^4.1.18",
|
|
18
|
+
"lucide-react": "^0.563.0",
|
|
19
|
+
"tailwindcss": "^4.1.18"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"react": "^18 || ^19",
|
|
23
|
+
"react-dom": "^18 || ^19"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@eslint/js": "^9.39.1",
|
|
27
|
+
"@types/react": "^19.2.5",
|
|
28
|
+
"@types/react-dom": "^19.2.3",
|
|
29
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
30
|
+
"eslint": "^9.39.1",
|
|
31
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
32
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
33
|
+
"globals": "^16.5.0",
|
|
34
|
+
"vite": "^7.2.4"
|
|
35
|
+
},
|
|
36
|
+
"main": "dist/index.cjs.js",
|
|
37
|
+
"module": "dist/index.esm.js",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist/",
|
|
40
|
+
"src/editor/",
|
|
41
|
+
"README.md",
|
|
42
|
+
"docs/"
|
|
43
|
+
],
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/danu20002/open-text-editor.git"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"rich-text",
|
|
50
|
+
"editor",
|
|
51
|
+
"react",
|
|
52
|
+
"contenteditable",
|
|
53
|
+
"rte",
|
|
54
|
+
"plugins"
|
|
55
|
+
],
|
|
56
|
+
"author": "danu20002",
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"homepage": "https://github.com/danu20002/open-text-editor#readme",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/danu20002/open-text-editor/issues"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
},
|
|
65
|
+
"exports": {
|
|
66
|
+
".": {
|
|
67
|
+
"import": "./dist/index.esm.js",
|
|
68
|
+
"require": "./dist/index.cjs.js"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|