@firecms/editor 3.0.0-canary.23 → 3.0.0-canary.231

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/dist/index.umd.js CHANGED
@@ -1,6 +1,1923 @@
1
- (function(u,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("react/jsx-runtime"),require("react"),require("@tiptap/extension-underline"),require("@tiptap/extension-text-style"),require("@tiptap/extension-color"),require("tiptap-markdown"),require("@tiptap/extension-highlight"),require("@tiptap/react"),require("jotai"),require("@radix-ui/react-slot"),require("tunnel-rat"),require("cmdk"),require("@tiptap/starter-kit"),require("@tiptap/extension-horizontal-rule"),require("@tiptap/extension-link"),require("@tiptap/extension-image"),require("@tiptap/extension-placeholder"),require("@tiptap/extension-task-item"),require("@tiptap/extension-task-list"),require("@tiptap/core"),require("@tiptap/suggestion"),require("tippy.js"),require("@firecms/ui"),require("prosemirror-state"),require("@tiptap/pm/view"),require("@tiptap/pm/state")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","@tiptap/extension-underline","@tiptap/extension-text-style","@tiptap/extension-color","tiptap-markdown","@tiptap/extension-highlight","@tiptap/react","jotai","@radix-ui/react-slot","tunnel-rat","cmdk","@tiptap/starter-kit","@tiptap/extension-horizontal-rule","@tiptap/extension-link","@tiptap/extension-image","@tiptap/extension-placeholder","@tiptap/extension-task-item","@tiptap/extension-task-list","@tiptap/core","@tiptap/suggestion","tippy.js","@firecms/ui","prosemirror-state","@tiptap/pm/view","@tiptap/pm/state"],o):(u=typeof globalThis<"u"?globalThis:u||self,o(u["FireCMS Editor"]={},u.jsxRuntime,u.React,u.TiptapUnderline,u.TextStyle,u.extensionColor,u.tiptapMarkdown,u.Highlight,u.react,u.jotai,u.reactSlot,u.tunnel,u.cmdk,u.StarterKit,u.HorizontalRule,u.TiptapLink,u.TiptapImage,u.Placeholder,u.extensionTaskItem,u.extensionTaskList,u.core,u.Suggestion,u.tippy,u.ui,u.prosemirrorState,u.view,u.state))})(this,function(u,o,g,W,Q,Z,_,V,b,y,X,Y,C,J,G,$,j,R,ee,te,w,re,ne,s,oe,A,E){"use strict";const T=y.createStore(),se=({children:e})=>o.jsx(y.Provider,{store:T,children:e}),ae=g.forwardRef(({children:e,tippyOptions:r,...t},n)=>{const{editor:i}=b.useCurrentEditor(),d=g.useRef(null);g.useEffect(()=>{!d.current||!r?.placement||(d.current.setProps({placement:r.placement}),d.current.popperInstance?.update())},[r?.placement]);const a=g.useMemo(()=>({shouldShow:({editor:m,state:p})=>{const{selection:h}=p,{empty:k}=h;return!(m.isActive("image")||k||b.isNodeSelection(h))},tippyOptions:{onCreate:m=>{d.current=m},moveTransition:"transform 0.15s ease-out",...r},...t}),[t,r]);return i?o.jsx("div",{ref:n,children:o.jsx(b.BubbleMenu,{editor:i,...a,children:e})}):null}),S=g.forwardRef(({children:e,asChild:r,onSelect:t,...n},i)=>{const{editor:d}=b.useCurrentEditor(),a=r?X.Slot:"div";return d?o.jsx(a,{ref:i,...n,onClick:()=>t?.(d),children:e}):null});S.displayName="EditorBubbleItem";const q=Y(),D=y.atom(""),z=y.atom(null),ie=({query:e,range:r})=>{const t=y.useSetAtom(D,{store:T}),n=y.useSetAtom(z,{store:T});return g.useEffect(()=>{t(e)},[e,t]),g.useEffect(()=>{n(r)},[r,n]),g.useEffect(()=>{const i=["ArrowUp","ArrowDown","Enter"],d=a=>{if(i.includes(a.key)){a.preventDefault();const c=document.querySelector("#slash-command");c&&c.dispatchEvent(new KeyboardEvent("keydown",{key:a.key,cancelable:!0,bubbles:!0}))}};return document.addEventListener("keydown",d),()=>{document.removeEventListener("keydown",d)}},[]),o.jsx(q.Out,{})},ce=g.forwardRef(({children:e,className:r,...t},n)=>{const i=g.useRef(null),[d,a]=y.useAtom(D);return o.jsx(q.In,{children:o.jsxs(C.Command,{ref:n,onKeyDown:c=>{c.stopPropagation()},id:"slash-command",className:r,...t,children:[o.jsx(C.Command.Input,{value:d,onValueChange:a,style:{display:"none"}}),o.jsx(C.Command.List,{ref:i,children:e})]})})}),F=g.forwardRef(({children:e,onCommand:r,...t},n)=>{const{editor:i}=b.useCurrentEditor(),d=y.useAtomValue(z);return!i||!d?null:o.jsx(C.CommandItem,{ref:n,...t,onSelect:()=>r({editor:i,range:d}),children:e})});F.displayName="EditorCommandItem";const de=C.CommandEmpty,le=w.Extension.create({name:"slash-command",addOptions(){return{suggestion:{char:"/",command:({editor:e,range:r,props:t})=>{t.command({editor:e,range:r})}}}},addProseMirrorPlugins(){return[re({editor:this.editor,...this.options.suggestion})]}}),ue=()=>{let e=null,r=null;return{onStart:t=>{e=new b.ReactRenderer(ie,{props:t,editor:t.editor}),r=ne("body",{getReferenceClientRect:t.clientRect,appendTo:()=>document.body,content:e.element,showOnCreate:!0,interactive:!0,trigger:"manual",placement:"bottom-start"})},onUpdate:t=>{e?.updateProps(t),r&&r[0].setProps({getReferenceClientRect:t.clientRect})},onKeyDown:t=>t.event.key==="Escape"?(r?.[0].hide(),!0):e?.ref?.onKeyDown(t),onExit:()=>{r?.[0].destroy(),e?.destroy()}}},me=e=>e,pe=R.configure({placeholder:({node:e})=>e.type.name==="heading"?`Heading ${e.attrs.level}`:"Press '/' for commands",includeChildren:!0}),ge=G.extend({addInputRules(){return[new w.InputRule({find:/^(?:---|—-|___\s|\*\*\*\s)$/,handler:({state:e,range:r})=>{const t={},{tr:n}=e,i=r.from,d=r.to;n.insert(i-1,this.type.create(t)).delete(n.mapping.map(i),n.mapping.map(d))}})]}}),U=[{name:"Text",icon:s.TextFieldsIcon,command:e=>e?.chain().focus().toggleNode("paragraph","paragraph").run(),isActive:e=>(e?.isActive("paragraph")&&!e?.isActive("bulletList")&&!e?.isActive("orderedList"))??!1},{name:"Heading 1",icon:s.LooksOneIcon,command:e=>e?.chain().focus().toggleHeading({level:1}).run(),isActive:e=>e?.isActive("heading",{level:1})??!1},{name:"Heading 2",icon:s.LooksTwoIcon,command:e=>e?.chain().focus().toggleHeading({level:2}).run(),isActive:e=>e?.isActive("heading",{level:2})??!1},{name:"Heading 3",icon:s.Looks3Icon,command:e=>e?.chain().focus().toggleHeading({level:3}).run(),isActive:e=>e?.isActive("heading",{level:3})??!1},{name:"To-do List",icon:s.CheckBoxIcon,command:e=>e?.chain().focus().toggleTaskList().run(),isActive:e=>e?.isActive("taskItem")??!1},{name:"Bullet List",icon:s.FormatListBulletedIcon,command:e=>e?.chain().focus().toggleBulletList().run(),isActive:e=>e?.isActive("bulletList")??!1},{name:"Numbered List",icon:s.FormatListNumberedIcon,command:e=>e?.chain().focus().toggleOrderedList().run(),isActive:e=>e?.isActive("orderedList")??!1},{name:"Quote",icon:s.FormatQuoteIcon,command:e=>e?.chain().focus().toggleNode("paragraph","paragraph").toggleBlockquote().run(),isActive:e=>e?.isActive("blockquote")??!1},{name:"Code",icon:s.CodeIcon,command:e=>e?.chain().focus().toggleCodeBlock().run(),isActive:e=>e?.isActive("codeBlock")??!1}],fe=({open:e,onOpenChange:r})=>{const{editor:t}=b.useCurrentEditor();if(!t)return null;const n=U.filter(i=>i.isActive(t)).pop()??{name:"Multiple"};return o.jsx(s.Popover,{sideOffset:5,align:"start",className:"w-48 p-1",trigger:o.jsxs(s.Button,{variant:"text",className:"gap-2 rounded-none",color:"text",children:[o.jsx("span",{className:"whitespace-nowrap text-sm",children:n.name}),o.jsx(s.ExpandMoreIcon,{size:"small"})]}),modal:!0,open:e,onOpenChange:r,children:U.map((i,d)=>o.jsxs(S,{onSelect:a=>{i.command(a),r(!1)},className:"flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-blue-50 hover:dark:bg-gray-700 text-gray-900 dark:text-white",children:[o.jsxs("div",{className:"flex items-center space-x-2",children:[o.jsx(i.icon,{size:"smallest"}),o.jsx("span",{children:i.name})]}),n.name===i.name&&o.jsx(s.CheckIcon,{size:"smallest"})]},d))})};function he(e){try{return new URL(e),!0}catch{return!1}}function xe(e){if(he(e))return e;try{return e.includes(".")&&!e.includes(" ")?new URL(`https://${e}`).toString():null}catch{return null}}const ke=({open:e,onOpenChange:r})=>{const t=g.useRef(null),{editor:n}=b.useCurrentEditor();return g.useEffect(()=>{t.current&&t.current?.focus()}),n?o.jsx(s.Popover,{modal:!0,open:e,onOpenChange:r,trigger:o.jsx(s.Button,{variant:"text",className:"gap-2 rounded-none",color:"text",children:o.jsx("p",{className:s.cn("underline decoration-stone-400 underline-offset-4",{"text-blue-500":n.isActive("link")}),children:"Link"})}),children:o.jsxs("form",{onSubmit:i=>{const d=i.currentTarget;i.preventDefault();const a=d[0],c=xe(a.value);c&&n.chain().focus().setLink({href:c}).run()},className:"flex p-1",children:[o.jsx("input",{ref:t,autoFocus:e,placeholder:"Paste a link",defaultValue:n.getAttributes("link").href||"",className:"text-gray-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none"}),n.getAttributes("link").href?o.jsx(s.Button,{size:"small",variant:"text",type:"button",color:"text",className:"flex items-center",onClick:()=>{n.chain().focus().unsetLink().run()},children:o.jsx(s.DeleteIcon,{size:"small"})}):o.jsx(s.Button,{size:"small",variant:"text",children:o.jsx(s.CheckIcon,{size:"small"})})]})}):null},be=()=>{const{editor:e}=b.useCurrentEditor();if(!e)return null;const r=[{name:"bold",isActive:t=>t?.isActive("bold")??!1,command:t=>t?.chain().focus().toggleBold().run(),icon:s.FormatBoldIcon},{name:"italic",isActive:t=>t?.isActive("italic")??!1,command:t=>t?.chain().focus().toggleItalic().run(),icon:s.FormatItalicIcon},{name:"underline",isActive:t=>t?.isActive("underline")??!1,command:t=>t?.chain().focus().toggleUnderline().run(),icon:s.FormatUnderlinedIcon},{name:"strike",isActive:t=>t?.isActive("strike")??!1,command:t=>t?.chain().focus().toggleStrike().run(),icon:s.FormatStrikethroughIcon},{name:"code",isActive:t=>t?.isActive("code")??!1,command:t=>t?.chain().focus().toggleCode().run(),icon:s.CodeIcon}];return o.jsx("div",{className:"flex",children:r.map((t,n)=>o.jsx(S,{onSelect:i=>{t.command(i)},children:o.jsx(s.Button,{size:"small",color:"text",className:"gap-2 rounded-none h-full",variant:"text",children:o.jsx(t.icon,{className:s.cn({"text-inherit":!t.isActive(e),"text-blue-500":t.isActive(e)})})})},n))})};function M(e,r,t,n=300){const i=g.useRef(!1),d=()=>{r(),i.current=!1},a=g.useRef(void 0);g.useEffect(()=>(i.current=!0,clearTimeout(a.current),a.current=setTimeout(d,n),()=>{t&&d()}),[t,e])}function I(e){return Array.isArray(e)?e.map(r=>I(r)):(typeof e=="object"&&e!==null&&(e.attrs&&typeof e.attrs=="object"&&"class"in e.attrs&&delete e.attrs.class,Object.keys(e).forEach(r=>{e[r]=I(e[r])})),e)}const ye=pe,ve=$.configure({HTMLAttributes:{class:s.cn("text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer")}}),Ce=te.TaskList.configure({HTMLAttributes:{class:s.cn("not-prose")}}),we=ee.TaskItem.configure({HTMLAttributes:{class:s.cn("flex items-start my-4")},nested:!0}),Le=ge.configure({HTMLAttributes:{class:s.cn("mt-4 mb-6 border-t",s.defaultBorderMixin)}}),Ae=J.configure({bulletList:{HTMLAttributes:{class:s.cn("list-disc list-outside leading-3 -mt-2")}},orderedList:{HTMLAttributes:{class:s.cn("list-decimal list-outside leading-3 -mt-2")}},listItem:{HTMLAttributes:{class:s.cn("leading-normal -mb-2")}},blockquote:{HTMLAttributes:{class:s.cn("border-l-4 border-primary")}},codeBlock:{HTMLAttributes:{class:s.cn("rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium",s.defaultBorderMixin)}},code:{HTMLAttributes:{class:s.cn("rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium"),spellcheck:"false"}},horizontalRule:!1,dropcursor:{color:"#DBEAFE",width:4},gapcursor:!1});async function K(e,r,t,n,i,d){const{schema:a}=r.state;let c=e.getState(r.state);const m=document.createElement("div"),p=document.createElement("img");p.setAttribute("class","opacity-40 rounded-lg border border-stone-200"),p.src=t.target?.result,m.appendChild(p);const h=A.Decoration.widget(n,m);c=c?.add(r.state.doc,[h]),r.dispatch(r.state.tr.setMeta(e,{decorationSet:c}));const k=await i(d);console.log("uploaded image",k);const x=a.nodes.image.create({src:k}),L=r.state.tr.replaceWith(n,n,x);c=c?.remove([h]),L.setMeta(e,{decorationSet:c}),r.dispatch(L)}const Ee=e=>{const r=new oe.Plugin({state:{init:()=>A.DecorationSet.empty,apply:(t,n)=>{const i=t.getMeta(r);return i&&i.decorationSet?i.decorationSet:n.map(t.mapping,t.doc)}},props:{handleDOMEvents:{drop:(t,n)=>{if(console.log("drop event",n),!n.dataTransfer?.files||n.dataTransfer?.files.length===0)return!1;n.preventDefault();const d=Array.from(n.dataTransfer.files).filter(a=>/image/i.test(a.type));return d.length===0?!1:(d.forEach(a=>{const c=t.posAtCoords({left:n.clientX,top:n.clientY});if(!c)return;const m=new FileReader;m.onload=async p=>{await K(r,t,p,c.pos,e,a)},m.readAsDataURL(a)}),!0)}},handlePaste(t,n,i){const d=Array.from(n.clipboardData?.items||[]),a=t.state.selection.from;console.log("pos",a);let c=!1;return d.forEach(m=>{const p=m.getAsFile();if(console.log("image",p),p){c=!0;const h=new FileReader;h.onload=async k=>{await K(r,t,k,a,e,p)},h.readAsDataURL(p)}}),c},decorations(t){return r.getState(t)}},view(t){return{update(n,i){const d=r.getState(i),a=r.getState(n.state);d!==a&&n.updateState(n.state)}}}});return r},Te=e=>j.extend({addProseMirrorPlugins(){return[Ee(e)]}}).configure({allowBase64:!0,HTMLAttributes:{class:s.cn("rounded-lg border",s.defaultBorderMixin)}}),Se=w.Extension.create({name:"CustomKeymap",addCommands(){return{selectTextWithinNodeBoundaries:()=>({editor:e,commands:r})=>{const{state:t}=e,{tr:n}=t,i=n.selection.$from.start(),d=n.selection.$to.end();return r.setTextSelection({from:i,to:d})}}},addKeyboardShortcuts(){return{"Mod-a":({editor:e})=>{const{state:r}=e,{tr:t}=r,n=t.selection.from,i=t.selection.to,d=t.selection.$from.start(),a=t.selection.$to.end();return n>d||i<a?(e.chain().selectTextWithinNodeBoundaries().run(),!0):!1}}}});function Me(e){const r=e.getBoundingClientRect();return{top:r.top,left:r.left,width:r.width}}function N(e){return document.elementsFromPoint(e.x,e.y).find(r=>r.parentElement?.matches?.(".ProseMirror")||r.matches(["li","p:not(:first-child)","pre","blockquote","h1, h2, h3, h4, h5, h6"].join(", ")))}function O(e,r,t){const n=e.getBoundingClientRect();return r.posAtCoords({left:n.left+50+t.dragHandleWidth,top:n.top+1})?.inside}function Ie(e){function r(a,c){if(c.focus(),!a.dataTransfer)return;const m=N({x:a.clientX+50+e.dragHandleWidth,y:a.clientY});if(!(m instanceof Element))return;const p=O(m,c,e);if(p==null||p<0)return;c.dispatch(c.state.tr.setSelection(E.NodeSelection.create(c.state.doc,p)));const h=c.state.selection.content(),{dom:k,text:x}=A.__serializeForClipboard(c,h);a.dataTransfer.clearData(),a.dataTransfer.setData("text/html",k.innerHTML),a.dataTransfer.setData("text/plain",x),a.dataTransfer.effectAllowed="copyMove",a.dataTransfer.setDragImage(m,0,0),c.dragging={slice:h,move:a.ctrlKey}}function t(a,c){c.focus(),c.dom.classList.remove("dragging");const m=N({x:a.clientX+50+e.dragHandleWidth,y:a.clientY});if(!(m instanceof Element))return;const p=O(m,c,e);p&&c.dispatch(c.state.tr.setSelection(E.NodeSelection.create(c.state.doc,p)))}let n=null;function i(){n&&n.classList.add("hide")}function d(){n&&n.classList.remove("hide")}return new E.Plugin({view:a=>(n=document.createElement("div"),n.draggable=!0,n.dataset.dragHandle="",n.classList.add("drag-handle"),n.addEventListener("dragstart",c=>{r(c,a)}),n.addEventListener("click",c=>{t(c,a)}),i(),a?.dom?.parentElement?.appendChild(n),{destroy:()=>{n?.remove?.(),n=null}}),props:{handleDOMEvents:{mousemove:(a,c)=>{if(!a.editable)return;const m=N({x:c.clientX+50+e.dragHandleWidth,y:c.clientY});if(!(m instanceof Element)){i();return}const p=window.getComputedStyle(m),h=parseInt(p.lineHeight,10),k=parseInt(p.paddingTop,10),x=Me(m);x.top+=(h-24)/2,x.top+=k,m.matches("ul:not([data-type=taskList]) li, ol li")&&(x.left-=e.dragHandleWidth),x.width=e.dragHandleWidth,n&&(n.style.left=`${x.left-x.width}px`,n.style.top=`${x.top}px`,d())},keydown:()=>{i()},mousewheel:()=>{i()},dragstart:a=>{a.dom.classList.add("dragging")},drop:a=>{a.dom.classList.remove("dragging")},dragend:a=>{a.dom.classList.remove("dragging")}}}})}const Ne=w.Extension.create({name:"dragAndDrop",addProseMirrorPlugins(){return[Ie({dragHandleWidth:24})]}}),Pe=({handleImageUpload:e,initialContent:r,onJsonContentChange:t,onHtmlContentChange:n,onMarkdownContentChange:i})=>{const d={handleDOMEvents:{keydown:(l,f)=>!!(["ArrowUp","ArrowDown","Enter"].includes(f.key)&&document.querySelector("#slash-command"))}},a=me([{title:"Text",description:"Just start typing with plain text.",searchTerms:["p","paragraph"],icon:o.jsx(s.TextFieldsIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).toggleNode("paragraph","paragraph").run()}},{title:"To-do List",description:"Track tasks with a to-do list.",searchTerms:["todo","task","list","check","checkbox"],icon:o.jsx(s.CheckBoxIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).toggleTaskList().run()}},{title:"Heading 1",description:"Big section heading.",searchTerms:["title","big","large"],icon:o.jsx(s.LooksOneIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).setNode("heading",{level:1}).run()}},{title:"Heading 2",description:"Medium section heading.",searchTerms:["subtitle","medium"],icon:o.jsx(s.LooksTwoIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).setNode("heading",{level:2}).run()}},{title:"Heading 3",description:"Small section heading.",searchTerms:["subtitle","small"],icon:o.jsx(s.Looks3Icon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).setNode("heading",{level:3}).run()}},{title:"Bullet List",description:"Create a simple bullet list.",searchTerms:["unordered","point"],icon:o.jsx(s.FormatListBulletedIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).toggleBulletList().run()}},{title:"Numbered List",description:"Create a list with numbering.",searchTerms:["ordered"],icon:o.jsx(s.FormatListNumberedIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).toggleOrderedList().run()}},{title:"Quote",description:"Capture a quote.",searchTerms:["blockquote"],icon:o.jsx(s.FormatQuoteIcon,{size:18}),command:({editor:l,range:f})=>l.chain().focus().deleteRange(f).toggleNode("paragraph","paragraph").toggleBlockquote().run()},{title:"Code",description:"Capture a code snippet.",searchTerms:["codeblock"],icon:o.jsx(s.CodeIcon,{size:18}),command:({editor:l,range:f})=>l.chain().focus().deleteRange(f).toggleCodeBlock().run()},{title:"Image",description:"Upload an image from your computer.",searchTerms:["photo","picture","media"],icon:o.jsx(s.ImageIcon,{size:18}),command:({editor:l,range:f})=>{l.chain().focus().deleteRange(f).run();const v=document.createElement("input");v.type="file",v.accept="image/*",v.onchange=async()=>{if(v.files?.length){if(!v.files[0])return;l.view.state.selection.from}},v.click()}}]),c=le.configure({suggestion:{items:()=>a,render:ue}}),m=g.useMemo(()=>Te(e),[]),p=[W,Q,Z.Color,V.configure({multicolor:!0}),_.Markdown.configure({html:!1,transformCopiedText:!0}),Se,Ne,Ae,ye,ve,m,Ce,we,Le,c],[h,k]=g.useState(!1),[x,L]=g.useState(!1);s.useInjectStyles("Editor",He);const P=g.useRef(null),[qe,De]=g.useState(null),[B,ze]=g.useState(null),[H,Fe]=g.useState(null),Ue=l=>{P.current=l,i&&De(l.storage.markdown.getMarkdown()),t&&ze(I(l.getJSON())),n&&Fe(l.getHTML())};return M(qe,()=>{if(P.current){const l=P.current.storage.markdown.getMarkdown();i?.(Be(l))}},!1,500),M(B,()=>{B&&t?.(B)},!1,500),M(H,()=>{H&&n?.(H)},!1,500),r?o.jsx("div",{className:"relative w-full p-8",children:o.jsx(se,{children:o.jsx("div",{className:"relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg",children:o.jsxs(b.EditorProvider,{content:r,extensions:p,editorProps:{...d,attributes:{class:"prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12"}},onUpdate:({editor:l})=>{console.log("editor updated"),Ue(l)},children:[o.jsxs(ce,{className:s.cn("text-gray-900 dark:text-white z-50 h-auto max-h-[330px] w-72 overflow-y-auto rounded-md border bg-white dark:bg-gray-900 px-1 py-2 shadow transition-all",s.defaultBorderMixin),children:[o.jsx(de,{className:"px-2 text-gray-700 dark:text-slate-300",children:"No results"}),a.map(l=>o.jsxs(F,{value:l.title,onCommand:f=>l?.command?.(f),className:"flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-gray-700 aria-selected:bg-blue-50 aria-selected:dark:bg-gray-700",children:[o.jsx("div",{className:s.cn("flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-gray-900",s.defaultBorderMixin),children:l.icon}),o.jsxs("div",{children:[o.jsx("p",{className:"font-medium",children:l.title}),o.jsx("p",{className:"text-xs text-gray-700 dark:text-slate-300",children:l.description})]})]},l.title))]}),o.jsxs(ae,{tippyOptions:{placement:"top"},className:s.cn("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow",s.defaultBorderMixin),children:[o.jsx(fe,{open:h,onOpenChange:k}),o.jsx(s.Separator,{orientation:"vertical"}),o.jsx(ke,{open:x,onOpenChange:L}),o.jsx(s.Separator,{orientation:"vertical"}),o.jsx(be,{})]})]})})})}):null};function Be(e){const r=/!\[.*?\]\(.*?\)/g;return e.replace(r,t=>`${t}
2
- `)}const He=`
3
-
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("react"), require("@firecms/ui"), require("@tiptap/react"), require("@tiptap/extension-document"), require("tiptap-markdown"), require("@tiptap/extension-underline"), require("@tiptap/extension-heading"), require("@tiptap/extension-text-style"), require("@tiptap/extension-color"), require("@tiptap/extension-highlight"), require("@tiptap/extension-bold"), require("@tiptap/extension-italic"), require("@tiptap/extension-strike"), require("react-compiler-runtime"), require("@radix-ui/react-slot"), require("@tiptap/starter-kit"), require("@tiptap/extension-horizontal-rule"), require("@tiptap/extension-link"), require("@tiptap/extension-image"), require("@tiptap/extension-placeholder"), require("@tiptap/extension-task-item"), require("@tiptap/extension-task-list"), require("@tiptap/core"), require("prosemirror-state"), require("prosemirror-view"), require("@tiptap/extension-ordered-list"), require("@tiptap/extension-bullet-list"), require("@tiptap/extension-list-item"), require("@tiptap/extension-code-block"), require("@tiptap/extension-blockquote"), require("@tiptap/extension-code"), require("@tiptap/pm/view"), require("@tiptap/pm/state"), require("@tiptap/suggestion"), require("tippy.js")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "react", "@firecms/ui", "@tiptap/react", "@tiptap/extension-document", "tiptap-markdown", "@tiptap/extension-underline", "@tiptap/extension-heading", "@tiptap/extension-text-style", "@tiptap/extension-color", "@tiptap/extension-highlight", "@tiptap/extension-bold", "@tiptap/extension-italic", "@tiptap/extension-strike", "react-compiler-runtime", "@radix-ui/react-slot", "@tiptap/starter-kit", "@tiptap/extension-horizontal-rule", "@tiptap/extension-link", "@tiptap/extension-image", "@tiptap/extension-placeholder", "@tiptap/extension-task-item", "@tiptap/extension-task-list", "@tiptap/core", "prosemirror-state", "prosemirror-view", "@tiptap/extension-ordered-list", "@tiptap/extension-bullet-list", "@tiptap/extension-list-item", "@tiptap/extension-code-block", "@tiptap/extension-blockquote", "@tiptap/extension-code", "@tiptap/pm/view", "@tiptap/pm/state", "@tiptap/suggestion", "tippy.js"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["FireCMS Editor"] = {}, global.jsxRuntime, global.React, global.ui, global.react, global.Document, global.tiptapMarkdown, global.Underline, global.Heading, global.TextStyle, global.Color, global.Highlight, global.Bold, global.Italic, global.Strike, global.reactCompilerRuntime, global.reactSlot, global.StarterKit, global.HorizontalRule, global.TiptapLink, global.TiptapImage, global.Placeholder, global.extensionTaskItem, global.extensionTaskList, global.core, global.prosemirrorState, global.prosemirrorView, global.OrderedList, global.BulletList, global.ListItem, global.CodeBlock, global.Blockquote, global.Code, global.view, global.state, global.Suggestion, global.tippy));
3
+ })(this, function(exports2, jsxRuntime, React, ui, react, Document, tiptapMarkdown, Underline, Heading, TextStyle, Color, Highlight, Bold, Italic, Strike, reactCompilerRuntime, reactSlot, StarterKit, HorizontalRule, TiptapLink, TiptapImage, Placeholder, extensionTaskItem, extensionTaskList, core, prosemirrorState, prosemirrorView, OrderedList, BulletList, ListItem, CodeBlock, Blockquote, Code, view, state, Suggestion, tippy) {
4
+ "use strict";
5
+ const EditorBubble = React.forwardRef((t0, ref) => {
6
+ const $ = reactCompilerRuntime.c(21);
7
+ let children;
8
+ let rest;
9
+ let tippyOptions;
10
+ if ($[0] !== t0) {
11
+ ({
12
+ children,
13
+ tippyOptions,
14
+ ...rest
15
+ } = t0);
16
+ $[0] = t0;
17
+ $[1] = children;
18
+ $[2] = rest;
19
+ $[3] = tippyOptions;
20
+ } else {
21
+ children = $[1];
22
+ rest = $[2];
23
+ tippyOptions = $[3];
24
+ }
25
+ const {
26
+ editor
27
+ } = react.useCurrentEditor();
28
+ const instanceRef = React.useRef(null);
29
+ let t1;
30
+ if ($[4] !== tippyOptions) {
31
+ t1 = () => {
32
+ if (!instanceRef.current || !tippyOptions?.placement) {
33
+ return;
34
+ }
35
+ instanceRef.current.setProps({
36
+ placement: tippyOptions.placement
37
+ });
38
+ instanceRef.current.popperInstance?.update();
39
+ };
40
+ $[4] = tippyOptions;
41
+ $[5] = t1;
42
+ } else {
43
+ t1 = $[5];
44
+ }
45
+ const t2 = tippyOptions?.placement;
46
+ let t3;
47
+ if ($[6] !== t2) {
48
+ t3 = [t2];
49
+ $[6] = t2;
50
+ $[7] = t3;
51
+ } else {
52
+ t3 = $[7];
53
+ }
54
+ React.useEffect(t1, t3);
55
+ let t4;
56
+ const shouldShow = _temp$1;
57
+ let t5;
58
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
59
+ t5 = (val) => {
60
+ instanceRef.current = val;
61
+ };
62
+ $[8] = t5;
63
+ } else {
64
+ t5 = $[8];
65
+ }
66
+ let t6;
67
+ if ($[9] !== tippyOptions) {
68
+ t6 = {
69
+ onCreate: t5,
70
+ moveTransition: "transform 0.15s ease-out",
71
+ ...tippyOptions
72
+ };
73
+ $[9] = tippyOptions;
74
+ $[10] = t6;
75
+ } else {
76
+ t6 = $[10];
77
+ }
78
+ let t7;
79
+ if ($[11] !== rest || $[12] !== t6) {
80
+ t7 = {
81
+ shouldShow,
82
+ tippyOptions: t6,
83
+ ...rest
84
+ };
85
+ $[11] = rest;
86
+ $[12] = t6;
87
+ $[13] = t7;
88
+ } else {
89
+ t7 = $[13];
90
+ }
91
+ t4 = t7;
92
+ const bubbleMenuProps = t4;
93
+ if (!editor) {
94
+ return null;
95
+ }
96
+ let t8;
97
+ if ($[14] !== bubbleMenuProps || $[15] !== children || $[16] !== editor) {
98
+ t8 = /* @__PURE__ */ jsxRuntime.jsx(react.BubbleMenu, { editor, ...bubbleMenuProps, children });
99
+ $[14] = bubbleMenuProps;
100
+ $[15] = children;
101
+ $[16] = editor;
102
+ $[17] = t8;
103
+ } else {
104
+ t8 = $[17];
105
+ }
106
+ let t9;
107
+ if ($[18] !== ref || $[19] !== t8) {
108
+ t9 = /* @__PURE__ */ jsxRuntime.jsx("div", { ref, children: t8 });
109
+ $[18] = ref;
110
+ $[19] = t8;
111
+ $[20] = t9;
112
+ } else {
113
+ t9 = $[20];
114
+ }
115
+ return t9;
116
+ });
117
+ function _temp$1(t0) {
118
+ const {
119
+ editor: editor_0,
120
+ state: state2
121
+ } = t0;
122
+ const {
123
+ selection
124
+ } = state2;
125
+ const {
126
+ empty
127
+ } = selection;
128
+ if (editor_0.isActive("image") || empty || react.isNodeSelection(selection)) {
129
+ return false;
130
+ }
131
+ return true;
132
+ }
133
+ const EditorBubbleItem = React.forwardRef((t0, ref) => {
134
+ const $ = reactCompilerRuntime.c(14);
135
+ let asChild;
136
+ let children;
137
+ let onSelect;
138
+ let rest;
139
+ if ($[0] !== t0) {
140
+ ({
141
+ children,
142
+ asChild,
143
+ onSelect,
144
+ ...rest
145
+ } = t0);
146
+ $[0] = t0;
147
+ $[1] = asChild;
148
+ $[2] = children;
149
+ $[3] = onSelect;
150
+ $[4] = rest;
151
+ } else {
152
+ asChild = $[1];
153
+ children = $[2];
154
+ onSelect = $[3];
155
+ rest = $[4];
156
+ }
157
+ const {
158
+ editor
159
+ } = react.useCurrentEditor();
160
+ const Comp = asChild ? reactSlot.Slot : "div";
161
+ if (!editor) {
162
+ return null;
163
+ }
164
+ let t1;
165
+ if ($[5] !== editor || $[6] !== onSelect) {
166
+ t1 = () => onSelect?.(editor);
167
+ $[5] = editor;
168
+ $[6] = onSelect;
169
+ $[7] = t1;
170
+ } else {
171
+ t1 = $[7];
172
+ }
173
+ let t2;
174
+ if ($[8] !== Comp || $[9] !== children || $[10] !== ref || $[11] !== rest || $[12] !== t1) {
175
+ t2 = /* @__PURE__ */ jsxRuntime.jsx(Comp, { ref, ...rest, onClick: t1, children });
176
+ $[8] = Comp;
177
+ $[9] = children;
178
+ $[10] = ref;
179
+ $[11] = rest;
180
+ $[12] = t1;
181
+ $[13] = t2;
182
+ } else {
183
+ t2 = $[13];
184
+ }
185
+ return t2;
186
+ });
187
+ EditorBubbleItem.displayName = "EditorBubbleItem";
188
+ const items = [{
189
+ name: "Text",
190
+ icon: ui.TextFieldsIcon,
191
+ command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").run(),
192
+ // I feel like there has to be a more efficient way to do this – feel free to PR if you know how!
193
+ isActive: (editor) => (editor?.isActive("paragraph") && !editor?.isActive("bulletList") && !editor?.isActive("orderedList")) ?? false
194
+ }, {
195
+ name: "Heading 1",
196
+ icon: ui.LooksOneIcon,
197
+ command: (editor) => editor?.chain().focus().toggleHeading({
198
+ level: 1
199
+ }).run(),
200
+ isActive: (editor) => editor?.isActive("heading", {
201
+ level: 1
202
+ }) ?? false
203
+ }, {
204
+ name: "Heading 2",
205
+ icon: ui.LooksTwoIcon,
206
+ command: (editor) => editor?.chain().focus().toggleHeading({
207
+ level: 2
208
+ }).run(),
209
+ isActive: (editor) => editor?.isActive("heading", {
210
+ level: 2
211
+ }) ?? false
212
+ }, {
213
+ name: "Heading 3",
214
+ icon: ui.Looks3Icon,
215
+ command: (editor) => editor?.chain().focus().toggleHeading({
216
+ level: 3
217
+ }).run(),
218
+ isActive: (editor) => editor?.isActive("heading", {
219
+ level: 3
220
+ }) ?? false
221
+ }, {
222
+ name: "To-do List",
223
+ icon: ui.CheckBoxIcon,
224
+ command: (editor) => editor?.chain().focus().toggleTaskList().run(),
225
+ isActive: (editor) => editor?.isActive("taskItem") ?? false
226
+ }, {
227
+ name: "Bullet List",
228
+ icon: ui.FormatListBulletedIcon,
229
+ command: (editor) => editor?.chain().focus().toggleBulletList().run(),
230
+ isActive: (editor) => editor?.isActive("bulletList") ?? false
231
+ }, {
232
+ name: "Numbered List",
233
+ icon: ui.FormatListNumberedIcon,
234
+ command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
235
+ isActive: (editor) => editor?.isActive("orderedList") ?? false
236
+ }, {
237
+ name: "Quote",
238
+ icon: ui.FormatQuoteIcon,
239
+ command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
240
+ isActive: (editor) => editor?.isActive("blockquote") ?? false
241
+ }, {
242
+ name: "Code",
243
+ icon: ui.CodeIcon,
244
+ command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
245
+ isActive: (editor) => editor?.isActive("codeBlock") ?? false
246
+ }];
247
+ const NodeSelector = (t0) => {
248
+ const $ = reactCompilerRuntime.c(16);
249
+ const {
250
+ open,
251
+ onOpenChange,
252
+ portalContainer
253
+ } = t0;
254
+ const {
255
+ editor
256
+ } = react.useCurrentEditor();
257
+ if (!editor) {
258
+ return null;
259
+ }
260
+ let t1;
261
+ if ($[0] !== editor) {
262
+ t1 = items.filter((item) => item.isActive(editor)).pop() ?? {
263
+ name: "Multiple"
264
+ };
265
+ $[0] = editor;
266
+ $[1] = t1;
267
+ } else {
268
+ t1 = $[1];
269
+ }
270
+ const activeItem = t1;
271
+ let t2;
272
+ if ($[2] !== activeItem.name) {
273
+ t2 = /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap text-sm", children: activeItem.name });
274
+ $[2] = activeItem.name;
275
+ $[3] = t2;
276
+ } else {
277
+ t2 = $[3];
278
+ }
279
+ let t3;
280
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
281
+ t3 = /* @__PURE__ */ jsxRuntime.jsx(ui.KeyboardArrowDownIcon, { size: "small" });
282
+ $[4] = t3;
283
+ } else {
284
+ t3 = $[4];
285
+ }
286
+ let t4;
287
+ if ($[5] !== t2) {
288
+ t4 = /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "text", className: "gap-2 rounded-none", color: "text", children: [
289
+ t2,
290
+ t3
291
+ ] });
292
+ $[5] = t2;
293
+ $[6] = t4;
294
+ } else {
295
+ t4 = $[6];
296
+ }
297
+ let t5;
298
+ if ($[7] !== activeItem.name || $[8] !== onOpenChange) {
299
+ t5 = items.map((item_0, index) => /* @__PURE__ */ jsxRuntime.jsxs(EditorBubbleItem, { onSelect: (editor_0) => {
300
+ item_0.command(editor_0);
301
+ onOpenChange(false);
302
+ }, className: "flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-blue-50 hover:dark:bg-surface-700 text-surface-900 dark:text-white", children: [
303
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
304
+ /* @__PURE__ */ jsxRuntime.jsx(item_0.icon, { size: "smallest" }),
305
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item_0.name })
306
+ ] }),
307
+ activeItem.name === item_0.name && /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" })
308
+ ] }, index));
309
+ $[7] = activeItem.name;
310
+ $[8] = onOpenChange;
311
+ $[9] = t5;
312
+ } else {
313
+ t5 = $[9];
314
+ }
315
+ let t6;
316
+ if ($[10] !== onOpenChange || $[11] !== open || $[12] !== portalContainer || $[13] !== t4 || $[14] !== t5) {
317
+ t6 = /* @__PURE__ */ jsxRuntime.jsx(ui.Popover, { sideOffset: 5, align: "start", portalContainer, className: "w-48 p-1", trigger: t4, modal: true, open, onOpenChange, children: t5 });
318
+ $[10] = onOpenChange;
319
+ $[11] = open;
320
+ $[12] = portalContainer;
321
+ $[13] = t4;
322
+ $[14] = t5;
323
+ $[15] = t6;
324
+ } else {
325
+ t6 = $[15];
326
+ }
327
+ return t6;
328
+ };
329
+ function isValidUrl(url) {
330
+ try {
331
+ new URL(url);
332
+ return true;
333
+ } catch (e) {
334
+ return false;
335
+ }
336
+ }
337
+ function getUrlFromString(str) {
338
+ if (isValidUrl(str)) return str;
339
+ try {
340
+ if (str.includes(".") && !str.includes(" ")) {
341
+ return new URL(`https://${str}`).toString();
342
+ }
343
+ return null;
344
+ } catch (e) {
345
+ return null;
346
+ }
347
+ }
348
+ const LinkSelector = (t0) => {
349
+ const $ = reactCompilerRuntime.c(24);
350
+ const {
351
+ open,
352
+ onOpenChange
353
+ } = t0;
354
+ const inputRef = React.useRef(null);
355
+ const {
356
+ editor
357
+ } = react.useCurrentEditor();
358
+ let t1;
359
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
360
+ t1 = () => {
361
+ inputRef.current && inputRef.current?.focus();
362
+ };
363
+ $[0] = t1;
364
+ } else {
365
+ t1 = $[0];
366
+ }
367
+ React.useEffect(t1);
368
+ if (!editor) {
369
+ return null;
370
+ }
371
+ let t2;
372
+ if ($[1] !== editor) {
373
+ t2 = ui.cls("underline decoration-stone-400 underline-offset-4", {
374
+ "text-blue-500": editor.isActive("link")
375
+ });
376
+ $[1] = editor;
377
+ $[2] = t2;
378
+ } else {
379
+ t2 = $[2];
380
+ }
381
+ let t3;
382
+ if ($[3] !== t2) {
383
+ t3 = /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "text", className: "gap-2 rounded-none", color: "text", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: t2, children: "Link" }) });
384
+ $[3] = t2;
385
+ $[4] = t3;
386
+ } else {
387
+ t3 = $[4];
388
+ }
389
+ let t4;
390
+ if ($[5] !== editor) {
391
+ t4 = (e) => {
392
+ const target = e.currentTarget;
393
+ e.preventDefault();
394
+ const input = target[0];
395
+ const url = getUrlFromString(input.value);
396
+ url && editor.chain().focus().setLink({
397
+ href: url
398
+ }).run();
399
+ };
400
+ $[5] = editor;
401
+ $[6] = t4;
402
+ } else {
403
+ t4 = $[6];
404
+ }
405
+ let t5;
406
+ if ($[7] !== editor) {
407
+ t5 = editor.getAttributes("link").href || "";
408
+ $[7] = editor;
409
+ $[8] = t5;
410
+ } else {
411
+ t5 = $[8];
412
+ }
413
+ let t6;
414
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
415
+ t6 = ui.cls("text-surface-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none", ui.focusedDisabled);
416
+ $[9] = t6;
417
+ } else {
418
+ t6 = $[9];
419
+ }
420
+ let t7;
421
+ if ($[10] !== open || $[11] !== t5) {
422
+ t7 = /* @__PURE__ */ jsxRuntime.jsx("input", { ref: inputRef, autoFocus: open, placeholder: "Paste a link", defaultValue: t5, className: t6 });
423
+ $[10] = open;
424
+ $[11] = t5;
425
+ $[12] = t7;
426
+ } else {
427
+ t7 = $[12];
428
+ }
429
+ let t8;
430
+ if ($[13] !== editor) {
431
+ t8 = editor.getAttributes("link").href ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "text", type: "button", color: "text", className: "flex items-center", onClick: () => {
432
+ editor.chain().focus().unsetLink().run();
433
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DeleteIcon, { size: "small" }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "text", children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "small" }) });
434
+ $[13] = editor;
435
+ $[14] = t8;
436
+ } else {
437
+ t8 = $[14];
438
+ }
439
+ let t9;
440
+ if ($[15] !== t4 || $[16] !== t7 || $[17] !== t8) {
441
+ t9 = /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: t4, className: "flex p-1", children: [
442
+ t7,
443
+ t8
444
+ ] });
445
+ $[15] = t4;
446
+ $[16] = t7;
447
+ $[17] = t8;
448
+ $[18] = t9;
449
+ } else {
450
+ t9 = $[18];
451
+ }
452
+ let t10;
453
+ if ($[19] !== onOpenChange || $[20] !== open || $[21] !== t3 || $[22] !== t9) {
454
+ t10 = /* @__PURE__ */ jsxRuntime.jsx(ui.Popover, { modal: true, open, onOpenChange, trigger: t3, children: t9 });
455
+ $[19] = onOpenChange;
456
+ $[20] = open;
457
+ $[21] = t3;
458
+ $[22] = t9;
459
+ $[23] = t10;
460
+ } else {
461
+ t10 = $[23];
462
+ }
463
+ return t10;
464
+ };
465
+ const TextButtons = () => {
466
+ const $ = reactCompilerRuntime.c(2);
467
+ const {
468
+ editor
469
+ } = react.useCurrentEditor();
470
+ if (!editor) {
471
+ return null;
472
+ }
473
+ let t0;
474
+ if ($[0] !== editor) {
475
+ const items2 = [{
476
+ name: "bold",
477
+ isActive: _temp,
478
+ command: _temp2,
479
+ icon: ui.FormatBoldIcon
480
+ }, {
481
+ name: "italic",
482
+ isActive: _temp3,
483
+ command: _temp4,
484
+ icon: ui.FormatItalicIcon
485
+ }, {
486
+ name: "underline",
487
+ isActive: _temp5,
488
+ command: _temp6,
489
+ icon: ui.FormatUnderlinedIcon
490
+ }, {
491
+ name: "strike",
492
+ isActive: _temp7,
493
+ command: _temp8,
494
+ icon: ui.FormatStrikethroughIcon
495
+ }, {
496
+ name: "code",
497
+ isActive: _temp9,
498
+ command: _temp10,
499
+ icon: ui.CodeIcon
500
+ }];
501
+ t0 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: items2.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(EditorBubbleItem, { onSelect: (editor_10) => {
502
+ item.command(editor_10);
503
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", color: "text", className: "gap-2 rounded-none h-full", variant: "text", children: /* @__PURE__ */ jsxRuntime.jsx(item.icon, { className: ui.cls({
504
+ "text-inherit": !item.isActive(editor),
505
+ "text-blue-500": item.isActive(editor)
506
+ }) }) }) }, index)) });
507
+ $[0] = editor;
508
+ $[1] = t0;
509
+ } else {
510
+ t0 = $[1];
511
+ }
512
+ return t0;
513
+ };
514
+ function _temp(editor_0) {
515
+ return editor_0?.isActive("bold") ?? false;
516
+ }
517
+ function _temp2(editor_1) {
518
+ return editor_1?.chain().focus().toggleBold().run();
519
+ }
520
+ function _temp3(editor_2) {
521
+ return editor_2?.isActive("italic") ?? false;
522
+ }
523
+ function _temp4(editor_3) {
524
+ return editor_3?.chain().focus().toggleItalic().run();
525
+ }
526
+ function _temp5(editor_4) {
527
+ return editor_4?.isActive("underline") ?? false;
528
+ }
529
+ function _temp6(editor_5) {
530
+ return editor_5?.chain().focus().toggleUnderline().run();
531
+ }
532
+ function _temp7(editor_6) {
533
+ return editor_6?.isActive("strike") ?? false;
534
+ }
535
+ function _temp8(editor_7) {
536
+ return editor_7?.chain().focus().toggleStrike().run();
537
+ }
538
+ function _temp9(editor_8) {
539
+ return editor_8?.isActive("code") ?? false;
540
+ }
541
+ function _temp10(editor_9) {
542
+ return editor_9?.chain().focus().toggleCode().run();
543
+ }
544
+ function removeClassesFromJson(jsonObj) {
545
+ if (Array.isArray(jsonObj)) {
546
+ return jsonObj.map((item) => removeClassesFromJson(item));
547
+ } else if (typeof jsonObj === "object" && jsonObj !== null) {
548
+ if (jsonObj.attrs && typeof jsonObj.attrs === "object" && "class" in jsonObj.attrs) {
549
+ delete jsonObj.attrs.class;
550
+ }
551
+ Object.keys(jsonObj).forEach((key) => {
552
+ jsonObj[key] = removeClassesFromJson(jsonObj[key]);
553
+ });
554
+ }
555
+ return jsonObj;
556
+ }
557
+ const loadingDecorationKey = new prosemirrorState.PluginKey("loadingDecoration");
558
+ const TextLoadingDecorationExtension = core.Extension.create({
559
+ name: "loadingDecoration",
560
+ addOptions() {
561
+ return {
562
+ pluginKey: loadingDecorationKey
563
+ };
564
+ },
565
+ addProseMirrorPlugins() {
566
+ const pluginKey = this.options.pluginKey;
567
+ return [new prosemirrorState.Plugin({
568
+ key: pluginKey,
569
+ state: {
570
+ init() {
571
+ return {
572
+ decorationSet: prosemirrorView.DecorationSet.empty,
573
+ hasDecoration: false
574
+ };
575
+ },
576
+ apply(tr, oldState) {
577
+ const action = tr.getMeta(pluginKey);
578
+ if (action?.type === "loadingDecoration") {
579
+ const {
580
+ pos,
581
+ remove,
582
+ loadingHtml
583
+ } = action;
584
+ if (remove) {
585
+ return {
586
+ decorationSet: prosemirrorView.DecorationSet.empty,
587
+ hasDecoration: false
588
+ };
589
+ }
590
+ const decoration = prosemirrorView.Decoration.widget(pos, () => {
591
+ const container = document.createElement("span");
592
+ container.className = "loading-decoration";
593
+ if (loadingHtml) {
594
+ container.innerHTML = loadingHtml;
595
+ } else {
596
+ const span = document.createElement("span");
597
+ span.innerText = "loading...";
598
+ container.appendChild(span);
599
+ }
600
+ return container;
601
+ });
602
+ return {
603
+ decorationSet: prosemirrorView.DecorationSet.empty.add(tr.doc, [decoration]),
604
+ hasDecoration: true
605
+ };
606
+ }
607
+ return {
608
+ decorationSet: oldState.decorationSet.map(tr.mapping, tr.doc),
609
+ hasDecoration: oldState.hasDecoration
610
+ };
611
+ }
612
+ },
613
+ props: {
614
+ decorations(state2) {
615
+ return this.getState(state2)?.decorationSet || prosemirrorView.DecorationSet.empty;
616
+ }
617
+ }
618
+ })];
619
+ },
620
+ addCommands() {
621
+ return {
622
+ toggleLoadingDecoration: (loadingHtml) => ({
623
+ state: state2,
624
+ dispatch
625
+ }) => {
626
+ const {
627
+ selection
628
+ } = state2;
629
+ const pos = selection.from;
630
+ if (!dispatch) return false;
631
+ const pluginKey = this.options.pluginKey;
632
+ const tr = state2.tr.setMeta(pluginKey, {
633
+ pos,
634
+ type: "loadingDecoration",
635
+ remove: false,
636
+ loadingHtml
637
+ });
638
+ dispatch(tr);
639
+ return true;
640
+ },
641
+ removeLoadingDecoration: () => ({
642
+ state: state2,
643
+ dispatch
644
+ }) => {
645
+ if (!dispatch) return false;
646
+ const pluginKey = this.options.pluginKey;
647
+ const tr = state2.tr.setMeta(pluginKey, {
648
+ pos: 0,
649
+ // We can pass any position as it will remove the entire decoration set
650
+ type: "loadingDecoration",
651
+ remove: true
652
+ });
653
+ dispatch(tr);
654
+ return true;
655
+ }
656
+ };
657
+ }
658
+ });
659
+ const PlaceholderExtension = Placeholder.configure({
660
+ placeholder: ({
661
+ node,
662
+ editor
663
+ }) => {
664
+ editor.state.selection;
665
+ function hasLoadingDecoration(editor2) {
666
+ const pluginState = loadingDecorationKey.get(editor2.state);
667
+ return pluginState?.getState(editor2.state)?.hasDecoration ?? false;
668
+ }
669
+ const hasDecoration = hasLoadingDecoration(editor);
670
+ if (hasDecoration) {
671
+ return "";
672
+ }
673
+ if (node.type.name === "heading") {
674
+ return `Heading ${node.attrs.level}`;
675
+ }
676
+ if (node.type.name === "paragraph") {
677
+ return "Press '/' for commands";
678
+ }
679
+ return "";
680
+ },
681
+ includeChildren: true
682
+ });
683
+ const Horizontal = HorizontalRule.extend({
684
+ addInputRules() {
685
+ return [new core.InputRule({
686
+ find: /^(?:---|—-|___\s|\*\*\*\s)$/,
687
+ handler: ({
688
+ state: state2,
689
+ range
690
+ }) => {
691
+ const attributes = {};
692
+ const {
693
+ tr
694
+ } = state2;
695
+ const start = range.from;
696
+ const end = range.to;
697
+ tr.insert(start - 1, this.type.create(attributes)).delete(tr.mapping.map(start), tr.mapping.map(end));
698
+ }
699
+ })];
700
+ }
701
+ });
702
+ const placeholder = PlaceholderExtension;
703
+ const tiptapLink = TiptapLink.configure({
704
+ HTMLAttributes: {
705
+ class: ui.cls("text-surface-700 dark:text-surface-accent-200 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer")
706
+ }
707
+ });
708
+ const taskList = extensionTaskList.TaskList.configure({
709
+ HTMLAttributes: {
710
+ class: ui.cls("not-prose")
711
+ }
712
+ });
713
+ const taskItem = extensionTaskItem.TaskItem.configure({
714
+ HTMLAttributes: {
715
+ class: ui.cls("flex items-start my-4")
716
+ },
717
+ nested: true
718
+ });
719
+ const horizontalRule = Horizontal.configure({
720
+ HTMLAttributes: {
721
+ class: ui.cls("mt-4 mb-6 border-t", ui.defaultBorderMixin)
722
+ }
723
+ });
724
+ const bulletList = BulletList.configure({
725
+ HTMLAttributes: {
726
+ class: ui.cls("list-disc list-outside leading-3 -mt-2")
727
+ }
728
+ });
729
+ const orderedList = OrderedList.configure({
730
+ HTMLAttributes: {
731
+ class: ui.cls("list-decimal list-outside leading-3 -mt-2")
732
+ }
733
+ });
734
+ const listItem = ListItem.configure({
735
+ HTMLAttributes: {
736
+ class: ui.cls("leading-normal -mb-2")
737
+ }
738
+ });
739
+ const blockquote = Blockquote.configure({
740
+ HTMLAttributes: {
741
+ class: ui.cls("border-l-4 border-primary")
742
+ }
743
+ });
744
+ const codeBlock = CodeBlock.configure({
745
+ HTMLAttributes: {
746
+ class: ui.cls("rounded bg-blue-50 dark:bg-surface-700 border p-5 font-mono font-medium", ui.defaultBorderMixin)
747
+ }
748
+ });
749
+ const code = Code.configure({
750
+ HTMLAttributes: {
751
+ class: ui.cls("rounded-md bg-surface-accent-50 dark:bg-surface-700 px-1.5 py-1 font-mono font-medium"),
752
+ spellcheck: "false"
753
+ }
754
+ });
755
+ const starterKit = StarterKit.configure({
756
+ document: false,
757
+ horizontalRule: false,
758
+ dropcursor: {
759
+ color: "#DBEAFE",
760
+ width: 4
761
+ },
762
+ gapcursor: false
763
+ });
764
+ async function onFileRead(view$1, readerEvent, pos, upload, image) {
765
+ const {
766
+ schema
767
+ } = view$1.state;
768
+ const plugin = view$1.state.plugins.find((p) => p.key === ImagePluginKey.key);
769
+ if (!plugin) {
770
+ console.error("Image plugin not found");
771
+ return;
772
+ }
773
+ let decorationSet = plugin.getState(view$1.state);
774
+ const placeholder2 = document.createElement("div");
775
+ const imageElement = document.createElement("img");
776
+ imageElement.setAttribute("class", "opacity-40 rounded-lg border " + ui.defaultBorderMixin);
777
+ imageElement.src = readerEvent.target?.result;
778
+ placeholder2.appendChild(imageElement);
779
+ const deco = view.Decoration.widget(pos, placeholder2);
780
+ decorationSet = decorationSet?.add(view$1.state.doc, [deco]);
781
+ view$1.dispatch(view$1.state.tr.setMeta(plugin, {
782
+ decorationSet
783
+ }));
784
+ const src = await upload(image);
785
+ console.debug("Uploaded image", src);
786
+ const imageNode = schema.nodes.image.create({
787
+ src
788
+ });
789
+ const tr = view$1.state.tr.replaceWith(pos, pos, imageNode);
790
+ decorationSet = decorationSet?.remove([deco]);
791
+ tr.setMeta(plugin, {
792
+ decorationSet
793
+ });
794
+ view$1.dispatch(tr);
795
+ }
796
+ const ImagePluginKey = new state.PluginKey("imagePlugin");
797
+ const createDropImagePlugin = (upload) => {
798
+ const plugin = new state.Plugin({
799
+ key: ImagePluginKey,
800
+ state: {
801
+ // Initialize the plugin state with an empty DecorationSet
802
+ init: () => view.DecorationSet.empty,
803
+ // Apply transactions to update the state
804
+ apply: (tr, old) => {
805
+ const meta = tr.getMeta(plugin);
806
+ if (meta && meta.decorationSet) {
807
+ return meta.decorationSet;
808
+ }
809
+ return old.map(tr.mapping, tr.doc);
810
+ }
811
+ },
812
+ props: {
813
+ handleDOMEvents: {
814
+ drop: (view2, event) => {
815
+ if (!event.dataTransfer?.files || event.dataTransfer?.files.length === 0) {
816
+ return false;
817
+ }
818
+ event.preventDefault();
819
+ const files = Array.from(event.dataTransfer.files);
820
+ const images = files.filter((file) => /image/i.test(file.type));
821
+ if (images.length === 0) {
822
+ console.log("No images found in dropped files");
823
+ return false;
824
+ }
825
+ images.forEach((image) => {
826
+ const position = view2.posAtCoords({
827
+ left: event.clientX,
828
+ top: event.clientY
829
+ });
830
+ if (!position) return;
831
+ const reader = new FileReader();
832
+ reader.onload = async (readerEvent) => {
833
+ await onFileRead(view2, readerEvent, position.pos, upload, image);
834
+ };
835
+ reader.readAsDataURL(image);
836
+ });
837
+ return true;
838
+ }
839
+ },
840
+ handlePaste(view2, event, slice) {
841
+ const items2 = Array.from(event.clipboardData?.items || []);
842
+ const pos = view2.state.selection.from;
843
+ let anyImageFound = false;
844
+ items2.forEach((item) => {
845
+ const image = item.getAsFile();
846
+ if (image) {
847
+ anyImageFound = true;
848
+ const reader = new FileReader();
849
+ reader.onload = async (readerEvent) => {
850
+ await onFileRead(view2, readerEvent, pos, upload, image);
851
+ };
852
+ reader.readAsDataURL(image);
853
+ }
854
+ });
855
+ return anyImageFound;
856
+ },
857
+ decorations(state2) {
858
+ return plugin.getState(state2);
859
+ }
860
+ },
861
+ view(editorView) {
862
+ return {
863
+ update(view2, prevState) {
864
+ const prevDecos = plugin.getState(prevState);
865
+ const newDecos = plugin.getState(view2.state);
866
+ if (prevDecos !== newDecos) {
867
+ view2.updateState(view2.state);
868
+ }
869
+ }
870
+ };
871
+ }
872
+ });
873
+ return plugin;
874
+ };
875
+ const createImageExtension = (dropImagePlugin) => {
876
+ return TiptapImage.extend({
877
+ addProseMirrorPlugins() {
878
+ return [dropImagePlugin];
879
+ }
880
+ }).configure({
881
+ allowBase64: true,
882
+ HTMLAttributes: {
883
+ class: ui.cls("rounded-lg border", ui.defaultBorderMixin)
884
+ }
885
+ });
886
+ };
887
+ const CustomKeymap = core.Extension.create({
888
+ name: "CustomKeymap",
889
+ addCommands() {
890
+ return {
891
+ selectTextWithinNodeBoundaries: () => ({
892
+ editor,
893
+ commands
894
+ }) => {
895
+ const {
896
+ state: state2
897
+ } = editor;
898
+ const {
899
+ tr
900
+ } = state2;
901
+ const startNodePos = tr.selection.$from.start();
902
+ const endNodePos = tr.selection.$to.end();
903
+ return commands.setTextSelection({
904
+ from: startNodePos,
905
+ to: endNodePos
906
+ });
907
+ }
908
+ };
909
+ },
910
+ addKeyboardShortcuts() {
911
+ return {
912
+ "Mod-a": ({
913
+ editor
914
+ }) => {
915
+ const {
916
+ state: state2
917
+ } = editor;
918
+ const {
919
+ tr
920
+ } = state2;
921
+ const startSelectionPos = tr.selection.from;
922
+ const endSelectionPos = tr.selection.to;
923
+ const startNodePos = tr.selection.$from.start();
924
+ const endNodePos = tr.selection.$to.end();
925
+ const isCurrentTextSelectionNotExtendedToNodeBoundaries = startSelectionPos > startNodePos || endSelectionPos < endNodePos;
926
+ if (isCurrentTextSelectionNotExtendedToNodeBoundaries) {
927
+ editor.chain().selectTextWithinNodeBoundaries().run();
928
+ return true;
929
+ }
930
+ return false;
931
+ }
932
+ };
933
+ }
934
+ });
935
+ function absoluteRect(element) {
936
+ const data = element.getBoundingClientRect();
937
+ let ancestor = element.parentElement;
938
+ while (ancestor && window.getComputedStyle(ancestor).position === "static") {
939
+ ancestor = ancestor.parentElement;
940
+ }
941
+ const ancestorRect = ancestor?.getBoundingClientRect();
942
+ return {
943
+ top: data.top - (ancestorRect?.top ?? 0),
944
+ left: data.left - (ancestorRect?.left ?? 0),
945
+ width: data.width
946
+ };
947
+ }
948
+ function nodeDOMAtCoords(coords) {
949
+ return document.elementsFromPoint(coords.x, coords.y).find((elem) => elem.parentElement?.matches?.(".ProseMirror") || elem.matches(["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3, h4, h5, h6"].join(", ")));
950
+ }
951
+ function nodePosAtDOM(node, view2, options) {
952
+ const boundingRect = node.getBoundingClientRect();
953
+ return view2.posAtCoords({
954
+ left: boundingRect.left + 50 + options.dragHandleWidth,
955
+ top: boundingRect.top + 1
956
+ })?.inside;
957
+ }
958
+ function DragHandle(options) {
959
+ function handleDragStart(event, view$1) {
960
+ view$1.focus();
961
+ if (!event.dataTransfer) return;
962
+ const node = nodeDOMAtCoords({
963
+ x: event.clientX + 50 + options.dragHandleWidth,
964
+ y: event.clientY
965
+ });
966
+ if (!(node instanceof Element)) return;
967
+ const nodePos = nodePosAtDOM(node, view$1, options);
968
+ if (nodePos == null || nodePos < 0) return;
969
+ view$1.dispatch(view$1.state.tr.setSelection(state.NodeSelection.create(view$1.state.doc, nodePos)));
970
+ const slice = view$1.state.selection.content();
971
+ const {
972
+ dom,
973
+ text
974
+ } = view.__serializeForClipboard(view$1, slice);
975
+ event.dataTransfer.clearData();
976
+ event.dataTransfer.setData("text/html", dom.innerHTML);
977
+ event.dataTransfer.setData("text/plain", text);
978
+ event.dataTransfer.effectAllowed = "copyMove";
979
+ event.dataTransfer.setDragImage(node, 0, 0);
980
+ view$1.dragging = {
981
+ slice,
982
+ move: event.ctrlKey
983
+ };
984
+ }
985
+ function handleClick(event, view2) {
986
+ view2.focus();
987
+ view2.dom.classList.remove("dragging");
988
+ const node = nodeDOMAtCoords({
989
+ x: event.clientX + 50 + options.dragHandleWidth,
990
+ y: event.clientY
991
+ });
992
+ if (!(node instanceof Element)) return;
993
+ const nodePos = nodePosAtDOM(node, view2, options);
994
+ if (!nodePos) return;
995
+ view2.dispatch(view2.state.tr.setSelection(state.NodeSelection.create(view2.state.doc, nodePos)));
996
+ }
997
+ let dragHandleElement = null;
998
+ function hideDragHandle() {
999
+ if (dragHandleElement) {
1000
+ dragHandleElement.classList.add("hide");
1001
+ }
1002
+ }
1003
+ function showDragHandle() {
1004
+ if (dragHandleElement) {
1005
+ dragHandleElement.classList.remove("hide");
1006
+ }
1007
+ }
1008
+ return new state.Plugin({
1009
+ view: (view2) => {
1010
+ dragHandleElement = document.createElement("div");
1011
+ dragHandleElement.draggable = true;
1012
+ dragHandleElement.dataset.dragHandle = "";
1013
+ dragHandleElement.classList.add("drag-handle");
1014
+ dragHandleElement.addEventListener("dragstart", (e) => {
1015
+ handleDragStart(e, view2);
1016
+ });
1017
+ dragHandleElement.addEventListener("click", (e) => {
1018
+ handleClick(e, view2);
1019
+ });
1020
+ hideDragHandle();
1021
+ view2?.dom?.parentElement?.appendChild(dragHandleElement);
1022
+ return {
1023
+ destroy: () => {
1024
+ }
1025
+ };
1026
+ },
1027
+ props: {
1028
+ handleDOMEvents: {
1029
+ mousemove: (view2, event) => {
1030
+ if (!view2.editable) {
1031
+ return;
1032
+ }
1033
+ const node = nodeDOMAtCoords({
1034
+ x: event.clientX + 50 + options.dragHandleWidth,
1035
+ y: event.clientY
1036
+ });
1037
+ if (!(node instanceof Element)) {
1038
+ hideDragHandle();
1039
+ return;
1040
+ }
1041
+ const compStyle = window.getComputedStyle(node);
1042
+ const lineHeight = parseInt(compStyle.lineHeight, 10);
1043
+ const paddingTop = parseInt(compStyle.paddingTop, 10);
1044
+ const rect = absoluteRect(node);
1045
+ rect.top += (lineHeight - 24) / 2;
1046
+ rect.top += paddingTop;
1047
+ if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
1048
+ rect.left -= options.dragHandleWidth;
1049
+ }
1050
+ rect.width = options.dragHandleWidth;
1051
+ if (!dragHandleElement) return;
1052
+ dragHandleElement.style.left = `${rect.left - rect.width}px`;
1053
+ dragHandleElement.style.top = `${rect.top}px`;
1054
+ showDragHandle();
1055
+ },
1056
+ keydown: () => {
1057
+ hideDragHandle();
1058
+ },
1059
+ mousewheel: () => {
1060
+ hideDragHandle();
1061
+ },
1062
+ // dragging class is used for CSS
1063
+ dragstart: (view2) => {
1064
+ view2.dom.classList.add("dragging");
1065
+ },
1066
+ drop: (view2) => {
1067
+ view2.dom.classList.remove("dragging");
1068
+ },
1069
+ dragend: (view2) => {
1070
+ view2.dom.classList.remove("dragging");
1071
+ }
1072
+ }
1073
+ }
1074
+ });
1075
+ }
1076
+ const DragAndDrop = core.Extension.create({
1077
+ name: "dragAndDrop",
1078
+ addProseMirrorPlugins() {
1079
+ return [DragHandle({
1080
+ dragHandleWidth: 24
1081
+ })];
1082
+ }
1083
+ });
1084
+ function buildDecorationSet(highlight, doc) {
1085
+ const decorations = [];
1086
+ if (highlight) {
1087
+ decorations.push(view.Decoration.inline(highlight.from, highlight.to, {
1088
+ class: "dark:bg-surface-accent-700 bg-surface-accent-300"
1089
+ }));
1090
+ }
1091
+ const decorationSet = view.DecorationSet.create(doc, decorations);
1092
+ return decorationSet;
1093
+ }
1094
+ const HighlightDecorationExtension = (initialHighlight) => core.Extension.create({
1095
+ name: "highlightDecoration",
1096
+ addOptions() {
1097
+ return {
1098
+ pluginKey: new state.PluginKey("highlightDecoration"),
1099
+ highlight: initialHighlight
1100
+ };
1101
+ },
1102
+ addProseMirrorPlugins() {
1103
+ const pluginKey = this.options.pluginKey;
1104
+ return [new state.Plugin({
1105
+ key: pluginKey,
1106
+ state: {
1107
+ init: (_, {
1108
+ doc
1109
+ }) => {
1110
+ const highlight = this.options.highlight;
1111
+ const decorationSet = highlight && doc ? buildDecorationSet(highlight, doc) : view.DecorationSet.empty;
1112
+ return {
1113
+ decorationSet,
1114
+ highlight
1115
+ };
1116
+ },
1117
+ apply(transaction, oldState) {
1118
+ const action = transaction.getMeta(pluginKey);
1119
+ const highlight = action?.range;
1120
+ if (action?.type === "highlightDecoration") {
1121
+ const doc = transaction.doc;
1122
+ const {
1123
+ remove
1124
+ } = action;
1125
+ if (remove) {
1126
+ return {
1127
+ decorationSet: view.DecorationSet.empty
1128
+ };
1129
+ }
1130
+ const decorationSet = buildDecorationSet(highlight, doc);
1131
+ return {
1132
+ decorationSet,
1133
+ highlight
1134
+ };
1135
+ } else {
1136
+ return oldState;
1137
+ }
1138
+ }
1139
+ },
1140
+ props: {
1141
+ decorations(state2) {
1142
+ const autocompleteState = this.getState(state2);
1143
+ if (autocompleteState?.decorationSet) {
1144
+ return autocompleteState.decorationSet;
1145
+ } else {
1146
+ return view.DecorationSet.empty;
1147
+ }
1148
+ }
1149
+ }
1150
+ })];
1151
+ },
1152
+ addCommands() {
1153
+ return {
1154
+ toggleAutocompleteHighlight: (range) => ({
1155
+ state: state2,
1156
+ dispatch
1157
+ }) => {
1158
+ const {
1159
+ selection
1160
+ } = state2;
1161
+ const pos = selection.from;
1162
+ if (!dispatch) return false;
1163
+ const pluginKey = this.options.pluginKey;
1164
+ const tr = state2.tr.setMeta(pluginKey, {
1165
+ pos,
1166
+ type: "highlightDecoration",
1167
+ remove: false,
1168
+ range
1169
+ });
1170
+ dispatch(tr);
1171
+ return true;
1172
+ },
1173
+ removeAutocompleteHighlight: () => ({
1174
+ state: state2,
1175
+ dispatch
1176
+ }) => {
1177
+ if (!dispatch) return false;
1178
+ const pluginKey = this.options.pluginKey;
1179
+ const tr = state2.tr.setMeta(pluginKey, {
1180
+ pos: 0,
1181
+ // We can pass any position as it will remove the entire decoration set
1182
+ type: "highlightDecoration",
1183
+ remove: true
1184
+ });
1185
+ dispatch(tr);
1186
+ return true;
1187
+ }
1188
+ };
1189
+ }
1190
+ });
1191
+ const CommandPluginKey = new state.PluginKey("slash-command");
1192
+ const SlashCommand = react.Node.create({
1193
+ name: "command",
1194
+ addOptions() {
1195
+ return {
1196
+ HTMLAttributes: {},
1197
+ renderText({
1198
+ options,
1199
+ node
1200
+ }) {
1201
+ return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
1202
+ },
1203
+ deleteTriggerWithBackspace: false,
1204
+ renderHTML({
1205
+ options,
1206
+ node
1207
+ }) {
1208
+ return ["span", react.mergeAttributes(this.HTMLAttributes, options.HTMLAttributes), `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`];
1209
+ },
1210
+ suggestion: {
1211
+ char: "/",
1212
+ pluginKey: CommandPluginKey,
1213
+ command: ({
1214
+ editor,
1215
+ range,
1216
+ props
1217
+ }) => {
1218
+ const nodeAfter = editor.view.state.selection.$to.nodeAfter;
1219
+ const overrideSpace = nodeAfter?.text?.startsWith(" ");
1220
+ if (overrideSpace) {
1221
+ range.to += 1;
1222
+ }
1223
+ editor.chain().focus().insertContentAt(range, [{
1224
+ type: this.name,
1225
+ attrs: props
1226
+ }, {
1227
+ type: "text",
1228
+ text: " "
1229
+ }]).run();
1230
+ window.getSelection()?.collapseToEnd();
1231
+ },
1232
+ allow: ({
1233
+ state: state2,
1234
+ range
1235
+ }) => {
1236
+ const $from = state2.doc.resolve(range.from);
1237
+ const type = state2.schema.nodes[this.name];
1238
+ const allow = !!$from.parent.type.contentMatch.matchType(type);
1239
+ return allow;
1240
+ }
1241
+ }
1242
+ };
1243
+ },
1244
+ group: "inline",
1245
+ inline: true,
1246
+ selectable: false,
1247
+ atom: true,
1248
+ addAttributes() {
1249
+ return {
1250
+ id: {
1251
+ default: null,
1252
+ parseHTML: (element) => element.getAttribute("data-id"),
1253
+ renderHTML: (attributes) => {
1254
+ if (!attributes.id) {
1255
+ return {};
1256
+ }
1257
+ return {
1258
+ "data-id": attributes.id
1259
+ };
1260
+ }
1261
+ },
1262
+ label: {
1263
+ default: null,
1264
+ parseHTML: (element) => element.getAttribute("data-label"),
1265
+ renderHTML: (attributes) => {
1266
+ if (!attributes.label) {
1267
+ return {};
1268
+ }
1269
+ return {
1270
+ "data-label": attributes.label
1271
+ };
1272
+ }
1273
+ }
1274
+ };
1275
+ },
1276
+ parseHTML() {
1277
+ return [{
1278
+ tag: `span[data-type="${this.name}"]`
1279
+ }];
1280
+ },
1281
+ renderHTML({
1282
+ node,
1283
+ HTMLAttributes
1284
+ }) {
1285
+ if (this.options.renderLabel !== void 0) {
1286
+ console.warn("renderLabel is deprecated use renderText and renderHTML instead");
1287
+ return ["span", react.mergeAttributes({
1288
+ "data-type": this.name
1289
+ }, this.options.HTMLAttributes, HTMLAttributes), this.options.renderLabel({
1290
+ options: this.options,
1291
+ node
1292
+ })];
1293
+ }
1294
+ const mergedOptions = {
1295
+ ...this.options
1296
+ };
1297
+ mergedOptions.HTMLAttributes = react.mergeAttributes({
1298
+ "data-type": this.name
1299
+ }, this.options.HTMLAttributes, HTMLAttributes);
1300
+ const html = this.options.renderHTML({
1301
+ options: mergedOptions,
1302
+ node
1303
+ });
1304
+ if (typeof html === "string") {
1305
+ return ["span", react.mergeAttributes({
1306
+ "data-type": this.name
1307
+ }, this.options.HTMLAttributes, HTMLAttributes), html];
1308
+ }
1309
+ return html;
1310
+ },
1311
+ renderText({
1312
+ node
1313
+ }) {
1314
+ return this.options.renderText({
1315
+ options: this.options,
1316
+ node
1317
+ });
1318
+ },
1319
+ addKeyboardShortcuts() {
1320
+ return {
1321
+ Backspace: () => this.editor.commands.command(({
1322
+ tr,
1323
+ state: state2
1324
+ }) => {
1325
+ let isCommand = false;
1326
+ const {
1327
+ selection
1328
+ } = state2;
1329
+ const {
1330
+ empty,
1331
+ anchor
1332
+ } = selection;
1333
+ if (!empty) {
1334
+ return false;
1335
+ }
1336
+ state2.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
1337
+ if (node.type.name === this.name) {
1338
+ isCommand = true;
1339
+ tr.insertText(this.options.deleteTriggerWithBackspace ? "" : this.options.suggestion.char || "", pos, pos + node.nodeSize);
1340
+ return false;
1341
+ }
1342
+ return true;
1343
+ });
1344
+ return isCommand;
1345
+ })
1346
+ };
1347
+ },
1348
+ addProseMirrorPlugins() {
1349
+ return [Suggestion({
1350
+ editor: this.editor,
1351
+ ...this.options.suggestion
1352
+ })];
1353
+ }
1354
+ });
1355
+ const suggestion = (ref, {
1356
+ upload,
1357
+ aiController
1358
+ }) => ({
1359
+ items: ({
1360
+ query
1361
+ }) => {
1362
+ const availableSuggestionItems = [...suggestionItems];
1363
+ if (aiController) {
1364
+ availableSuggestionItems.push(autocompleteSuggestionItem);
1365
+ }
1366
+ return availableSuggestionItems.filter((item) => {
1367
+ const inTitle = item.title.toLowerCase().startsWith(query.toLowerCase());
1368
+ if (inTitle) return inTitle;
1369
+ const inSearchTerms = item.searchTerms?.some((term) => term.toLowerCase().startsWith(query.toLowerCase()));
1370
+ return inSearchTerms;
1371
+ });
1372
+ },
1373
+ render: () => {
1374
+ let component;
1375
+ let popup;
1376
+ return {
1377
+ onStart: (props) => {
1378
+ component = new react.ReactRenderer(CommandList, {
1379
+ props: {
1380
+ ...props,
1381
+ upload,
1382
+ aiController
1383
+ },
1384
+ editor: props.editor
1385
+ });
1386
+ if (!props.clientRect) {
1387
+ return;
1388
+ }
1389
+ popup = tippy("body", {
1390
+ getReferenceClientRect: props.clientRect,
1391
+ appendTo: ref?.current,
1392
+ content: component.element,
1393
+ showOnCreate: true,
1394
+ interactive: true,
1395
+ trigger: "manual",
1396
+ placement: "bottom-start"
1397
+ });
1398
+ },
1399
+ onUpdate(props) {
1400
+ component.updateProps(props);
1401
+ if (!props.clientRect) {
1402
+ return;
1403
+ }
1404
+ popup[0].setProps({
1405
+ getReferenceClientRect: props.clientRect
1406
+ });
1407
+ },
1408
+ onKeyDown(props) {
1409
+ if (props.event.key === "Escape") {
1410
+ popup[0].hide();
1411
+ props.event.preventDefault();
1412
+ return true;
1413
+ }
1414
+ return component.ref?.onKeyDown(props);
1415
+ },
1416
+ onExit() {
1417
+ if (popup && popup[0]) popup[0].destroy();
1418
+ component?.destroy();
1419
+ }
1420
+ };
1421
+ }
1422
+ });
1423
+ const CommandList = React.forwardRef((props, ref) => {
1424
+ const $ = reactCompilerRuntime.c(33);
1425
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
1426
+ const {
1427
+ editor
1428
+ } = react.useCurrentEditor();
1429
+ let t0;
1430
+ if ($[0] !== editor || $[1] !== props.aiController || $[2] !== props.range || $[3] !== props.upload) {
1431
+ t0 = (item) => {
1432
+ if (!editor) {
1433
+ return;
1434
+ }
1435
+ item?.command?.({
1436
+ editor,
1437
+ range: props.range,
1438
+ upload: props.upload,
1439
+ aiController: props.aiController
1440
+ });
1441
+ };
1442
+ $[0] = editor;
1443
+ $[1] = props.aiController;
1444
+ $[2] = props.range;
1445
+ $[3] = props.upload;
1446
+ $[4] = t0;
1447
+ } else {
1448
+ t0 = $[4];
1449
+ }
1450
+ const selectItem = t0;
1451
+ let t1;
1452
+ if ($[5] !== props.items.length || $[6] !== selectedIndex) {
1453
+ t1 = () => {
1454
+ setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
1455
+ };
1456
+ $[5] = props.items.length;
1457
+ $[6] = selectedIndex;
1458
+ $[7] = t1;
1459
+ } else {
1460
+ t1 = $[7];
1461
+ }
1462
+ const upHandler = t1;
1463
+ let t2;
1464
+ if ($[8] !== props.items.length || $[9] !== selectedIndex) {
1465
+ t2 = () => {
1466
+ setSelectedIndex((selectedIndex + 1) % props.items.length);
1467
+ };
1468
+ $[8] = props.items.length;
1469
+ $[9] = selectedIndex;
1470
+ $[10] = t2;
1471
+ } else {
1472
+ t2 = $[10];
1473
+ }
1474
+ const downHandler = t2;
1475
+ let t3;
1476
+ if ($[11] !== props.items || $[12] !== selectItem || $[13] !== selectedIndex) {
1477
+ t3 = () => {
1478
+ const item_0 = props.items[selectedIndex];
1479
+ selectItem(item_0);
1480
+ };
1481
+ $[11] = props.items;
1482
+ $[12] = selectItem;
1483
+ $[13] = selectedIndex;
1484
+ $[14] = t3;
1485
+ } else {
1486
+ t3 = $[14];
1487
+ }
1488
+ const enterHandler = t3;
1489
+ let t4;
1490
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
1491
+ t4 = () => setSelectedIndex(0);
1492
+ $[15] = t4;
1493
+ } else {
1494
+ t4 = $[15];
1495
+ }
1496
+ let t5;
1497
+ if ($[16] !== props.items) {
1498
+ t5 = [props.items];
1499
+ $[16] = props.items;
1500
+ $[17] = t5;
1501
+ } else {
1502
+ t5 = $[17];
1503
+ }
1504
+ React.useEffect(t4, t5);
1505
+ let t6;
1506
+ if ($[18] !== downHandler || $[19] !== enterHandler || $[20] !== upHandler) {
1507
+ t6 = () => ({
1508
+ onKeyDown: (t72) => {
1509
+ const {
1510
+ event
1511
+ } = t72;
1512
+ if (event.key === "ArrowUp") {
1513
+ upHandler();
1514
+ return true;
1515
+ }
1516
+ if (event.key === "ArrowDown") {
1517
+ downHandler();
1518
+ return true;
1519
+ }
1520
+ if (event.key === "Enter") {
1521
+ enterHandler();
1522
+ return true;
1523
+ }
1524
+ return false;
1525
+ }
1526
+ });
1527
+ $[18] = downHandler;
1528
+ $[19] = enterHandler;
1529
+ $[20] = upHandler;
1530
+ $[21] = t6;
1531
+ } else {
1532
+ t6 = $[21];
1533
+ }
1534
+ React.useImperativeHandle(ref, t6);
1535
+ let t7;
1536
+ if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
1537
+ t7 = [];
1538
+ $[22] = t7;
1539
+ } else {
1540
+ t7 = $[22];
1541
+ }
1542
+ const itemRefs = React.useRef(t7);
1543
+ let t8;
1544
+ let t9;
1545
+ if ($[23] !== selectedIndex) {
1546
+ t8 = () => {
1547
+ if (itemRefs.current[selectedIndex]) {
1548
+ itemRefs.current[selectedIndex].scrollIntoView({
1549
+ block: "nearest"
1550
+ });
1551
+ }
1552
+ };
1553
+ t9 = [selectedIndex];
1554
+ $[23] = selectedIndex;
1555
+ $[24] = t8;
1556
+ $[25] = t9;
1557
+ } else {
1558
+ t8 = $[24];
1559
+ t9 = $[25];
1560
+ }
1561
+ React.useEffect(t8, t9);
1562
+ let t10;
1563
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
1564
+ t10 = ui.cls("text-surface-900 dark:text-white z-50 max-h-[280px] h-auto w-72 overflow-y-auto rounded-md border bg-white dark:bg-surface-900 px-1 py-2 shadow transition-all", ui.defaultBorderMixin);
1565
+ $[26] = t10;
1566
+ } else {
1567
+ t10 = $[26];
1568
+ }
1569
+ let t11;
1570
+ if ($[27] !== props.items || $[28] !== selectItem || $[29] !== selectedIndex) {
1571
+ t11 = props.items.length ? props.items.map((item_1, index) => /* @__PURE__ */ jsxRuntime.jsxs("button", { value: item_1.title, ref: (el) => {
1572
+ if (!el) {
1573
+ return;
1574
+ }
1575
+ itemRefs.current[index] = el;
1576
+ }, onClick: () => selectItem(item_1), tabIndex: index === selectedIndex ? 0 : -1, "aria-selected": index === selectedIndex, className: ui.cls("flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-surface-700 aria-selected:bg-blue-50 aria-selected:dark:bg-surface-700", index === selectedIndex ? "bg-blue-100 dark:bg-surface-accent-950" : ""), children: [
1577
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ui.cls("flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-surface-900", ui.defaultBorderMixin), children: item_1.icon }),
1578
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1579
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: item_1.title }),
1580
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-surface-700 dark:text-surface-accent-300", children: item_1.description })
1581
+ ] })
1582
+ ] }, item_1.title)) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "item", children: "No result" });
1583
+ $[27] = props.items;
1584
+ $[28] = selectItem;
1585
+ $[29] = selectedIndex;
1586
+ $[30] = t11;
1587
+ } else {
1588
+ t11 = $[30];
1589
+ }
1590
+ let t12;
1591
+ if ($[31] !== t11) {
1592
+ t12 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: t10, children: t11 });
1593
+ $[31] = t11;
1594
+ $[32] = t12;
1595
+ } else {
1596
+ t12 = $[32];
1597
+ }
1598
+ return t12;
1599
+ });
1600
+ CommandList.displayName = "CommandList";
1601
+ const autocompleteSuggestionItem = {
1602
+ title: "Autocomplete",
1603
+ description: "Add text based on the context.",
1604
+ searchTerms: ["ai"],
1605
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.AutoFixHighIcon, { size: 18 }),
1606
+ command: async ({
1607
+ editor,
1608
+ range,
1609
+ aiController
1610
+ }) => {
1611
+ if (!aiController) throw Error("No AiController");
1612
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
1613
+ const {
1614
+ state: state2
1615
+ } = editor;
1616
+ const {
1617
+ from,
1618
+ to
1619
+ } = state2.selection;
1620
+ const textBeforeCursor = state2.doc.textBetween(0, from, "\n");
1621
+ const textAfterCursor = state2.doc.textBetween(to, state2.doc.content.size, "\n");
1622
+ let buffer = "";
1623
+ const result = await aiController.autocomplete(textBeforeCursor, textAfterCursor, (delta) => {
1624
+ buffer += delta;
1625
+ if (delta.length !== 0) {
1626
+ editor.chain().focus().toggleLoadingDecoration(buffer).run();
1627
+ }
1628
+ });
1629
+ editor.chain().focus().insertContent(result, {
1630
+ applyInputRules: false,
1631
+ applyPasteRules: false,
1632
+ parseOptions: {
1633
+ preserveWhitespace: false
1634
+ }
1635
+ }).run();
1636
+ }
1637
+ };
1638
+ const suggestionItems = [{
1639
+ title: "Text",
1640
+ description: "Just start typing with plain text.",
1641
+ searchTerms: ["p", "paragraph"],
1642
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.TextFieldsIcon, { size: 18 }),
1643
+ command: ({
1644
+ editor,
1645
+ range
1646
+ }) => {
1647
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
1648
+ }
1649
+ }, {
1650
+ title: "To-do List",
1651
+ description: "Track tasks with a to-do list.",
1652
+ searchTerms: ["todo", "task", "list", "check", "checkbox"],
1653
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckBoxIcon, { size: 18 }),
1654
+ command: ({
1655
+ editor,
1656
+ range
1657
+ }) => {
1658
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
1659
+ }
1660
+ }, {
1661
+ title: "Heading 1",
1662
+ description: "Big section heading.",
1663
+ searchTerms: ["title", "big", "large"],
1664
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.LooksOneIcon, { size: 18 }),
1665
+ command: ({
1666
+ editor,
1667
+ range
1668
+ }) => {
1669
+ editor.chain().focus().deleteRange(range).setNode("heading", {
1670
+ level: 1
1671
+ }).run();
1672
+ }
1673
+ }, {
1674
+ title: "Heading 2",
1675
+ description: "Medium section heading.",
1676
+ searchTerms: ["subtitle", "medium"],
1677
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.LooksTwoIcon, { size: 18 }),
1678
+ command: ({
1679
+ editor,
1680
+ range
1681
+ }) => {
1682
+ editor.chain().focus().deleteRange(range).setNode("heading", {
1683
+ level: 2
1684
+ }).run();
1685
+ }
1686
+ }, {
1687
+ title: "Heading 3",
1688
+ description: "Small section heading.",
1689
+ searchTerms: ["subtitle", "small"],
1690
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.Looks3Icon, { size: 18 }),
1691
+ command: ({
1692
+ editor,
1693
+ range
1694
+ }) => {
1695
+ editor.chain().focus().deleteRange(range).setNode("heading", {
1696
+ level: 3
1697
+ }).run();
1698
+ }
1699
+ }, {
1700
+ title: "Bullet List",
1701
+ description: "Create a simple bullet list.",
1702
+ searchTerms: ["unordered", "point"],
1703
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatListBulletedIcon, { size: 18 }),
1704
+ command: ({
1705
+ editor,
1706
+ range
1707
+ }) => {
1708
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
1709
+ }
1710
+ }, {
1711
+ title: "Numbered List",
1712
+ description: "Create a list with numbering.",
1713
+ searchTerms: ["ordered"],
1714
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatListNumberedIcon, { size: 18 }),
1715
+ command: ({
1716
+ editor,
1717
+ range
1718
+ }) => {
1719
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
1720
+ }
1721
+ }, {
1722
+ title: "Quote",
1723
+ description: "Capture a quote.",
1724
+ searchTerms: ["blockquote"],
1725
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatQuoteIcon, { size: 18 }),
1726
+ command: ({
1727
+ editor,
1728
+ range
1729
+ }) => editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
1730
+ }, {
1731
+ title: "Code",
1732
+ description: "Capture a code snippet.",
1733
+ searchTerms: ["codeblock"],
1734
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.CodeIcon, { size: 18 }),
1735
+ command: ({
1736
+ editor,
1737
+ range
1738
+ }) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run()
1739
+ }, {
1740
+ title: "Image",
1741
+ description: "Upload an image from your computer.",
1742
+ searchTerms: ["photo", "picture", "media", "upload", "file"],
1743
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.ImageIcon, { size: 18 }),
1744
+ command: ({
1745
+ editor,
1746
+ range,
1747
+ upload
1748
+ }) => {
1749
+ editor.chain().focus().deleteRange(range).run();
1750
+ const input = document.createElement("input");
1751
+ input.type = "file";
1752
+ input.accept = "image/*";
1753
+ input.onchange = async () => {
1754
+ if (input.files?.length) {
1755
+ const file = input.files[0];
1756
+ if (!file) return;
1757
+ const pos = editor.view.state.selection.from;
1758
+ const fileList = input.files;
1759
+ const files = Array.from(fileList);
1760
+ const images = files.filter((file2) => /image/i.test(file2.type));
1761
+ if (images.length === 0) {
1762
+ console.log("No images found in uploaded files");
1763
+ return false;
1764
+ }
1765
+ const view2 = editor.view;
1766
+ images.forEach((image) => {
1767
+ const reader = new FileReader();
1768
+ reader.onload = async (readerEvent) => {
1769
+ await onFileRead(view2, readerEvent, pos, upload, image);
1770
+ };
1771
+ reader.readAsDataURL(image);
1772
+ });
1773
+ }
1774
+ return true;
1775
+ };
1776
+ input.click();
1777
+ }
1778
+ }];
1779
+ const CustomDocument = Document.extend({
1780
+ // content: 'heading block*',
1781
+ });
1782
+ const proseClasses = {
1783
+ "sm": "prose-sm",
1784
+ "base": "prose-base",
1785
+ "lg": "prose-lg"
1786
+ };
1787
+ const FireCMSEditor = ({
1788
+ content,
1789
+ onJsonContentChange,
1790
+ onHtmlContentChange,
1791
+ onMarkdownContentChange,
1792
+ version,
1793
+ textSize = "base",
1794
+ highlight,
1795
+ handleImageUpload,
1796
+ aiController,
1797
+ disabled
1798
+ }) => {
1799
+ const ref = React.useRef(null);
1800
+ const editorRef = React.useRef(null);
1801
+ const imagePlugin = createDropImagePlugin(handleImageUpload);
1802
+ const imageExtension = React.useMemo(() => createImageExtension(imagePlugin), []);
1803
+ const [openNode, setOpenNode] = React.useState(false);
1804
+ const [openLink, setOpenLink] = React.useState(false);
1805
+ ui.useInjectStyles("Editor", cssStyles);
1806
+ const deferredHighlight = React.useDeferredValue(highlight);
1807
+ React.useEffect(() => {
1808
+ if (version === void 0) return;
1809
+ if (version > -1 && editorRef.current) {
1810
+ editorRef.current?.commands.setContent(content ?? "");
1811
+ }
1812
+ }, [version]);
1813
+ React.useEffect(() => {
1814
+ editorRef?.current?.setEditable(!disabled);
1815
+ }, [disabled]);
1816
+ React.useEffect(() => {
1817
+ if (version === void 0) return;
1818
+ if (editorRef.current && version > 0) {
1819
+ const chain = editorRef.current.chain();
1820
+ if (deferredHighlight) {
1821
+ chain.focus().toggleAutocompleteHighlight(deferredHighlight).run();
1822
+ } else {
1823
+ chain.focus().removeAutocompleteHighlight().run();
1824
+ }
1825
+ }
1826
+ }, [deferredHighlight?.from, deferredHighlight?.to]);
1827
+ const onEditorUpdate = (editor) => {
1828
+ editorRef.current = editor;
1829
+ if (onMarkdownContentChange) {
1830
+ const markdown = editorRef.current.storage.markdown.getMarkdown();
1831
+ onMarkdownContentChange?.(addLineBreakAfterImages(markdown));
1832
+ }
1833
+ if (onJsonContentChange) {
1834
+ const jsonContent = removeClassesFromJson(editor.getJSON());
1835
+ onJsonContentChange(jsonContent);
1836
+ }
1837
+ if (onHtmlContentChange) {
1838
+ onHtmlContentChange?.(editor.getHTML());
1839
+ }
1840
+ };
1841
+ const proseClass = proseClasses[textSize];
1842
+ const extensions = React.useMemo(() => [
1843
+ starterKit,
1844
+ CustomDocument,
1845
+ HighlightDecorationExtension(highlight),
1846
+ TextLoadingDecorationExtension,
1847
+ Underline,
1848
+ Bold,
1849
+ TextStyle,
1850
+ Italic,
1851
+ Strike,
1852
+ Color,
1853
+ Highlight.configure({
1854
+ multicolor: true
1855
+ }),
1856
+ // CustomBlock.configure({
1857
+ // component: CustomComponent,
1858
+ // delimiter: "```custom"
1859
+ // }),
1860
+ Heading,
1861
+ CustomKeymap,
1862
+ DragAndDrop,
1863
+ placeholder,
1864
+ tiptapLink,
1865
+ imageExtension,
1866
+ taskList,
1867
+ taskItem,
1868
+ tiptapMarkdown.Markdown.configure({
1869
+ html: true
1870
+ }),
1871
+ horizontalRule,
1872
+ bulletList,
1873
+ orderedList,
1874
+ listItem,
1875
+ blockquote,
1876
+ codeBlock,
1877
+ code,
1878
+ SlashCommand.configure({
1879
+ HTMLAttributes: {
1880
+ class: "mention"
1881
+ },
1882
+ suggestion: suggestion(ref, {
1883
+ upload: handleImageUpload,
1884
+ aiController
1885
+ })
1886
+ })
1887
+ ], []);
1888
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: "relative min-h-[300px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(react.EditorProvider, { content: content ?? "", extensions, editorProps: {
1889
+ editable: () => !disabled,
1890
+ attributes: {
1891
+ class: ui.cls(proseClass, "prose-headings:font-title font-default focus:outline-none max-w-full p-12")
1892
+ }
1893
+ }, onCreate: ({
1894
+ editor: editor_0
1895
+ }) => {
1896
+ editorRef.current = editor_0;
1897
+ editor_0.setEditable(!disabled);
1898
+ }, onUpdate: ({
1899
+ editor: editor_1
1900
+ }) => {
1901
+ onEditorUpdate(editor_1);
1902
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs(EditorBubble, { tippyOptions: {
1903
+ placement: "top"
1904
+ }, className: ui.cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-surface-900 shadow", ui.defaultBorderMixin), children: [
1905
+ /* @__PURE__ */ jsxRuntime.jsx(NodeSelector, { portalContainer: ref.current, open: openNode, onOpenChange: setOpenNode }),
1906
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Separator, { orientation: "vertical" }),
1907
+ /* @__PURE__ */ jsxRuntime.jsx(LinkSelector, { open: openLink, onOpenChange: setOpenLink }),
1908
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Separator, { orientation: "vertical" }),
1909
+ /* @__PURE__ */ jsxRuntime.jsx(TextButtons, {})
1910
+ ] }) }) });
1911
+ };
1912
+ function addLineBreakAfterImages(markdown) {
1913
+ const imageRegex = /!\[.*?\]\(.*?\)/g;
1914
+ return markdown.replace(imageRegex, (match) => `${match}
1915
+ `);
1916
+ }
1917
+ const cssStyles = `
1918
+ .ProseMirror {
1919
+ box-shadow: none !important;
1920
+ }
4
1921
  .ProseMirror .is-editor-empty:first-child::before {
5
1922
  content: attr(data-placeholder);
6
1923
  float: left;
@@ -23,6 +1940,7 @@
23
1940
  }
24
1941
 
25
1942
  .is-empty {
1943
+ cursor: text;
26
1944
  color: rgb(100 116 139); //500
27
1945
  }
28
1946
 
@@ -40,6 +1958,7 @@
40
1958
  &.ProseMirror-selectednode {
41
1959
  outline: 3px solid #5abbf7;
42
1960
  filter: brightness(90%);
1961
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000) !important;
43
1962
  }
44
1963
  }
45
1964
 
@@ -67,7 +1986,7 @@ ul[data-type="taskList"] li > label {
67
1986
  }
68
1987
 
69
1988
  &:active {
70
- background-color: rgb(71 85 105);;
1989
+ background-color: rgb(71 85 105);
71
1990
  }
72
1991
  }
73
1992
  }
@@ -134,7 +2053,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
134
2053
  }
135
2054
 
136
2055
  .ProseMirror:not(.dragging) .ProseMirror-selectednode {
137
- outline: none !important;
2056
+ // outline: none !important;
138
2057
  background-color: rgb(219 234 254); // blue 100
139
2058
  transition: background-color 0.2s;
140
2059
  box-shadow: none;
@@ -144,8 +2063,12 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
144
2063
  background-color: rgb(51 65 85); // 700
145
2064
  }
146
2065
 
2066
+ .prose-base table p {
2067
+ margin: 0;
2068
+ }
2069
+
147
2070
  .drag-handle {
148
- position: fixed;
2071
+ position: absolute;
149
2072
  opacity: 1;
150
2073
  transition: opacity ease-in 0.2s;
151
2074
  border-radius: 0.25rem;
@@ -156,7 +2079,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
156
2079
  background-position: center;
157
2080
  width: 1.2rem;
158
2081
  height: 1.5rem;
159
- z-index: 50;
2082
+ z-index: 100;
160
2083
  cursor: grab;
161
2084
 
162
2085
  &:hover {
@@ -189,5 +2112,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
189
2112
  background-color: rgb(51 65 85); // 700
190
2113
  }
191
2114
  }
192
- `;u.FireCMSEditor=Pe,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
2115
+ `;
2116
+ exports2.FireCMSEditor = FireCMSEditor;
2117
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
2118
+ });
193
2119
  //# sourceMappingURL=index.umd.js.map