@firecms/editor 3.0.0-canary.25 → 3.0.0-canary.251

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,1978 @@
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("prosemirror-model"), 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", "prosemirror-model", "@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.prosemirrorModel, 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, prosemirrorModel, 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 serializeForClipboard(view2, slice) {
936
+ view2.someProp("transformCopied", (f) => {
937
+ slice = f(slice, view2);
938
+ });
939
+ const context = [];
940
+ let {
941
+ content,
942
+ openStart,
943
+ openEnd
944
+ } = slice;
945
+ while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
946
+ openStart--;
947
+ openEnd--;
948
+ const node = content.firstChild;
949
+ context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null);
950
+ content = node.content;
951
+ }
952
+ const serializer = view2.someProp("clipboardSerializer") || prosemirrorModel.DOMSerializer.fromSchema(view2.state.schema);
953
+ const doc = detachedDoc(), wrap = doc.createElement("div");
954
+ wrap.appendChild(serializer.serializeFragment(content, {
955
+ document: doc
956
+ }));
957
+ let firstChild = wrap.firstChild, needsWrap, wrappers = 0;
958
+ while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
959
+ for (let i = needsWrap.length - 1; i >= 0; i--) {
960
+ const wrapper = doc.createElement(needsWrap[i]);
961
+ while (wrap.firstChild) wrapper.appendChild(wrap.firstChild);
962
+ wrap.appendChild(wrapper);
963
+ wrappers++;
964
+ }
965
+ firstChild = wrap.firstChild;
966
+ }
967
+ if (firstChild && firstChild.nodeType == 1) firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
968
+ const text = view2.someProp("clipboardTextSerializer", (f) => f(slice, view2)) || slice.content.textBetween(0, slice.content.size, "\n\n");
969
+ return {
970
+ dom: wrap,
971
+ text,
972
+ slice
973
+ };
974
+ }
975
+ const wrapMap = {
976
+ thead: ["table"],
977
+ tbody: ["table"],
978
+ tfoot: ["table"],
979
+ caption: ["table"],
980
+ colgroup: ["table"],
981
+ col: ["table", "colgroup"],
982
+ tr: ["table", "tbody"],
983
+ td: ["table", "tbody", "tr"],
984
+ th: ["table", "tbody", "tr"]
985
+ };
986
+ let _detachedDoc = null;
987
+ function detachedDoc() {
988
+ return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
989
+ }
990
+ function absoluteRect(element) {
991
+ const data = element.getBoundingClientRect();
992
+ let ancestor = element.parentElement;
993
+ while (ancestor && window.getComputedStyle(ancestor).position === "static") {
994
+ ancestor = ancestor.parentElement;
995
+ }
996
+ const ancestorRect = ancestor?.getBoundingClientRect();
997
+ return {
998
+ top: data.top - (ancestorRect?.top ?? 0),
999
+ left: data.left - (ancestorRect?.left ?? 0),
1000
+ width: data.width
1001
+ };
1002
+ }
1003
+ function nodeDOMAtCoords(coords) {
1004
+ 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(", ")));
1005
+ }
1006
+ function nodePosAtDOM(node, view2, options) {
1007
+ const boundingRect = node.getBoundingClientRect();
1008
+ return view2.posAtCoords({
1009
+ left: boundingRect.left + 50 + options.dragHandleWidth,
1010
+ top: boundingRect.top + 1
1011
+ })?.inside;
1012
+ }
1013
+ function DragHandle(options) {
1014
+ function handleDragStart(event, view2) {
1015
+ view2.focus();
1016
+ if (!event.dataTransfer) return;
1017
+ const node = nodeDOMAtCoords({
1018
+ x: event.clientX + 50 + options.dragHandleWidth,
1019
+ y: event.clientY
1020
+ });
1021
+ if (!(node instanceof Element)) return;
1022
+ const nodePos = nodePosAtDOM(node, view2, options);
1023
+ if (nodePos == null || nodePos < 0) return;
1024
+ view2.dispatch(view2.state.tr.setSelection(state.NodeSelection.create(view2.state.doc, nodePos)));
1025
+ const slice = view2.state.selection.content();
1026
+ const {
1027
+ dom,
1028
+ text
1029
+ } = serializeForClipboard(view2, slice);
1030
+ event.dataTransfer.clearData();
1031
+ event.dataTransfer.setData("text/html", dom.innerHTML);
1032
+ event.dataTransfer.setData("text/plain", text);
1033
+ event.dataTransfer.effectAllowed = "copyMove";
1034
+ event.dataTransfer.setDragImage(node, 0, 0);
1035
+ view2.dragging = {
1036
+ slice,
1037
+ move: event.ctrlKey
1038
+ };
1039
+ }
1040
+ function handleClick(event, view2) {
1041
+ view2.focus();
1042
+ view2.dom.classList.remove("dragging");
1043
+ const node = nodeDOMAtCoords({
1044
+ x: event.clientX + 50 + options.dragHandleWidth,
1045
+ y: event.clientY
1046
+ });
1047
+ if (!(node instanceof Element)) return;
1048
+ const nodePos = nodePosAtDOM(node, view2, options);
1049
+ if (!nodePos) return;
1050
+ view2.dispatch(view2.state.tr.setSelection(state.NodeSelection.create(view2.state.doc, nodePos)));
1051
+ }
1052
+ let dragHandleElement = null;
1053
+ function hideDragHandle() {
1054
+ if (dragHandleElement) {
1055
+ dragHandleElement.classList.add("hide");
1056
+ }
1057
+ }
1058
+ function showDragHandle() {
1059
+ if (dragHandleElement) {
1060
+ dragHandleElement.classList.remove("hide");
1061
+ }
1062
+ }
1063
+ return new state.Plugin({
1064
+ view: (view2) => {
1065
+ dragHandleElement = document.createElement("div");
1066
+ dragHandleElement.draggable = true;
1067
+ dragHandleElement.dataset.dragHandle = "";
1068
+ dragHandleElement.classList.add("drag-handle");
1069
+ dragHandleElement.addEventListener("dragstart", (e) => {
1070
+ handleDragStart(e, view2);
1071
+ });
1072
+ dragHandleElement.addEventListener("click", (e) => {
1073
+ handleClick(e, view2);
1074
+ });
1075
+ hideDragHandle();
1076
+ view2?.dom?.parentElement?.appendChild(dragHandleElement);
1077
+ return {
1078
+ destroy: () => {
1079
+ }
1080
+ };
1081
+ },
1082
+ props: {
1083
+ handleDOMEvents: {
1084
+ mousemove: (view2, event) => {
1085
+ if (!view2.editable) {
1086
+ return;
1087
+ }
1088
+ const node = nodeDOMAtCoords({
1089
+ x: event.clientX + 50 + options.dragHandleWidth,
1090
+ y: event.clientY
1091
+ });
1092
+ if (!(node instanceof Element)) {
1093
+ hideDragHandle();
1094
+ return;
1095
+ }
1096
+ const compStyle = window.getComputedStyle(node);
1097
+ const lineHeight = parseInt(compStyle.lineHeight, 10);
1098
+ const paddingTop = parseInt(compStyle.paddingTop, 10);
1099
+ const rect = absoluteRect(node);
1100
+ rect.top += (lineHeight - 24) / 2;
1101
+ rect.top += paddingTop;
1102
+ if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
1103
+ rect.left -= options.dragHandleWidth;
1104
+ }
1105
+ rect.width = options.dragHandleWidth;
1106
+ if (!dragHandleElement) return;
1107
+ dragHandleElement.style.left = `${rect.left - rect.width}px`;
1108
+ dragHandleElement.style.top = `${rect.top}px`;
1109
+ showDragHandle();
1110
+ },
1111
+ keydown: () => {
1112
+ hideDragHandle();
1113
+ },
1114
+ mousewheel: () => {
1115
+ hideDragHandle();
1116
+ },
1117
+ // dragging class is used for CSS
1118
+ dragstart: (view2) => {
1119
+ view2.dom.classList.add("dragging");
1120
+ },
1121
+ drop: (view2) => {
1122
+ view2.dom.classList.remove("dragging");
1123
+ },
1124
+ dragend: (view2) => {
1125
+ view2.dom.classList.remove("dragging");
1126
+ }
1127
+ }
1128
+ }
1129
+ });
1130
+ }
1131
+ const DragAndDrop = core.Extension.create({
1132
+ name: "dragAndDrop",
1133
+ addProseMirrorPlugins() {
1134
+ return [DragHandle({
1135
+ dragHandleWidth: 24
1136
+ })];
1137
+ }
1138
+ });
1139
+ function buildDecorationSet(highlight, doc) {
1140
+ const decorations = [];
1141
+ if (highlight) {
1142
+ decorations.push(view.Decoration.inline(highlight.from, highlight.to, {
1143
+ class: "dark:bg-surface-accent-700 bg-surface-accent-300"
1144
+ }));
1145
+ }
1146
+ const decorationSet = view.DecorationSet.create(doc, decorations);
1147
+ return decorationSet;
1148
+ }
1149
+ const HighlightDecorationExtension = (initialHighlight) => core.Extension.create({
1150
+ name: "highlightDecoration",
1151
+ addOptions() {
1152
+ return {
1153
+ pluginKey: new state.PluginKey("highlightDecoration"),
1154
+ highlight: initialHighlight
1155
+ };
1156
+ },
1157
+ addProseMirrorPlugins() {
1158
+ const pluginKey = this.options.pluginKey;
1159
+ return [new state.Plugin({
1160
+ key: pluginKey,
1161
+ state: {
1162
+ init: (_, {
1163
+ doc
1164
+ }) => {
1165
+ const highlight = this.options.highlight;
1166
+ const decorationSet = highlight && doc ? buildDecorationSet(highlight, doc) : view.DecorationSet.empty;
1167
+ return {
1168
+ decorationSet,
1169
+ highlight
1170
+ };
1171
+ },
1172
+ apply(transaction, oldState) {
1173
+ const action = transaction.getMeta(pluginKey);
1174
+ const highlight = action?.range;
1175
+ if (action?.type === "highlightDecoration") {
1176
+ const doc = transaction.doc;
1177
+ const {
1178
+ remove
1179
+ } = action;
1180
+ if (remove) {
1181
+ return {
1182
+ decorationSet: view.DecorationSet.empty
1183
+ };
1184
+ }
1185
+ const decorationSet = buildDecorationSet(highlight, doc);
1186
+ return {
1187
+ decorationSet,
1188
+ highlight
1189
+ };
1190
+ } else {
1191
+ return oldState;
1192
+ }
1193
+ }
1194
+ },
1195
+ props: {
1196
+ decorations(state2) {
1197
+ const autocompleteState = this.getState(state2);
1198
+ if (autocompleteState?.decorationSet) {
1199
+ return autocompleteState.decorationSet;
1200
+ } else {
1201
+ return view.DecorationSet.empty;
1202
+ }
1203
+ }
1204
+ }
1205
+ })];
1206
+ },
1207
+ addCommands() {
1208
+ return {
1209
+ toggleAutocompleteHighlight: (range) => ({
1210
+ state: state2,
1211
+ dispatch
1212
+ }) => {
1213
+ const {
1214
+ selection
1215
+ } = state2;
1216
+ const pos = selection.from;
1217
+ if (!dispatch) return false;
1218
+ const pluginKey = this.options.pluginKey;
1219
+ const tr = state2.tr.setMeta(pluginKey, {
1220
+ pos,
1221
+ type: "highlightDecoration",
1222
+ remove: false,
1223
+ range
1224
+ });
1225
+ dispatch(tr);
1226
+ return true;
1227
+ },
1228
+ removeAutocompleteHighlight: () => ({
1229
+ state: state2,
1230
+ dispatch
1231
+ }) => {
1232
+ if (!dispatch) return false;
1233
+ const pluginKey = this.options.pluginKey;
1234
+ const tr = state2.tr.setMeta(pluginKey, {
1235
+ pos: 0,
1236
+ // We can pass any position as it will remove the entire decoration set
1237
+ type: "highlightDecoration",
1238
+ remove: true
1239
+ });
1240
+ dispatch(tr);
1241
+ return true;
1242
+ }
1243
+ };
1244
+ }
1245
+ });
1246
+ const CommandPluginKey = new state.PluginKey("slash-command");
1247
+ const SlashCommand = react.Node.create({
1248
+ name: "command",
1249
+ addOptions() {
1250
+ return {
1251
+ HTMLAttributes: {},
1252
+ renderText({
1253
+ options,
1254
+ node
1255
+ }) {
1256
+ return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
1257
+ },
1258
+ deleteTriggerWithBackspace: false,
1259
+ renderHTML({
1260
+ options,
1261
+ node
1262
+ }) {
1263
+ return ["span", react.mergeAttributes(this.HTMLAttributes, options.HTMLAttributes), `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`];
1264
+ },
1265
+ suggestion: {
1266
+ char: "/",
1267
+ pluginKey: CommandPluginKey,
1268
+ command: ({
1269
+ editor,
1270
+ range,
1271
+ props
1272
+ }) => {
1273
+ const nodeAfter = editor.view.state.selection.$to.nodeAfter;
1274
+ const overrideSpace = nodeAfter?.text?.startsWith(" ");
1275
+ if (overrideSpace) {
1276
+ range.to += 1;
1277
+ }
1278
+ editor.chain().focus().insertContentAt(range, [{
1279
+ type: this.name,
1280
+ attrs: props
1281
+ }, {
1282
+ type: "text",
1283
+ text: " "
1284
+ }]).run();
1285
+ window.getSelection()?.collapseToEnd();
1286
+ },
1287
+ allow: ({
1288
+ state: state2,
1289
+ range
1290
+ }) => {
1291
+ const $from = state2.doc.resolve(range.from);
1292
+ const type = state2.schema.nodes[this.name];
1293
+ const allow = !!$from.parent.type.contentMatch.matchType(type);
1294
+ return allow;
1295
+ }
1296
+ }
1297
+ };
1298
+ },
1299
+ group: "inline",
1300
+ inline: true,
1301
+ selectable: false,
1302
+ atom: true,
1303
+ addAttributes() {
1304
+ return {
1305
+ id: {
1306
+ default: null,
1307
+ parseHTML: (element) => element.getAttribute("data-id"),
1308
+ renderHTML: (attributes) => {
1309
+ if (!attributes.id) {
1310
+ return {};
1311
+ }
1312
+ return {
1313
+ "data-id": attributes.id
1314
+ };
1315
+ }
1316
+ },
1317
+ label: {
1318
+ default: null,
1319
+ parseHTML: (element) => element.getAttribute("data-label"),
1320
+ renderHTML: (attributes) => {
1321
+ if (!attributes.label) {
1322
+ return {};
1323
+ }
1324
+ return {
1325
+ "data-label": attributes.label
1326
+ };
1327
+ }
1328
+ }
1329
+ };
1330
+ },
1331
+ parseHTML() {
1332
+ return [{
1333
+ tag: `span[data-type="${this.name}"]`
1334
+ }];
1335
+ },
1336
+ renderHTML({
1337
+ node,
1338
+ HTMLAttributes
1339
+ }) {
1340
+ if (this.options.renderLabel !== void 0) {
1341
+ console.warn("renderLabel is deprecated use renderText and renderHTML instead");
1342
+ return ["span", react.mergeAttributes({
1343
+ "data-type": this.name
1344
+ }, this.options.HTMLAttributes, HTMLAttributes), this.options.renderLabel({
1345
+ options: this.options,
1346
+ node
1347
+ })];
1348
+ }
1349
+ const mergedOptions = {
1350
+ ...this.options
1351
+ };
1352
+ mergedOptions.HTMLAttributes = react.mergeAttributes({
1353
+ "data-type": this.name
1354
+ }, this.options.HTMLAttributes, HTMLAttributes);
1355
+ const html = this.options.renderHTML({
1356
+ options: mergedOptions,
1357
+ node
1358
+ });
1359
+ if (typeof html === "string") {
1360
+ return ["span", react.mergeAttributes({
1361
+ "data-type": this.name
1362
+ }, this.options.HTMLAttributes, HTMLAttributes), html];
1363
+ }
1364
+ return html;
1365
+ },
1366
+ renderText({
1367
+ node
1368
+ }) {
1369
+ return this.options.renderText({
1370
+ options: this.options,
1371
+ node
1372
+ });
1373
+ },
1374
+ addKeyboardShortcuts() {
1375
+ return {
1376
+ Backspace: () => this.editor.commands.command(({
1377
+ tr,
1378
+ state: state2
1379
+ }) => {
1380
+ let isCommand = false;
1381
+ const {
1382
+ selection
1383
+ } = state2;
1384
+ const {
1385
+ empty,
1386
+ anchor
1387
+ } = selection;
1388
+ if (!empty) {
1389
+ return false;
1390
+ }
1391
+ state2.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
1392
+ if (node.type.name === this.name) {
1393
+ isCommand = true;
1394
+ tr.insertText(this.options.deleteTriggerWithBackspace ? "" : this.options.suggestion.char || "", pos, pos + node.nodeSize);
1395
+ return false;
1396
+ }
1397
+ return true;
1398
+ });
1399
+ return isCommand;
1400
+ })
1401
+ };
1402
+ },
1403
+ addProseMirrorPlugins() {
1404
+ return [Suggestion({
1405
+ editor: this.editor,
1406
+ ...this.options.suggestion
1407
+ })];
1408
+ }
1409
+ });
1410
+ const suggestion = (ref, {
1411
+ upload,
1412
+ aiController
1413
+ }) => ({
1414
+ items: ({
1415
+ query
1416
+ }) => {
1417
+ const availableSuggestionItems = [...suggestionItems];
1418
+ if (aiController) {
1419
+ availableSuggestionItems.push(autocompleteSuggestionItem);
1420
+ }
1421
+ return availableSuggestionItems.filter((item) => {
1422
+ const inTitle = item.title.toLowerCase().startsWith(query.toLowerCase());
1423
+ if (inTitle) return inTitle;
1424
+ const inSearchTerms = item.searchTerms?.some((term) => term.toLowerCase().startsWith(query.toLowerCase()));
1425
+ return inSearchTerms;
1426
+ });
1427
+ },
1428
+ render: () => {
1429
+ let component;
1430
+ let popup;
1431
+ return {
1432
+ onStart: (props) => {
1433
+ component = new react.ReactRenderer(CommandList, {
1434
+ props: {
1435
+ ...props,
1436
+ upload,
1437
+ aiController
1438
+ },
1439
+ editor: props.editor
1440
+ });
1441
+ if (!props.clientRect) {
1442
+ return;
1443
+ }
1444
+ popup = tippy("body", {
1445
+ getReferenceClientRect: props.clientRect,
1446
+ appendTo: ref?.current,
1447
+ content: component.element,
1448
+ showOnCreate: true,
1449
+ interactive: true,
1450
+ trigger: "manual",
1451
+ placement: "bottom-start"
1452
+ });
1453
+ },
1454
+ onUpdate(props) {
1455
+ component.updateProps(props);
1456
+ if (!props.clientRect) {
1457
+ return;
1458
+ }
1459
+ popup[0].setProps({
1460
+ getReferenceClientRect: props.clientRect
1461
+ });
1462
+ },
1463
+ onKeyDown(props) {
1464
+ if (props.event.key === "Escape") {
1465
+ popup[0].hide();
1466
+ props.event.preventDefault();
1467
+ return true;
1468
+ }
1469
+ return component.ref?.onKeyDown(props);
1470
+ },
1471
+ onExit() {
1472
+ if (popup && popup[0]) popup[0].destroy();
1473
+ component?.destroy();
1474
+ }
1475
+ };
1476
+ }
1477
+ });
1478
+ const CommandList = React.forwardRef((props, ref) => {
1479
+ const $ = reactCompilerRuntime.c(33);
1480
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
1481
+ const {
1482
+ editor
1483
+ } = react.useCurrentEditor();
1484
+ let t0;
1485
+ if ($[0] !== editor || $[1] !== props.aiController || $[2] !== props.range || $[3] !== props.upload) {
1486
+ t0 = (item) => {
1487
+ if (!editor) {
1488
+ return;
1489
+ }
1490
+ item?.command?.({
1491
+ editor,
1492
+ range: props.range,
1493
+ upload: props.upload,
1494
+ aiController: props.aiController
1495
+ });
1496
+ };
1497
+ $[0] = editor;
1498
+ $[1] = props.aiController;
1499
+ $[2] = props.range;
1500
+ $[3] = props.upload;
1501
+ $[4] = t0;
1502
+ } else {
1503
+ t0 = $[4];
1504
+ }
1505
+ const selectItem = t0;
1506
+ let t1;
1507
+ if ($[5] !== props.items.length || $[6] !== selectedIndex) {
1508
+ t1 = () => {
1509
+ setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length);
1510
+ };
1511
+ $[5] = props.items.length;
1512
+ $[6] = selectedIndex;
1513
+ $[7] = t1;
1514
+ } else {
1515
+ t1 = $[7];
1516
+ }
1517
+ const upHandler = t1;
1518
+ let t2;
1519
+ if ($[8] !== props.items.length || $[9] !== selectedIndex) {
1520
+ t2 = () => {
1521
+ setSelectedIndex((selectedIndex + 1) % props.items.length);
1522
+ };
1523
+ $[8] = props.items.length;
1524
+ $[9] = selectedIndex;
1525
+ $[10] = t2;
1526
+ } else {
1527
+ t2 = $[10];
1528
+ }
1529
+ const downHandler = t2;
1530
+ let t3;
1531
+ if ($[11] !== props.items || $[12] !== selectItem || $[13] !== selectedIndex) {
1532
+ t3 = () => {
1533
+ const item_0 = props.items[selectedIndex];
1534
+ selectItem(item_0);
1535
+ };
1536
+ $[11] = props.items;
1537
+ $[12] = selectItem;
1538
+ $[13] = selectedIndex;
1539
+ $[14] = t3;
1540
+ } else {
1541
+ t3 = $[14];
1542
+ }
1543
+ const enterHandler = t3;
1544
+ let t4;
1545
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
1546
+ t4 = () => setSelectedIndex(0);
1547
+ $[15] = t4;
1548
+ } else {
1549
+ t4 = $[15];
1550
+ }
1551
+ let t5;
1552
+ if ($[16] !== props.items) {
1553
+ t5 = [props.items];
1554
+ $[16] = props.items;
1555
+ $[17] = t5;
1556
+ } else {
1557
+ t5 = $[17];
1558
+ }
1559
+ React.useEffect(t4, t5);
1560
+ let t6;
1561
+ if ($[18] !== downHandler || $[19] !== enterHandler || $[20] !== upHandler) {
1562
+ t6 = () => ({
1563
+ onKeyDown: (t72) => {
1564
+ const {
1565
+ event
1566
+ } = t72;
1567
+ if (event.key === "ArrowUp") {
1568
+ upHandler();
1569
+ return true;
1570
+ }
1571
+ if (event.key === "ArrowDown") {
1572
+ downHandler();
1573
+ return true;
1574
+ }
1575
+ if (event.key === "Enter") {
1576
+ enterHandler();
1577
+ return true;
1578
+ }
1579
+ return false;
1580
+ }
1581
+ });
1582
+ $[18] = downHandler;
1583
+ $[19] = enterHandler;
1584
+ $[20] = upHandler;
1585
+ $[21] = t6;
1586
+ } else {
1587
+ t6 = $[21];
1588
+ }
1589
+ React.useImperativeHandle(ref, t6);
1590
+ let t7;
1591
+ if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
1592
+ t7 = [];
1593
+ $[22] = t7;
1594
+ } else {
1595
+ t7 = $[22];
1596
+ }
1597
+ const itemRefs = React.useRef(t7);
1598
+ let t8;
1599
+ let t9;
1600
+ if ($[23] !== selectedIndex) {
1601
+ t8 = () => {
1602
+ if (itemRefs.current[selectedIndex]) {
1603
+ itemRefs.current[selectedIndex].scrollIntoView({
1604
+ block: "nearest"
1605
+ });
1606
+ }
1607
+ };
1608
+ t9 = [selectedIndex];
1609
+ $[23] = selectedIndex;
1610
+ $[24] = t8;
1611
+ $[25] = t9;
1612
+ } else {
1613
+ t8 = $[24];
1614
+ t9 = $[25];
1615
+ }
1616
+ React.useEffect(t8, t9);
1617
+ let t10;
1618
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
1619
+ 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);
1620
+ $[26] = t10;
1621
+ } else {
1622
+ t10 = $[26];
1623
+ }
1624
+ let t11;
1625
+ if ($[27] !== props.items || $[28] !== selectItem || $[29] !== selectedIndex) {
1626
+ t11 = props.items.length ? props.items.map((item_1, index) => /* @__PURE__ */ jsxRuntime.jsxs("button", { value: item_1.title, ref: (el) => {
1627
+ if (!el) {
1628
+ return;
1629
+ }
1630
+ itemRefs.current[index] = el;
1631
+ }, 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: [
1632
+ /* @__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 }),
1633
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1634
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: item_1.title }),
1635
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-surface-700 dark:text-surface-accent-300", children: item_1.description })
1636
+ ] })
1637
+ ] }, item_1.title)) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "item", children: "No result" });
1638
+ $[27] = props.items;
1639
+ $[28] = selectItem;
1640
+ $[29] = selectedIndex;
1641
+ $[30] = t11;
1642
+ } else {
1643
+ t11 = $[30];
1644
+ }
1645
+ let t12;
1646
+ if ($[31] !== t11) {
1647
+ t12 = /* @__PURE__ */ jsxRuntime.jsx("div", { className: t10, children: t11 });
1648
+ $[31] = t11;
1649
+ $[32] = t12;
1650
+ } else {
1651
+ t12 = $[32];
1652
+ }
1653
+ return t12;
1654
+ });
1655
+ CommandList.displayName = "CommandList";
1656
+ const autocompleteSuggestionItem = {
1657
+ title: "Autocomplete",
1658
+ description: "Add text based on the context.",
1659
+ searchTerms: ["ai"],
1660
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.AutoFixHighIcon, { size: 18 }),
1661
+ command: async ({
1662
+ editor,
1663
+ range,
1664
+ aiController
1665
+ }) => {
1666
+ if (!aiController) throw Error("No AiController");
1667
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
1668
+ const {
1669
+ state: state2
1670
+ } = editor;
1671
+ const {
1672
+ from,
1673
+ to
1674
+ } = state2.selection;
1675
+ const textBeforeCursor = state2.doc.textBetween(0, from, "\n");
1676
+ const textAfterCursor = state2.doc.textBetween(to, state2.doc.content.size, "\n");
1677
+ let buffer = "";
1678
+ const result = await aiController.autocomplete(textBeforeCursor, textAfterCursor, (delta) => {
1679
+ buffer += delta;
1680
+ if (delta.length !== 0) {
1681
+ editor.chain().focus().toggleLoadingDecoration(buffer).run();
1682
+ }
1683
+ });
1684
+ editor.chain().focus().insertContent(result, {
1685
+ applyInputRules: false,
1686
+ applyPasteRules: false,
1687
+ parseOptions: {
1688
+ preserveWhitespace: false
1689
+ }
1690
+ }).run();
1691
+ }
1692
+ };
1693
+ const suggestionItems = [{
1694
+ title: "Text",
1695
+ description: "Just start typing with plain text.",
1696
+ searchTerms: ["p", "paragraph"],
1697
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.TextFieldsIcon, { size: 18 }),
1698
+ command: ({
1699
+ editor,
1700
+ range
1701
+ }) => {
1702
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
1703
+ }
1704
+ }, {
1705
+ title: "To-do List",
1706
+ description: "Track tasks with a to-do list.",
1707
+ searchTerms: ["todo", "task", "list", "check", "checkbox"],
1708
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.CheckBoxIcon, { size: 18 }),
1709
+ command: ({
1710
+ editor,
1711
+ range
1712
+ }) => {
1713
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
1714
+ }
1715
+ }, {
1716
+ title: "Heading 1",
1717
+ description: "Big section heading.",
1718
+ searchTerms: ["title", "big", "large"],
1719
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.LooksOneIcon, { size: 18 }),
1720
+ command: ({
1721
+ editor,
1722
+ range
1723
+ }) => {
1724
+ editor.chain().focus().deleteRange(range).setNode("heading", {
1725
+ level: 1
1726
+ }).run();
1727
+ }
1728
+ }, {
1729
+ title: "Heading 2",
1730
+ description: "Medium section heading.",
1731
+ searchTerms: ["subtitle", "medium"],
1732
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.LooksTwoIcon, { size: 18 }),
1733
+ command: ({
1734
+ editor,
1735
+ range
1736
+ }) => {
1737
+ editor.chain().focus().deleteRange(range).setNode("heading", {
1738
+ level: 2
1739
+ }).run();
1740
+ }
1741
+ }, {
1742
+ title: "Heading 3",
1743
+ description: "Small section heading.",
1744
+ searchTerms: ["subtitle", "small"],
1745
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.Looks3Icon, { size: 18 }),
1746
+ command: ({
1747
+ editor,
1748
+ range
1749
+ }) => {
1750
+ editor.chain().focus().deleteRange(range).setNode("heading", {
1751
+ level: 3
1752
+ }).run();
1753
+ }
1754
+ }, {
1755
+ title: "Bullet List",
1756
+ description: "Create a simple bullet list.",
1757
+ searchTerms: ["unordered", "point"],
1758
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatListBulletedIcon, { size: 18 }),
1759
+ command: ({
1760
+ editor,
1761
+ range
1762
+ }) => {
1763
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
1764
+ }
1765
+ }, {
1766
+ title: "Numbered List",
1767
+ description: "Create a list with numbering.",
1768
+ searchTerms: ["ordered"],
1769
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatListNumberedIcon, { size: 18 }),
1770
+ command: ({
1771
+ editor,
1772
+ range
1773
+ }) => {
1774
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
1775
+ }
1776
+ }, {
1777
+ title: "Quote",
1778
+ description: "Capture a quote.",
1779
+ searchTerms: ["blockquote"],
1780
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.FormatQuoteIcon, { size: 18 }),
1781
+ command: ({
1782
+ editor,
1783
+ range
1784
+ }) => editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run()
1785
+ }, {
1786
+ title: "Code",
1787
+ description: "Capture a code snippet.",
1788
+ searchTerms: ["codeblock"],
1789
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.CodeIcon, { size: 18 }),
1790
+ command: ({
1791
+ editor,
1792
+ range
1793
+ }) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run()
1794
+ }, {
1795
+ title: "Image",
1796
+ description: "Upload an image from your computer.",
1797
+ searchTerms: ["photo", "picture", "media", "upload", "file"],
1798
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ui.ImageIcon, { size: 18 }),
1799
+ command: ({
1800
+ editor,
1801
+ range,
1802
+ upload
1803
+ }) => {
1804
+ editor.chain().focus().deleteRange(range).run();
1805
+ const input = document.createElement("input");
1806
+ input.type = "file";
1807
+ input.accept = "image/*";
1808
+ input.onchange = async () => {
1809
+ if (input.files?.length) {
1810
+ const file = input.files[0];
1811
+ if (!file) return;
1812
+ const pos = editor.view.state.selection.from;
1813
+ const fileList = input.files;
1814
+ const files = Array.from(fileList);
1815
+ const images = files.filter((file2) => /image/i.test(file2.type));
1816
+ if (images.length === 0) {
1817
+ console.log("No images found in uploaded files");
1818
+ return false;
1819
+ }
1820
+ const view2 = editor.view;
1821
+ images.forEach((image) => {
1822
+ const reader = new FileReader();
1823
+ reader.onload = async (readerEvent) => {
1824
+ await onFileRead(view2, readerEvent, pos, upload, image);
1825
+ };
1826
+ reader.readAsDataURL(image);
1827
+ });
1828
+ }
1829
+ return true;
1830
+ };
1831
+ input.click();
1832
+ }
1833
+ }];
1834
+ const CustomDocument = Document.extend({
1835
+ // content: 'heading block*',
1836
+ });
1837
+ const proseClasses = {
1838
+ "sm": "prose-sm",
1839
+ "base": "prose-base",
1840
+ "lg": "prose-lg"
1841
+ };
1842
+ const FireCMSEditor = ({
1843
+ content,
1844
+ onJsonContentChange,
1845
+ onHtmlContentChange,
1846
+ onMarkdownContentChange,
1847
+ version,
1848
+ textSize = "base",
1849
+ highlight,
1850
+ handleImageUpload,
1851
+ aiController,
1852
+ disabled
1853
+ }) => {
1854
+ const ref = React.useRef(null);
1855
+ const editorRef = React.useRef(null);
1856
+ const imagePlugin = createDropImagePlugin(handleImageUpload);
1857
+ const imageExtension = React.useMemo(() => createImageExtension(imagePlugin), []);
1858
+ const [openNode, setOpenNode] = React.useState(false);
1859
+ const [openLink, setOpenLink] = React.useState(false);
1860
+ ui.useInjectStyles("Editor", cssStyles);
1861
+ const deferredHighlight = React.useDeferredValue(highlight);
1862
+ React.useEffect(() => {
1863
+ if (version === void 0) return;
1864
+ if (version > -1 && editorRef.current) {
1865
+ editorRef.current?.commands.setContent(content ?? "");
1866
+ }
1867
+ }, [version]);
1868
+ React.useEffect(() => {
1869
+ editorRef?.current?.setEditable(!disabled);
1870
+ }, [disabled]);
1871
+ React.useEffect(() => {
1872
+ if (version === void 0) return;
1873
+ if (editorRef.current && version > 0) {
1874
+ const chain = editorRef.current.chain();
1875
+ if (deferredHighlight) {
1876
+ chain.focus().toggleAutocompleteHighlight(deferredHighlight).run();
1877
+ } else {
1878
+ chain.focus().removeAutocompleteHighlight().run();
1879
+ }
1880
+ }
1881
+ }, [deferredHighlight?.from, deferredHighlight?.to]);
1882
+ const onEditorUpdate = (editor) => {
1883
+ editorRef.current = editor;
1884
+ if (onMarkdownContentChange) {
1885
+ const markdown = editorRef.current.storage.markdown.getMarkdown();
1886
+ onMarkdownContentChange?.(addLineBreakAfterImages(markdown));
1887
+ }
1888
+ if (onJsonContentChange) {
1889
+ const jsonContent = removeClassesFromJson(editor.getJSON());
1890
+ onJsonContentChange(jsonContent);
1891
+ }
1892
+ if (onHtmlContentChange) {
1893
+ onHtmlContentChange?.(editor.getHTML());
1894
+ }
1895
+ };
1896
+ const proseClass = proseClasses[textSize];
1897
+ const extensions = React.useMemo(() => [
1898
+ starterKit,
1899
+ CustomDocument,
1900
+ HighlightDecorationExtension(highlight),
1901
+ TextLoadingDecorationExtension,
1902
+ Underline,
1903
+ Bold,
1904
+ TextStyle,
1905
+ Italic,
1906
+ Strike,
1907
+ Color,
1908
+ Highlight.configure({
1909
+ multicolor: true
1910
+ }),
1911
+ // CustomBlock.configure({
1912
+ // component: CustomComponent,
1913
+ // delimiter: "```custom"
1914
+ // }),
1915
+ Heading,
1916
+ CustomKeymap,
1917
+ DragAndDrop,
1918
+ placeholder,
1919
+ tiptapLink,
1920
+ imageExtension,
1921
+ taskList,
1922
+ taskItem,
1923
+ tiptapMarkdown.Markdown.configure({
1924
+ html: true
1925
+ }),
1926
+ horizontalRule,
1927
+ bulletList,
1928
+ orderedList,
1929
+ listItem,
1930
+ blockquote,
1931
+ codeBlock,
1932
+ code,
1933
+ SlashCommand.configure({
1934
+ HTMLAttributes: {
1935
+ class: "mention"
1936
+ },
1937
+ suggestion: suggestion(ref, {
1938
+ upload: handleImageUpload,
1939
+ aiController
1940
+ })
1941
+ })
1942
+ ], []);
1943
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: "relative min-h-[300px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(react.EditorProvider, { content: content ?? "", extensions, editorProps: {
1944
+ editable: () => !disabled,
1945
+ attributes: {
1946
+ class: ui.cls(proseClass, "prose-headings:font-title font-default focus:outline-none max-w-full p-12")
1947
+ }
1948
+ }, onCreate: ({
1949
+ editor: editor_0
1950
+ }) => {
1951
+ editorRef.current = editor_0;
1952
+ editor_0.setEditable(!disabled);
1953
+ }, onUpdate: ({
1954
+ editor: editor_1
1955
+ }) => {
1956
+ onEditorUpdate(editor_1);
1957
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs(EditorBubble, { tippyOptions: {
1958
+ placement: "top"
1959
+ }, 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: [
1960
+ /* @__PURE__ */ jsxRuntime.jsx(NodeSelector, { portalContainer: ref.current, open: openNode, onOpenChange: setOpenNode }),
1961
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Separator, { orientation: "vertical" }),
1962
+ /* @__PURE__ */ jsxRuntime.jsx(LinkSelector, { open: openLink, onOpenChange: setOpenLink }),
1963
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Separator, { orientation: "vertical" }),
1964
+ /* @__PURE__ */ jsxRuntime.jsx(TextButtons, {})
1965
+ ] }) }) });
1966
+ };
1967
+ function addLineBreakAfterImages(markdown) {
1968
+ const imageRegex = /!\[.*?\]\(.*?\)/g;
1969
+ return markdown.replace(imageRegex, (match) => `${match}
1970
+ `);
1971
+ }
1972
+ const cssStyles = `
1973
+ .ProseMirror {
1974
+ box-shadow: none !important;
1975
+ }
4
1976
  .ProseMirror .is-editor-empty:first-child::before {
5
1977
  content: attr(data-placeholder);
6
1978
  float: left;
@@ -23,6 +1995,7 @@
23
1995
  }
24
1996
 
25
1997
  .is-empty {
1998
+ cursor: text;
26
1999
  color: rgb(100 116 139); //500
27
2000
  }
28
2001
 
@@ -40,6 +2013,7 @@
40
2013
  &.ProseMirror-selectednode {
41
2014
  outline: 3px solid #5abbf7;
42
2015
  filter: brightness(90%);
2016
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000) !important;
43
2017
  }
44
2018
  }
45
2019
 
@@ -67,7 +2041,7 @@ ul[data-type="taskList"] li > label {
67
2041
  }
68
2042
 
69
2043
  &:active {
70
- background-color: rgb(71 85 105);;
2044
+ background-color: rgb(71 85 105);
71
2045
  }
72
2046
  }
73
2047
  }
@@ -134,7 +2108,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
134
2108
  }
135
2109
 
136
2110
  .ProseMirror:not(.dragging) .ProseMirror-selectednode {
137
- outline: none !important;
2111
+ // outline: none !important;
138
2112
  background-color: rgb(219 234 254); // blue 100
139
2113
  transition: background-color 0.2s;
140
2114
  box-shadow: none;
@@ -144,8 +2118,12 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
144
2118
  background-color: rgb(51 65 85); // 700
145
2119
  }
146
2120
 
2121
+ .prose-base table p {
2122
+ margin: 0;
2123
+ }
2124
+
147
2125
  .drag-handle {
148
- position: fixed;
2126
+ position: absolute;
149
2127
  opacity: 1;
150
2128
  transition: opacity ease-in 0.2s;
151
2129
  border-radius: 0.25rem;
@@ -156,7 +2134,7 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
156
2134
  background-position: center;
157
2135
  width: 1.2rem;
158
2136
  height: 1.5rem;
159
- z-index: 50;
2137
+ z-index: 100;
160
2138
  cursor: grab;
161
2139
 
162
2140
  &:hover {
@@ -189,5 +2167,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
189
2167
  background-color: rgb(51 65 85); // 700
190
2168
  }
191
2169
  }
192
- `;u.FireCMSEditor=Pe,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
2170
+ `;
2171
+ exports2.FireCMSEditor = FireCMSEditor;
2172
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
2173
+ });
193
2174
  //# sourceMappingURL=index.umd.js.map