@firecms/editor 3.0.0-canary.9 → 3.0.0-canary.91

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,5 +1,1148 @@
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=`
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(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"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["FireCMS Editor"] = {}, global.jsxRuntime, global.React, global.TiptapUnderline, global.TextStyle, global.extensionColor, global.tiptapMarkdown, global.Highlight, global.react, global.jotai, global.reactSlot, global.tunnel, global.cmdk, global.StarterKit, global.HorizontalRule, global.TiptapLink, global.TiptapImage, global.Placeholder, global.extensionTaskItem, global.extensionTaskList, global.core, global.Suggestion, global.tippy, global.ui, global.prosemirrorState, global.view, global.state));
3
+ })(this, function(exports2, jsxRuntime, React, TiptapUnderline, TextStyle, extensionColor, tiptapMarkdown, Highlight, react, jotai, reactSlot, tunnel, cmdk, StarterKit, HorizontalRule, TiptapLink, TiptapImage, Placeholder, extensionTaskItem, extensionTaskList, core, Suggestion, tippy, ui, prosemirrorState, view, state) {
4
+ "use strict";
5
+ const editorStore = jotai.createStore();
6
+ const EditorRoot = ({ children }) => {
7
+ return /* @__PURE__ */ jsxRuntime.jsx(jotai.Provider, { store: editorStore, children });
8
+ };
9
+ const EditorBubble = React.forwardRef(
10
+ ({ children, tippyOptions, ...rest }, ref) => {
11
+ const { editor } = react.useCurrentEditor();
12
+ const instanceRef = React.useRef(null);
13
+ React.useEffect(() => {
14
+ if (!instanceRef.current || !tippyOptions?.placement) return;
15
+ instanceRef.current.setProps({ placement: tippyOptions.placement });
16
+ instanceRef.current.popperInstance?.update();
17
+ }, [tippyOptions?.placement]);
18
+ const bubbleMenuProps = React.useMemo(() => {
19
+ const shouldShow = ({ editor: editor2, state: state2 }) => {
20
+ const { selection } = state2;
21
+ const { empty } = selection;
22
+ if (editor2.isActive("image") || empty || react.isNodeSelection(selection)) {
23
+ return false;
24
+ }
25
+ return true;
26
+ };
27
+ return {
28
+ shouldShow,
29
+ tippyOptions: {
30
+ onCreate: (val) => {
31
+ instanceRef.current = val;
32
+ },
33
+ moveTransition: "transform 0.15s ease-out",
34
+ ...tippyOptions
35
+ },
36
+ ...rest
37
+ };
38
+ }, [rest, tippyOptions]);
39
+ if (!editor) return null;
40
+ return (
41
+ //We need to add this because of https://github.com/ueberdosis/tiptap/issues/2658
42
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref, children: /* @__PURE__ */ jsxRuntime.jsx(react.BubbleMenu, { editor, ...bubbleMenuProps, children }) })
43
+ );
44
+ }
45
+ );
46
+ const EditorBubbleItem = React.forwardRef(({ children, asChild, onSelect, ...rest }, ref) => {
47
+ const { editor } = react.useCurrentEditor();
48
+ const Comp = asChild ? reactSlot.Slot : "div";
49
+ if (!editor) return null;
50
+ return /* @__PURE__ */ jsxRuntime.jsx(Comp, { ref, ...rest, onClick: () => onSelect?.(editor), children });
51
+ });
52
+ EditorBubbleItem.displayName = "EditorBubbleItem";
53
+ const t = tunnel();
54
+ const queryAtom = jotai.atom("");
55
+ const rangeAtom = jotai.atom(null);
56
+ const EditorCommandOut = ({
57
+ query,
58
+ range
59
+ }) => {
60
+ const setQuery = jotai.useSetAtom(queryAtom, { store: editorStore });
61
+ const setRange = jotai.useSetAtom(rangeAtom, { store: editorStore });
62
+ React.useEffect(() => {
63
+ setQuery(query);
64
+ }, [query, setQuery]);
65
+ React.useEffect(() => {
66
+ setRange(range);
67
+ }, [range, setRange]);
68
+ React.useEffect(() => {
69
+ const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"];
70
+ const onKeyDown = (e) => {
71
+ if (navigationKeys.includes(e.key)) {
72
+ e.preventDefault();
73
+ const commandRef = document.querySelector("#slash-command");
74
+ if (commandRef)
75
+ commandRef.dispatchEvent(
76
+ new KeyboardEvent("keydown", { key: e.key, cancelable: true, bubbles: true })
77
+ );
78
+ }
79
+ };
80
+ document.addEventListener("keydown", onKeyDown);
81
+ return () => {
82
+ document.removeEventListener("keydown", onKeyDown);
83
+ };
84
+ }, []);
85
+ return /* @__PURE__ */ jsxRuntime.jsx(t.Out, {});
86
+ };
87
+ const EditorCommand = React.forwardRef(
88
+ ({ children, className, ...rest }, ref) => {
89
+ const commandListRef = React.useRef(null);
90
+ const [query, setQuery] = jotai.useAtom(queryAtom);
91
+ return /* @__PURE__ */ jsxRuntime.jsx(t.In, { children: /* @__PURE__ */ jsxRuntime.jsxs(
92
+ cmdk.Command,
93
+ {
94
+ ref,
95
+ onKeyDown: (e) => {
96
+ e.stopPropagation();
97
+ },
98
+ id: "slash-command",
99
+ className,
100
+ ...rest,
101
+ children: [
102
+ /* @__PURE__ */ jsxRuntime.jsx(cmdk.Command.Input, { value: query, onValueChange: setQuery, style: { display: "none" } }),
103
+ /* @__PURE__ */ jsxRuntime.jsx(cmdk.Command.List, { ref: commandListRef, children })
104
+ ]
105
+ }
106
+ ) });
107
+ }
108
+ );
109
+ const EditorCommandItem = React.forwardRef(({ children, onCommand, ...rest }, ref) => {
110
+ const { editor } = react.useCurrentEditor();
111
+ const range = jotai.useAtomValue(rangeAtom);
112
+ if (!editor || !range) return null;
113
+ return /* @__PURE__ */ jsxRuntime.jsx(cmdk.CommandItem, { ref, ...rest, onSelect: () => onCommand({ editor, range }), children });
114
+ });
115
+ EditorCommandItem.displayName = "EditorCommandItem";
116
+ const EditorCommandEmpty = cmdk.CommandEmpty;
117
+ const Command = core.Extension.create({
118
+ name: "slash-command",
119
+ addOptions() {
120
+ return {
121
+ suggestion: {
122
+ char: "/",
123
+ command: ({ editor, range, props }) => {
124
+ props.command({ editor, range });
125
+ }
126
+ }
127
+ };
128
+ },
129
+ addProseMirrorPlugins() {
130
+ return [
131
+ Suggestion({
132
+ editor: this.editor,
133
+ ...this.options.suggestion
134
+ })
135
+ ];
136
+ }
137
+ });
138
+ const renderItems = () => {
139
+ let component = null;
140
+ let popup = null;
141
+ return {
142
+ onStart: (props) => {
143
+ component = new react.ReactRenderer(EditorCommandOut, {
144
+ props,
145
+ editor: props.editor
146
+ });
147
+ popup = tippy("body", {
148
+ getReferenceClientRect: props.clientRect,
149
+ appendTo: () => document.body,
150
+ content: component.element,
151
+ showOnCreate: true,
152
+ interactive: true,
153
+ trigger: "manual",
154
+ placement: "bottom-start"
155
+ });
156
+ },
157
+ onUpdate: (props) => {
158
+ component?.updateProps(props);
159
+ popup && popup[0].setProps({
160
+ getReferenceClientRect: props.clientRect
161
+ });
162
+ },
163
+ onKeyDown: (props) => {
164
+ if (props.event.key === "Escape") {
165
+ popup?.[0].hide();
166
+ return true;
167
+ }
168
+ return component?.ref?.onKeyDown(props);
169
+ },
170
+ onExit: () => {
171
+ popup?.[0].destroy();
172
+ component?.destroy();
173
+ }
174
+ };
175
+ };
176
+ const createSuggestionItems = (items2) => items2;
177
+ const PlaceholderExtension = Placeholder.configure({
178
+ placeholder: ({ node }) => {
179
+ if (node.type.name === "heading") {
180
+ return `Heading ${node.attrs.level}`;
181
+ }
182
+ return "Press '/' for commands";
183
+ },
184
+ includeChildren: true
185
+ });
186
+ const Horizontal = HorizontalRule.extend({
187
+ addInputRules() {
188
+ return [
189
+ new core.InputRule({
190
+ find: /^(?:---|—-|___\s|\*\*\*\s)$/,
191
+ handler: ({ state: state2, range }) => {
192
+ const attributes = {};
193
+ const { tr } = state2;
194
+ const start = range.from;
195
+ const end = range.to;
196
+ tr.insert(start - 1, this.type.create(attributes)).delete(
197
+ tr.mapping.map(start),
198
+ tr.mapping.map(end)
199
+ );
200
+ }
201
+ })
202
+ ];
203
+ }
204
+ });
205
+ const items = [
206
+ {
207
+ name: "Text",
208
+ icon: ui.TextFieldsIcon,
209
+ command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").run(),
210
+ // I feel like there has to be a more efficient way to do this – feel free to PR if you know how!
211
+ isActive: (editor) => (editor?.isActive("paragraph") && !editor?.isActive("bulletList") && !editor?.isActive("orderedList")) ?? false
212
+ },
213
+ {
214
+ name: "Heading 1",
215
+ icon: ui.LooksOneIcon,
216
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
217
+ isActive: (editor) => editor?.isActive("heading", { level: 1 }) ?? false
218
+ },
219
+ {
220
+ name: "Heading 2",
221
+ icon: ui.LooksTwoIcon,
222
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
223
+ isActive: (editor) => editor?.isActive("heading", { level: 2 }) ?? false
224
+ },
225
+ {
226
+ name: "Heading 3",
227
+ icon: ui.Looks3Icon,
228
+ command: (editor) => editor?.chain().focus().toggleHeading({ level: 3 }).run(),
229
+ isActive: (editor) => editor?.isActive("heading", { level: 3 }) ?? false
230
+ },
231
+ {
232
+ name: "To-do List",
233
+ icon: ui.CheckBoxIcon,
234
+ command: (editor) => editor?.chain().focus().toggleTaskList().run(),
235
+ isActive: (editor) => editor?.isActive("taskItem") ?? false
236
+ },
237
+ {
238
+ name: "Bullet List",
239
+ icon: ui.FormatListBulletedIcon,
240
+ command: (editor) => editor?.chain().focus().toggleBulletList().run(),
241
+ isActive: (editor) => editor?.isActive("bulletList") ?? false
242
+ },
243
+ {
244
+ name: "Numbered List",
245
+ icon: ui.FormatListNumberedIcon,
246
+ command: (editor) => editor?.chain().focus().toggleOrderedList().run(),
247
+ isActive: (editor) => editor?.isActive("orderedList") ?? false
248
+ },
249
+ {
250
+ name: "Quote",
251
+ icon: ui.FormatQuoteIcon,
252
+ command: (editor) => editor?.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
253
+ isActive: (editor) => editor?.isActive("blockquote") ?? false
254
+ },
255
+ {
256
+ name: "Code",
257
+ icon: ui.CodeIcon,
258
+ command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),
259
+ isActive: (editor) => editor?.isActive("codeBlock") ?? false
260
+ }
261
+ ];
262
+ const NodeSelector = ({
263
+ open,
264
+ onOpenChange
265
+ }) => {
266
+ const { editor } = react.useCurrentEditor();
267
+ if (!editor) return null;
268
+ const activeItem = items.filter((item) => item.isActive(editor)).pop() ?? {
269
+ name: "Multiple"
270
+ };
271
+ return /* @__PURE__ */ jsxRuntime.jsx(
272
+ ui.Popover,
273
+ {
274
+ sideOffset: 5,
275
+ align: "start",
276
+ className: "w-48 p-1",
277
+ trigger: /* @__PURE__ */ jsxRuntime.jsxs(
278
+ ui.Button,
279
+ {
280
+ variant: "text",
281
+ className: "gap-2 rounded-none",
282
+ color: "text",
283
+ children: [
284
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap text-sm", children: activeItem.name }),
285
+ /* @__PURE__ */ jsxRuntime.jsx(ui.ExpandMoreIcon, { size: "small" })
286
+ ]
287
+ }
288
+ ),
289
+ modal: true,
290
+ open,
291
+ onOpenChange,
292
+ children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
293
+ EditorBubbleItem,
294
+ {
295
+ onSelect: (editor2) => {
296
+ item.command(editor2);
297
+ onOpenChange(false);
298
+ },
299
+ 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",
300
+ children: [
301
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
302
+ /* @__PURE__ */ jsxRuntime.jsx(item.icon, { size: "smallest" }),
303
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.name })
304
+ ] }),
305
+ activeItem.name === item.name && /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "smallest" })
306
+ ]
307
+ },
308
+ index
309
+ ))
310
+ }
311
+ );
312
+ };
313
+ function isValidUrl(url) {
314
+ try {
315
+ new URL(url);
316
+ return true;
317
+ } catch (e) {
318
+ return false;
319
+ }
320
+ }
321
+ function getUrlFromString(str) {
322
+ if (isValidUrl(str)) return str;
323
+ try {
324
+ if (str.includes(".") && !str.includes(" ")) {
325
+ return new URL(`https://${str}`).toString();
326
+ }
327
+ return null;
328
+ } catch (e) {
329
+ return null;
330
+ }
331
+ }
332
+ const LinkSelector = ({
333
+ open,
334
+ onOpenChange
335
+ }) => {
336
+ const inputRef = React.useRef(null);
337
+ const { editor } = react.useCurrentEditor();
338
+ React.useEffect(() => {
339
+ inputRef.current && inputRef.current?.focus();
340
+ });
341
+ if (!editor) return null;
342
+ return /* @__PURE__ */ jsxRuntime.jsx(
343
+ ui.Popover,
344
+ {
345
+ modal: true,
346
+ open,
347
+ onOpenChange,
348
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(
349
+ ui.Button,
350
+ {
351
+ variant: "text",
352
+ className: "gap-2 rounded-none",
353
+ color: "text",
354
+ children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: ui.cls("underline decoration-stone-400 underline-offset-4", {
355
+ "text-blue-500": editor.isActive("link")
356
+ }), children: "Link" })
357
+ }
358
+ ),
359
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
360
+ "form",
361
+ {
362
+ onSubmit: (e) => {
363
+ const target = e.currentTarget;
364
+ e.preventDefault();
365
+ const input = target[0];
366
+ const url = getUrlFromString(input.value);
367
+ url && editor.chain().focus().setLink({ href: url }).run();
368
+ },
369
+ className: "flex p-1",
370
+ children: [
371
+ /* @__PURE__ */ jsxRuntime.jsx(
372
+ "input",
373
+ {
374
+ ref: inputRef,
375
+ autoFocus: open,
376
+ placeholder: "Paste a link",
377
+ defaultValue: editor.getAttributes("link").href || "",
378
+ className: "text-gray-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none"
379
+ }
380
+ ),
381
+ editor.getAttributes("link").href ? /* @__PURE__ */ jsxRuntime.jsx(
382
+ ui.Button,
383
+ {
384
+ size: "small",
385
+ variant: "text",
386
+ type: "button",
387
+ color: "text",
388
+ className: "flex items-center",
389
+ onClick: () => {
390
+ editor.chain().focus().unsetLink().run();
391
+ },
392
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.DeleteIcon, { size: "small" })
393
+ }
394
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
395
+ ui.Button,
396
+ {
397
+ size: "small",
398
+ variant: "text",
399
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckIcon, { size: "small" })
400
+ }
401
+ )
402
+ ]
403
+ }
404
+ )
405
+ }
406
+ );
407
+ };
408
+ const TextButtons = () => {
409
+ const { editor } = react.useCurrentEditor();
410
+ if (!editor) return null;
411
+ const items2 = [
412
+ {
413
+ name: "bold",
414
+ isActive: (editor2) => editor2?.isActive("bold") ?? false,
415
+ command: (editor2) => editor2?.chain().focus().toggleBold().run(),
416
+ icon: ui.FormatBoldIcon
417
+ },
418
+ {
419
+ name: "italic",
420
+ isActive: (editor2) => editor2?.isActive("italic") ?? false,
421
+ command: (editor2) => editor2?.chain().focus().toggleItalic().run(),
422
+ icon: ui.FormatItalicIcon
423
+ },
424
+ {
425
+ name: "underline",
426
+ isActive: (editor2) => editor2?.isActive("underline") ?? false,
427
+ command: (editor2) => editor2?.chain().focus().toggleUnderline().run(),
428
+ icon: ui.FormatUnderlinedIcon
429
+ },
430
+ {
431
+ name: "strike",
432
+ isActive: (editor2) => editor2?.isActive("strike") ?? false,
433
+ command: (editor2) => editor2?.chain().focus().toggleStrike().run(),
434
+ icon: ui.FormatStrikethroughIcon
435
+ },
436
+ {
437
+ name: "code",
438
+ isActive: (editor2) => editor2?.isActive("code") ?? false,
439
+ command: (editor2) => editor2?.chain().focus().toggleCode().run(),
440
+ icon: ui.CodeIcon
441
+ }
442
+ ];
443
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: items2.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
444
+ EditorBubbleItem,
445
+ {
446
+ onSelect: (editor2) => {
447
+ item.command(editor2);
448
+ },
449
+ children: /* @__PURE__ */ jsxRuntime.jsx(
450
+ ui.Button,
451
+ {
452
+ size: "small",
453
+ color: "text",
454
+ className: "gap-2 rounded-none h-full",
455
+ variant: "text",
456
+ children: /* @__PURE__ */ jsxRuntime.jsx(
457
+ item.icon,
458
+ {
459
+ className: ui.cls({
460
+ "text-inherit": !item.isActive(editor),
461
+ "text-blue-500": item.isActive(editor)
462
+ })
463
+ }
464
+ )
465
+ }
466
+ )
467
+ },
468
+ index
469
+ )) });
470
+ };
471
+ function useDebouncedCallback(value, callback, immediate, timeoutMs = 300) {
472
+ const pendingUpdate = React.useRef(false);
473
+ const performUpdate = () => {
474
+ callback();
475
+ pendingUpdate.current = false;
476
+ };
477
+ const handlerRef = React.useRef(void 0);
478
+ React.useEffect(
479
+ () => {
480
+ pendingUpdate.current = true;
481
+ clearTimeout(handlerRef.current);
482
+ handlerRef.current = setTimeout(performUpdate, timeoutMs);
483
+ return () => {
484
+ };
485
+ },
486
+ [immediate, value]
487
+ );
488
+ }
489
+ function removeClassesFromJson(jsonObj) {
490
+ if (Array.isArray(jsonObj)) {
491
+ return jsonObj.map((item) => removeClassesFromJson(item));
492
+ } else if (typeof jsonObj === "object" && jsonObj !== null) {
493
+ if (jsonObj.attrs && typeof jsonObj.attrs === "object" && "class" in jsonObj.attrs) {
494
+ delete jsonObj.attrs.class;
495
+ }
496
+ Object.keys(jsonObj).forEach((key) => {
497
+ jsonObj[key] = removeClassesFromJson(jsonObj[key]);
498
+ });
499
+ }
500
+ return jsonObj;
501
+ }
502
+ const placeholder = PlaceholderExtension;
503
+ const tiptapLink = TiptapLink.configure({
504
+ HTMLAttributes: {
505
+ class: ui.cls(
506
+ "text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer"
507
+ )
508
+ }
509
+ });
510
+ const taskList = extensionTaskList.TaskList.configure({
511
+ HTMLAttributes: {
512
+ class: ui.cls("not-prose")
513
+ }
514
+ });
515
+ const taskItem = extensionTaskItem.TaskItem.configure({
516
+ HTMLAttributes: {
517
+ class: ui.cls("flex items-start my-4")
518
+ },
519
+ nested: true
520
+ });
521
+ const horizontalRule = Horizontal.configure({
522
+ HTMLAttributes: {
523
+ class: ui.cls("mt-4 mb-6 border-t", ui.defaultBorderMixin)
524
+ }
525
+ });
526
+ const starterKit = StarterKit.configure({
527
+ bulletList: {
528
+ HTMLAttributes: {
529
+ class: ui.cls("list-disc list-outside leading-3 -mt-2")
530
+ }
531
+ },
532
+ orderedList: {
533
+ HTMLAttributes: {
534
+ class: ui.cls("list-decimal list-outside leading-3 -mt-2")
535
+ }
536
+ },
537
+ listItem: {
538
+ HTMLAttributes: {
539
+ class: ui.cls("leading-normal -mb-2")
540
+ }
541
+ },
542
+ blockquote: {
543
+ HTMLAttributes: {
544
+ class: ui.cls("border-l-4 border-primary")
545
+ }
546
+ },
547
+ codeBlock: {
548
+ HTMLAttributes: {
549
+ class: ui.cls("rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium", ui.defaultBorderMixin)
550
+ }
551
+ },
552
+ code: {
553
+ HTMLAttributes: {
554
+ class: ui.cls("rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium"),
555
+ spellcheck: "false"
556
+ }
557
+ },
558
+ horizontalRule: false,
559
+ dropcursor: {
560
+ color: "#DBEAFE",
561
+ width: 4
562
+ },
563
+ gapcursor: false
564
+ });
565
+ async function onFileRead(plugin, view$1, readerEvent, pos, upload, image) {
566
+ const { schema } = view$1.state;
567
+ let decorationSet = plugin.getState(view$1.state);
568
+ const placeholder2 = document.createElement("div");
569
+ const imageElement = document.createElement("img");
570
+ imageElement.setAttribute("class", "opacity-40 rounded-lg border border-stone-200");
571
+ imageElement.src = readerEvent.target?.result;
572
+ placeholder2.appendChild(imageElement);
573
+ const deco = view.Decoration.widget(pos, placeholder2);
574
+ decorationSet = decorationSet?.add(view$1.state.doc, [deco]);
575
+ view$1.dispatch(view$1.state.tr.setMeta(plugin, { decorationSet }));
576
+ const src = await upload(image);
577
+ console.log("uploaded image", src);
578
+ const imageNode = schema.nodes.image.create({ src });
579
+ const tr = view$1.state.tr.replaceWith(pos, pos, imageNode);
580
+ decorationSet = decorationSet?.remove([deco]);
581
+ tr.setMeta(plugin, { decorationSet });
582
+ view$1.dispatch(tr);
583
+ }
584
+ const dropImagePlugin = (upload) => {
585
+ const plugin = new prosemirrorState.Plugin({
586
+ state: {
587
+ // Initialize the plugin state with an empty DecorationSet
588
+ init: () => view.DecorationSet.empty,
589
+ // Apply transactions to update the state
590
+ apply: (tr, old) => {
591
+ const meta = tr.getMeta(plugin);
592
+ if (meta && meta.decorationSet) {
593
+ return meta.decorationSet;
594
+ }
595
+ return old.map(tr.mapping, tr.doc);
596
+ }
597
+ },
598
+ props: {
599
+ handleDOMEvents: {
600
+ drop: (view2, event) => {
601
+ console.log("drop event", event);
602
+ if (!event.dataTransfer?.files || event.dataTransfer?.files.length === 0) {
603
+ return false;
604
+ }
605
+ event.preventDefault();
606
+ const files = Array.from(event.dataTransfer.files);
607
+ const images = files.filter((file) => /image/i.test(file.type));
608
+ if (images.length === 0) return false;
609
+ images.forEach((image) => {
610
+ const position = view2.posAtCoords({ left: event.clientX, top: event.clientY });
611
+ if (!position) return;
612
+ const reader = new FileReader();
613
+ reader.onload = async (readerEvent) => {
614
+ await onFileRead(plugin, view2, readerEvent, position.pos, upload, image);
615
+ };
616
+ reader.readAsDataURL(image);
617
+ });
618
+ return true;
619
+ }
620
+ },
621
+ handlePaste(view2, event, slice) {
622
+ const items2 = Array.from(event.clipboardData?.items || []);
623
+ const pos = view2.state.selection.from;
624
+ console.log("pos", pos);
625
+ let anyImageFound = false;
626
+ items2.forEach((item) => {
627
+ const image = item.getAsFile();
628
+ console.log("image", image);
629
+ if (image) {
630
+ anyImageFound = true;
631
+ const reader = new FileReader();
632
+ reader.onload = async (readerEvent) => {
633
+ await onFileRead(plugin, view2, readerEvent, pos, upload, image);
634
+ };
635
+ reader.readAsDataURL(image);
636
+ }
637
+ });
638
+ return anyImageFound;
639
+ },
640
+ decorations(state2) {
641
+ return plugin.getState(state2);
642
+ }
643
+ },
644
+ view(editorView) {
645
+ return {
646
+ update(view2, prevState) {
647
+ const prevDecos = plugin.getState(prevState);
648
+ const newDecos = plugin.getState(view2.state);
649
+ if (prevDecos !== newDecos) {
650
+ view2.updateState(view2.state);
651
+ }
652
+ }
653
+ };
654
+ }
655
+ });
656
+ return plugin;
657
+ };
658
+ const createImageExtension = (uploadFn) => {
659
+ return TiptapImage.extend({
660
+ addProseMirrorPlugins() {
661
+ return [dropImagePlugin(uploadFn)];
662
+ }
663
+ }).configure({
664
+ allowBase64: true,
665
+ HTMLAttributes: {
666
+ class: ui.cls("rounded-lg border", ui.defaultBorderMixin)
667
+ }
668
+ });
669
+ };
670
+ const CustomKeymap = core.Extension.create({
671
+ name: "CustomKeymap",
672
+ addCommands() {
673
+ return {
674
+ selectTextWithinNodeBoundaries: () => ({ editor, commands }) => {
675
+ const { state: state2 } = editor;
676
+ const { tr } = state2;
677
+ const startNodePos = tr.selection.$from.start();
678
+ const endNodePos = tr.selection.$to.end();
679
+ return commands.setTextSelection({
680
+ from: startNodePos,
681
+ to: endNodePos
682
+ });
683
+ }
684
+ };
685
+ },
686
+ addKeyboardShortcuts() {
687
+ return {
688
+ "Mod-a": ({ editor }) => {
689
+ const { state: state2 } = editor;
690
+ const { tr } = state2;
691
+ const startSelectionPos = tr.selection.from;
692
+ const endSelectionPos = tr.selection.to;
693
+ const startNodePos = tr.selection.$from.start();
694
+ const endNodePos = tr.selection.$to.end();
695
+ const isCurrentTextSelectionNotExtendedToNodeBoundaries = startSelectionPos > startNodePos || endSelectionPos < endNodePos;
696
+ if (isCurrentTextSelectionNotExtendedToNodeBoundaries) {
697
+ editor.chain().selectTextWithinNodeBoundaries().run();
698
+ return true;
699
+ }
700
+ return false;
701
+ }
702
+ };
703
+ }
704
+ });
705
+ function absoluteRect(node) {
706
+ const data = node.getBoundingClientRect();
707
+ return {
708
+ top: data.top,
709
+ left: data.left,
710
+ width: data.width
711
+ };
712
+ }
713
+ function nodeDOMAtCoords(coords) {
714
+ return document.elementsFromPoint(coords.x, coords.y).find(
715
+ (elem) => elem.parentElement?.matches?.(".ProseMirror") || elem.matches(
716
+ ["li", "p:not(:first-child)", "pre", "blockquote", "h1, h2, h3, h4, h5, h6"].join(", ")
717
+ )
718
+ );
719
+ }
720
+ function nodePosAtDOM(node, view2, options) {
721
+ const boundingRect = node.getBoundingClientRect();
722
+ return view2.posAtCoords({
723
+ left: boundingRect.left + 50 + options.dragHandleWidth,
724
+ top: boundingRect.top + 1
725
+ })?.inside;
726
+ }
727
+ function DragHandle(options) {
728
+ function handleDragStart(event, view$1) {
729
+ view$1.focus();
730
+ if (!event.dataTransfer) return;
731
+ const node = nodeDOMAtCoords({
732
+ x: event.clientX + 50 + options.dragHandleWidth,
733
+ y: event.clientY
734
+ });
735
+ if (!(node instanceof Element)) return;
736
+ const nodePos = nodePosAtDOM(node, view$1, options);
737
+ if (nodePos == null || nodePos < 0) return;
738
+ view$1.dispatch(view$1.state.tr.setSelection(state.NodeSelection.create(view$1.state.doc, nodePos)));
739
+ const slice = view$1.state.selection.content();
740
+ const { dom, text } = view.__serializeForClipboard(view$1, slice);
741
+ event.dataTransfer.clearData();
742
+ event.dataTransfer.setData("text/html", dom.innerHTML);
743
+ event.dataTransfer.setData("text/plain", text);
744
+ event.dataTransfer.effectAllowed = "copyMove";
745
+ event.dataTransfer.setDragImage(node, 0, 0);
746
+ view$1.dragging = { slice, move: event.ctrlKey };
747
+ }
748
+ function handleClick(event, view2) {
749
+ view2.focus();
750
+ view2.dom.classList.remove("dragging");
751
+ const node = nodeDOMAtCoords({
752
+ x: event.clientX + 50 + options.dragHandleWidth,
753
+ y: event.clientY
754
+ });
755
+ if (!(node instanceof Element)) return;
756
+ const nodePos = nodePosAtDOM(node, view2, options);
757
+ if (!nodePos) return;
758
+ view2.dispatch(view2.state.tr.setSelection(state.NodeSelection.create(view2.state.doc, nodePos)));
759
+ }
760
+ let dragHandleElement = null;
761
+ function hideDragHandle() {
762
+ if (dragHandleElement) {
763
+ dragHandleElement.classList.add("hide");
764
+ }
765
+ }
766
+ function showDragHandle() {
767
+ if (dragHandleElement) {
768
+ dragHandleElement.classList.remove("hide");
769
+ }
770
+ }
771
+ return new state.Plugin({
772
+ view: (view2) => {
773
+ dragHandleElement = document.createElement("div");
774
+ dragHandleElement.draggable = true;
775
+ dragHandleElement.dataset.dragHandle = "";
776
+ dragHandleElement.classList.add("drag-handle");
777
+ dragHandleElement.addEventListener("dragstart", (e) => {
778
+ handleDragStart(e, view2);
779
+ });
780
+ dragHandleElement.addEventListener("click", (e) => {
781
+ handleClick(e, view2);
782
+ });
783
+ hideDragHandle();
784
+ view2?.dom?.parentElement?.appendChild(dragHandleElement);
785
+ return {
786
+ destroy: () => {
787
+ dragHandleElement?.remove?.();
788
+ dragHandleElement = null;
789
+ }
790
+ };
791
+ },
792
+ props: {
793
+ handleDOMEvents: {
794
+ mousemove: (view2, event) => {
795
+ if (!view2.editable) {
796
+ return;
797
+ }
798
+ const node = nodeDOMAtCoords({
799
+ x: event.clientX + 50 + options.dragHandleWidth,
800
+ y: event.clientY
801
+ });
802
+ if (!(node instanceof Element)) {
803
+ hideDragHandle();
804
+ return;
805
+ }
806
+ const compStyle = window.getComputedStyle(node);
807
+ const lineHeight = parseInt(compStyle.lineHeight, 10);
808
+ const paddingTop = parseInt(compStyle.paddingTop, 10);
809
+ const rect = absoluteRect(node);
810
+ rect.top += (lineHeight - 24) / 2;
811
+ rect.top += paddingTop;
812
+ if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
813
+ rect.left -= options.dragHandleWidth;
814
+ }
815
+ rect.width = options.dragHandleWidth;
816
+ if (!dragHandleElement) return;
817
+ dragHandleElement.style.left = `${rect.left - rect.width}px`;
818
+ dragHandleElement.style.top = `${rect.top}px`;
819
+ showDragHandle();
820
+ },
821
+ keydown: () => {
822
+ hideDragHandle();
823
+ },
824
+ mousewheel: () => {
825
+ hideDragHandle();
826
+ },
827
+ // dragging class is used for CSS
828
+ dragstart: (view2) => {
829
+ view2.dom.classList.add("dragging");
830
+ },
831
+ drop: (view2) => {
832
+ view2.dom.classList.remove("dragging");
833
+ },
834
+ dragend: (view2) => {
835
+ view2.dom.classList.remove("dragging");
836
+ }
837
+ }
838
+ }
839
+ });
840
+ }
841
+ const DragAndDrop = core.Extension.create({
842
+ name: "dragAndDrop",
843
+ addProseMirrorPlugins() {
844
+ return [
845
+ DragHandle({
846
+ dragHandleWidth: 24
847
+ })
848
+ ];
849
+ }
850
+ });
851
+ const FireCMSEditor = ({
852
+ handleImageUpload,
853
+ initialContent,
854
+ onJsonContentChange,
855
+ onHtmlContentChange,
856
+ onMarkdownContentChange
857
+ }) => {
858
+ const defaultEditorProps = {
859
+ handleDOMEvents: {
860
+ keydown: (_view, event) => {
861
+ if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
862
+ const slashCommand2 = document.querySelector("#slash-command");
863
+ if (slashCommand2) {
864
+ return true;
865
+ }
866
+ }
867
+ return false;
868
+ }
869
+ }
870
+ // handlePaste: (view, event) => {
871
+ // if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {
872
+ // event.preventDefault();
873
+ // const file = event.clipboardData.files[0];
874
+ // const pos = view.state.selection.from;
875
+ //
876
+ // // startImageUpload({ file, view, pos, handleImageUpload });
877
+ // return true;
878
+ // }
879
+ // return false;
880
+ // },
881
+ // handleDrop: (view, event, _slice, moved) => {
882
+ // console.log("handleDrop", { event, moved });
883
+ // if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {
884
+ // console.log("handleDrop!!!", { event, moved });
885
+ // event.preventDefault();
886
+ // const file = event.dataTransfer.files[0];
887
+ // const coordinates = view.posAtCoords({
888
+ // left: event.clientX,
889
+ // top: event.clientY
890
+ // });
891
+ // // here we deduct 1 from the pos or else the image will create an extra node
892
+ // startImageUpload({
893
+ // file,
894
+ // view,
895
+ // pos: coordinates?.pos || 0 - 1,
896
+ // handleImageUpload,
897
+ // });
898
+ // return true;
899
+ // }
900
+ // return false;
901
+ // }
902
+ };
903
+ const suggestionItems = createSuggestionItems([
904
+ {
905
+ title: "Text",
906
+ description: "Just start typing with plain text.",
907
+ searchTerms: ["p", "paragraph"],
908
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.TextFieldsIcon, { size: 18 }),
909
+ command: ({ editor, range }) => {
910
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
911
+ }
912
+ },
913
+ {
914
+ title: "To-do List",
915
+ description: "Track tasks with a to-do list.",
916
+ searchTerms: ["todo", "task", "list", "check", "checkbox"],
917
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckBoxIcon, { size: 18 }),
918
+ command: ({ editor, range }) => {
919
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
920
+ }
921
+ },
922
+ {
923
+ title: "Heading 1",
924
+ description: "Big section heading.",
925
+ searchTerms: ["title", "big", "large"],
926
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.LooksOneIcon, { size: 18 }),
927
+ command: ({ editor, range }) => {
928
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
929
+ }
930
+ },
931
+ {
932
+ title: "Heading 2",
933
+ description: "Medium section heading.",
934
+ searchTerms: ["subtitle", "medium"],
935
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.LooksTwoIcon, { size: 18 }),
936
+ command: ({ editor, range }) => {
937
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
938
+ }
939
+ },
940
+ {
941
+ title: "Heading 3",
942
+ description: "Small section heading.",
943
+ searchTerms: ["subtitle", "small"],
944
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.Looks3Icon, { size: 18 }),
945
+ command: ({ editor, range }) => {
946
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
947
+ }
948
+ },
949
+ {
950
+ title: "Bullet List",
951
+ description: "Create a simple bullet list.",
952
+ searchTerms: ["unordered", "point"],
953
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatListBulletedIcon, { size: 18 }),
954
+ command: ({ editor, range }) => {
955
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
956
+ }
957
+ },
958
+ {
959
+ title: "Numbered List",
960
+ description: "Create a list with numbering.",
961
+ searchTerms: ["ordered"],
962
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatListNumberedIcon, { size: 18 }),
963
+ command: ({ editor, range }) => {
964
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
965
+ }
966
+ },
967
+ {
968
+ title: "Quote",
969
+ description: "Capture a quote.",
970
+ searchTerms: ["blockquote"],
971
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatQuoteIcon, { size: 18 }),
972
+ command: ({ editor, range }) => editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
973
+ },
974
+ {
975
+ title: "Code",
976
+ description: "Capture a code snippet.",
977
+ searchTerms: ["codeblock"],
978
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.CodeIcon, { size: 18 }),
979
+ command: ({ editor, range }) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run()
980
+ },
981
+ {
982
+ title: "Image",
983
+ description: "Upload an image from your computer.",
984
+ searchTerms: ["photo", "picture", "media"],
985
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.ImageIcon, { size: 18 }),
986
+ command: ({ editor, range }) => {
987
+ editor.chain().focus().deleteRange(range).run();
988
+ const input = document.createElement("input");
989
+ input.type = "file";
990
+ input.accept = "image/*";
991
+ input.onchange = async () => {
992
+ if (input.files?.length) {
993
+ const file = input.files[0];
994
+ if (!file) return;
995
+ editor.view.state.selection.from;
996
+ }
997
+ };
998
+ input.click();
999
+ }
1000
+ }
1001
+ ]);
1002
+ const slashCommand = Command.configure({
1003
+ suggestion: {
1004
+ items: () => suggestionItems,
1005
+ render: renderItems
1006
+ }
1007
+ });
1008
+ const imageExtension = React.useMemo(() => createImageExtension(handleImageUpload), []);
1009
+ const extensions = [
1010
+ TiptapUnderline,
1011
+ TextStyle,
1012
+ extensionColor.Color,
1013
+ Highlight.configure({
1014
+ multicolor: true
1015
+ }),
1016
+ tiptapMarkdown.Markdown.configure({
1017
+ html: false,
1018
+ transformCopiedText: true
1019
+ }),
1020
+ CustomKeymap,
1021
+ DragAndDrop,
1022
+ starterKit,
1023
+ placeholder,
1024
+ tiptapLink,
1025
+ // tiptapImage,
1026
+ imageExtension,
1027
+ // updatedImage,
1028
+ taskList,
1029
+ taskItem,
1030
+ horizontalRule,
1031
+ slashCommand
1032
+ ];
1033
+ const [openNode, setOpenNode] = React.useState(false);
1034
+ const [openLink, setOpenLink] = React.useState(false);
1035
+ ui.useInjectStyles("Editor", cssStyles);
1036
+ const editorRef = React.useRef(null);
1037
+ const [markdownContent, setMarkdownContent] = React.useState(null);
1038
+ const [jsonContent, setJsonContent] = React.useState(null);
1039
+ const [htmlContent, setHtmlContent] = React.useState(null);
1040
+ const onEditorUpdate = (editor) => {
1041
+ editorRef.current = editor;
1042
+ if (onMarkdownContentChange) {
1043
+ setMarkdownContent(editor.storage.markdown.getMarkdown());
1044
+ }
1045
+ if (onJsonContentChange) {
1046
+ setJsonContent(removeClassesFromJson(editor.getJSON()));
1047
+ }
1048
+ if (onHtmlContentChange) {
1049
+ setHtmlContent(editor.getHTML());
1050
+ }
1051
+ };
1052
+ useDebouncedCallback(markdownContent, () => {
1053
+ if (editorRef.current) {
1054
+ const markdown = editorRef.current.storage.markdown.getMarkdown();
1055
+ onMarkdownContentChange?.(addLineBreakAfterImages(markdown));
1056
+ }
1057
+ }, false, 500);
1058
+ useDebouncedCallback(jsonContent, () => {
1059
+ if (jsonContent)
1060
+ onJsonContentChange?.(jsonContent);
1061
+ }, false, 500);
1062
+ useDebouncedCallback(htmlContent, () => {
1063
+ if (htmlContent)
1064
+ onHtmlContentChange?.(htmlContent);
1065
+ }, false, 500);
1066
+ if (!initialContent) return null;
1067
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full p-8", children: /* @__PURE__ */ jsxRuntime.jsx(EditorRoot, { children: /* @__PURE__ */ jsxRuntime.jsx(
1068
+ "div",
1069
+ {
1070
+ className: "relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg",
1071
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1072
+ react.EditorProvider,
1073
+ {
1074
+ content: initialContent,
1075
+ extensions,
1076
+ editorProps: {
1077
+ ...defaultEditorProps,
1078
+ attributes: {
1079
+ class: "prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12"
1080
+ }
1081
+ },
1082
+ onUpdate: ({ editor }) => {
1083
+ console.debug("Editor updated");
1084
+ onEditorUpdate(editor);
1085
+ },
1086
+ children: [
1087
+ /* @__PURE__ */ jsxRuntime.jsxs(
1088
+ EditorCommand,
1089
+ {
1090
+ className: ui.cls("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", ui.defaultBorderMixin),
1091
+ children: [
1092
+ /* @__PURE__ */ jsxRuntime.jsx(EditorCommandEmpty, { className: "px-2 text-gray-700 dark:text-slate-300", children: "No results" }),
1093
+ suggestionItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
1094
+ EditorCommandItem,
1095
+ {
1096
+ value: item.title,
1097
+ onCommand: (val) => item?.command?.(val),
1098
+ 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",
1099
+ children: [
1100
+ /* @__PURE__ */ jsxRuntime.jsx(
1101
+ "div",
1102
+ {
1103
+ className: ui.cls("flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-gray-900", ui.defaultBorderMixin),
1104
+ children: item.icon
1105
+ }
1106
+ ),
1107
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1108
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: item.title }),
1109
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-700 dark:text-slate-300", children: item.description })
1110
+ ] })
1111
+ ]
1112
+ },
1113
+ item.title
1114
+ ))
1115
+ ]
1116
+ }
1117
+ ),
1118
+ /* @__PURE__ */ jsxRuntime.jsxs(
1119
+ EditorBubble,
1120
+ {
1121
+ tippyOptions: {
1122
+ placement: "top"
1123
+ },
1124
+ className: ui.cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow", ui.defaultBorderMixin),
1125
+ children: [
1126
+ /* @__PURE__ */ jsxRuntime.jsx(NodeSelector, { open: openNode, onOpenChange: setOpenNode }),
1127
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Separator, { orientation: "vertical" }),
1128
+ /* @__PURE__ */ jsxRuntime.jsx(LinkSelector, { open: openLink, onOpenChange: setOpenLink }),
1129
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Separator, { orientation: "vertical" }),
1130
+ /* @__PURE__ */ jsxRuntime.jsx(TextButtons, {})
1131
+ ]
1132
+ }
1133
+ )
1134
+ ]
1135
+ }
1136
+ )
1137
+ }
1138
+ ) }) });
1139
+ };
1140
+ function addLineBreakAfterImages(markdown) {
1141
+ const imageRegex = /!\[.*?\]\(.*?\)/g;
1142
+ return markdown.replace(imageRegex, (match) => `${match}
1143
+ `);
1144
+ }
1145
+ const cssStyles = `
3
1146
 
4
1147
  .ProseMirror .is-editor-empty:first-child::before {
5
1148
  content: attr(data-placeholder);
@@ -189,5 +1332,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
189
1332
  background-color: rgb(51 65 85); // 700
190
1333
  }
191
1334
  }
192
- `;u.FireCMSEditor=Pe,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
1335
+ `;
1336
+ exports2.FireCMSEditor = FireCMSEditor;
1337
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
1338
+ });
193
1339
  //# sourceMappingURL=index.umd.js.map