neuphlo-editor 2.0.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/headless/index.ts","../src/headless/components/editor.tsx","../src/headless/utils/store.ts","../src/headless/components/editor-bubble.tsx","../src/headless/components/editor-bubble-item.tsx","../src/headless/components/editor-command.tsx","../src/headless/utils/atoms.ts","../src/headless/components/editor-command-item.tsx","../src/headless/extensions/index.ts","../src/headless/extensions/CodeBlock/CodeBlock.ts","../src/headless/extensions/Link/Link.ts","../src/headless/extensions/ImageBlock/ImageBlock.ts","../src/headless/extensions/Mention/mention.tsx","../src/headless/extensions/Mention/mention-command.tsx","../src/headless/extensions/Mention/mention-node-view.tsx","../src/headless/extensions/DragHandle/DragHandle.ts","../src/headless/extensions/Table/index.ts","../src/headless/extensions/MarkdownPaste.ts","../src/headless/extensions/slash-command.tsx"],"sourcesContent":["export { useCurrentEditor as useEditor } from \"@tiptap/react\"\n\nexport {\n EditorRoot,\n EditorContent,\n type EditorContentProps,\n} from \"./components/editor\"\n\nexport { EditorBubble } from \"./components/editor-bubble\"\nexport { EditorBubbleItem } from \"./components/editor-bubble-item\"\nexport {\n EditorCommand,\n EditorCommandList,\n EditorCommandOut,\n} from \"./components/editor-command\"\nexport {\n EditorCommandItem,\n EditorCommandEmpty,\n} from \"./components/editor-command-item\"\n\nexport { Placeholder, StarterKit } from \"./extensions\"\nexport {\n Command as SlashCommand,\n renderItems as renderSlashCommandItems,\n createSuggestionItems,\n handleCommandNavigation,\n} from \"./extensions/slash-command\"\nexport {\n createMentionExtension,\n renderMentionSuggestion,\n MentionCommand,\n type MentionItem,\n type MentionOptions,\n} from \"./extensions/Mention\"\n// Path without extension to satisfy TS/tsup\n// (the file is at ./extensions/slash-command.tsx)\n// eslint-disable-next-line\n","import { EditorProvider } from \"@tiptap/react\"\nimport type { EditorProviderProps } from \"@tiptap/react\"\nimport { forwardRef } from \"react\"\nimport type { FC, ReactNode } from \"react\"\nimport { Provider } from \"jotai\"\nimport { novelStore } from \"../utils/store\"\n\nexport interface EditorRootProps {\n readonly children: ReactNode\n}\n\nexport const EditorRoot: FC<EditorRootProps> = ({ children }) => {\n return (\n <Provider store={novelStore as any}>\n {children as any}\n </Provider>\n )\n}\n\nexport type EditorContentProps = EditorProviderProps & {\n readonly children?: ReactNode\n readonly className?: string\n readonly initialContent?: any\n}\n\nexport const EditorContent = forwardRef<HTMLDivElement, EditorContentProps>(\n ({ className, children, initialContent, content, ...rest }, ref) => {\n const effectiveContent = content ?? initialContent\n return (\n <div ref={ref} className={className}>\n <EditorProvider {...rest} content={effectiveContent}>\n {children}\n </EditorProvider>\n </div>\n )\n }\n)\n\nEditorContent.displayName = \"EditorContent\"\n","import { createStore } from \"jotai\";\n\n// biome-ignore lint/suspicious/noExplicitAny: store is opaque to consumers\nexport const novelStore: any = createStore();\nexport * from \"jotai\";\n\n","import { useCurrentEditor } from \"@tiptap/react\";\nimport { BubbleMenu as BubbleMenuReact } from \"@tiptap/react/menus\";\nimport type { BubbleMenuProps } from \"@tiptap/react/menus\";\nimport type { ReactNode } from \"react\";\n\ntype ForwardedBubbleProps = Omit<BubbleMenuProps, \"editor\" | \"children\" | \"className\">;\n\nexport interface EditorBubbleProps extends ForwardedBubbleProps {\n readonly className?: string;\n readonly children: ReactNode;\n}\n\nexport function EditorBubble({ className, children, ...rest }: EditorBubbleProps) {\n const { editor } = useCurrentEditor();\n if (!editor) return null;\n\n return (\n <BubbleMenuReact editor={editor} {...rest}>\n <div className={className}>{children}</div>\n </BubbleMenuReact>\n );\n}\n","import { forwardRef, isValidElement, cloneElement } from \"react\"\nimport type { ComponentPropsWithoutRef, ReactElement, ReactNode } from \"react\"\nimport { useCurrentEditor } from \"@tiptap/react\"\nimport type { Editor as TiptapEditor } from \"@tiptap/react\"\n\ninterface EditorBubbleItemProps {\n readonly children: ReactNode\n readonly asChild?: boolean\n readonly onSelect?: (editor: TiptapEditor) => void\n}\n\nexport const EditorBubbleItem = forwardRef<\n HTMLDivElement,\n EditorBubbleItemProps & Omit<ComponentPropsWithoutRef<\"div\">, \"onSelect\">\n>(({ children, asChild, onSelect, ...rest }, ref) => {\n const { editor } = useCurrentEditor()\n\n if (!editor) return null\n\n const handleClick = (e: React.MouseEvent) => {\n e.preventDefault()\n onSelect?.(editor)\n }\n\n if (asChild && isValidElement(children)) {\n const child = children as ReactElement<any>\n const childOnClick = (child.props as any)?.onClick as\n | ((e: any) => void)\n | undefined\n const mergedOnClick = (e: any) => {\n childOnClick?.(e)\n if (!e?.defaultPrevented) onSelect?.(editor)\n }\n\n return cloneElement(child, {\n ...rest,\n ref: (child as any).ref ?? ref,\n onClick: mergedOnClick,\n })\n }\n\n return (\n <div ref={ref} {...rest} onClick={handleClick}>\n {children}\n </div>\n )\n})\n\nEditorBubbleItem.displayName = \"EditorBubbleItem\"\n\nexport default EditorBubbleItem\n","import { useAtomValue } from \"jotai\"\nimport { forwardRef, useRef, useEffect, useLayoutEffect, useState, useCallback } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { queryAtom, slashMenuOpenAtom, slashMenuRectAtom } from \"../utils/atoms\"\nimport { novelStore } from \"../utils/store\"\n\n// EditorCommandOut is no longer needed — kept as a no-op for backward compatibility\nexport const EditorCommandOut = () => null\n\nexport const EditorCommand = forwardRef<HTMLDivElement, any>(\n ({ children, className, ...rest }, ref) => {\n const isOpen = useAtomValue(slashMenuOpenAtom, { store: novelStore })\n const rect = useAtomValue(slashMenuRectAtom, { store: novelStore })\n const containerRef = useRef<HTMLDivElement | null>(null)\n const [activeIndex, setActiveIndex] = useState(0)\n const contentRef = useRef<HTMLDivElement | null>(null)\n\n // Reset active index when query changes\n const query = useAtomValue(queryAtom, { store: novelStore })\n useEffect(() => {\n setActiveIndex(0)\n }, [query])\n\n // Create portal container once\n if (typeof document !== \"undefined\" && !containerRef.current) {\n const el = document.createElement(\"div\")\n el.style.position = \"fixed\"\n el.style.zIndex = \"9999\"\n el.style.minWidth = \"240px\"\n el.style.display = \"none\"\n containerRef.current = el\n }\n\n // Manage DOM attachment\n useEffect(() => {\n const el = containerRef.current\n if (!el) return\n document.body.appendChild(el)\n return () => {\n el.remove()\n }\n }, [])\n\n // Show/hide and position\n useLayoutEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n if (!isOpen || !rect) {\n container.style.display = \"none\"\n return\n }\n\n container.style.display = \"\"\n\n const menuHeight = container.offsetHeight || 360\n const viewportHeight = window.innerHeight\n const spaceBelow = viewportHeight - rect.bottom\n const spaceAbove = rect.top\n\n let top: number\n if (spaceBelow < menuHeight + 16 && spaceAbove > spaceBelow) {\n top = Math.round(rect.top - menuHeight - 8)\n if (top < 8) top = 8\n } else {\n top = Math.round(rect.bottom + 8)\n }\n\n let left = Math.round(rect.left)\n const menuWidth = container.offsetWidth || 280\n if (left + menuWidth > window.innerWidth - 8) {\n left = window.innerWidth - menuWidth - 8\n }\n if (left < 8) left = 8\n\n container.style.top = `${top}px`\n container.style.left = `${left}px`\n }, [isOpen, rect])\n\n // Keyboard navigation\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (!isOpen || !contentRef.current) return\n\n const items = contentRef.current.querySelectorAll(\"[role='option']\")\n if (items.length === 0) return\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault()\n setActiveIndex((prev) => {\n const next = Math.min(prev + 1, items.length - 1)\n items[next]?.scrollIntoView({ block: \"nearest\" })\n return next\n })\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault()\n setActiveIndex((prev) => {\n const next = Math.max(prev - 1, 0)\n items[next]?.scrollIntoView({ block: \"nearest\" })\n return next\n })\n } else if (e.key === \"Enter\") {\n e.preventDefault()\n const activeItem = items[activeIndex] as HTMLElement | undefined\n activeItem?.click()\n }\n },\n [isOpen, activeIndex]\n )\n\n useEffect(() => {\n if (!isOpen) return\n document.addEventListener(\"keydown\", handleKeyDown)\n return () => document.removeEventListener(\"keydown\", handleKeyDown)\n }, [isOpen, handleKeyDown])\n\n // Apply active styling\n useEffect(() => {\n if (!contentRef.current) return\n const items = contentRef.current.querySelectorAll(\"[role='option']\")\n items.forEach((item, i) => {\n if (i === activeIndex) {\n item.setAttribute(\"aria-selected\", \"true\")\n } else {\n item.removeAttribute(\"aria-selected\")\n }\n })\n })\n\n if (!isOpen || !containerRef.current) return null\n\n return createPortal(\n <div\n ref={(el) => {\n contentRef.current = el\n if (typeof ref === \"function\") ref(el)\n else if (ref) ref.current = el\n }}\n id=\"slash-command\"\n className={className}\n {...rest}\n >\n {children}\n </div>,\n containerRef.current\n )\n }\n)\n\n// Simple list wrapper\nexport const EditorCommandList = forwardRef<HTMLDivElement, any>(\n ({ children, ...rest }, ref) => {\n return (\n <div ref={ref} role=\"listbox\" {...rest}>\n {children}\n </div>\n )\n }\n)\n\nEditorCommand.displayName = \"EditorCommand\"\nEditorCommandList.displayName = \"EditorCommandList\"\n","import { atom } from \"jotai\"\nimport type { Range } from \"@tiptap/core\"\n\nexport const queryAtom = atom(\"\")\nexport const rangeAtom = atom<Range | null>(null)\nexport const slashMenuOpenAtom = atom(false)\nexport const slashMenuRectAtom = atom<DOMRect | null>(null)\n","import { forwardRef } from \"react\"\nimport { useCurrentEditor } from \"@tiptap/react\"\nimport { useAtomValue } from \"jotai\"\nimport { rangeAtom, queryAtom } from \"../utils/atoms\"\nimport { novelStore } from \"../utils/store\"\nimport type { Editor, Range } from \"@tiptap/core\"\n\ninterface EditorCommandItemProps {\n readonly onCommand: ({\n editor,\n range,\n }: {\n editor: Editor\n range: Range\n }) => void\n readonly value?: string\n}\n\nexport const EditorCommandItem = forwardRef<\n HTMLDivElement,\n EditorCommandItemProps & any\n>(({ children, onCommand, value, className, ...rest }, ref) => {\n const { editor } = useCurrentEditor()\n const range = useAtomValue(rangeAtom, { store: novelStore })\n const query = useAtomValue(queryAtom, { store: novelStore })\n\n if (!editor || !range) return null\n\n // Filter: if query is set, check if this item matches\n if (query && value) {\n const searchText = value.toLowerCase()\n const q = query.toLowerCase()\n if (!searchText.includes(q)) return null\n }\n\n return (\n <div\n ref={ref}\n role=\"option\"\n className={className}\n onClick={() => onCommand({ editor, range })}\n {...rest}\n >\n {children}\n </div>\n )\n})\n\nEditorCommandItem.displayName = \"EditorCommandItem\"\n\nexport const EditorCommandEmpty = forwardRef<HTMLDivElement, any>(\n ({ children, ...rest }, ref) => {\n return (\n <div ref={ref} {...rest}>\n {children}\n </div>\n )\n }\n)\n\nEditorCommandEmpty.displayName = \"EditorCommandEmpty\"\n\nexport default EditorCommandItem\n","export { StarterKit } from \"@tiptap/starter-kit\";\nexport { Placeholder } from \"@tiptap/extension-placeholder\";\n\n// Custom\nexport { CodeBlock } from \"./CodeBlock\";\nexport { Link } from \"./Link\";\nexport { ImageBlock } from \"./ImageBlock\";\nexport type { ImageBlockOptions } from \"./ImageBlock\";\nexport { AISuggestion, AISuggestionPluginKey } from \"./AISuggestion\";\nexport type { AISuggestionOptions } from \"./AISuggestion\";\nexport { createMentionExtension, renderMentionSuggestion, MentionCommand } from \"./Mention\";\nexport type { MentionItem, MentionOptions } from \"./Mention\";\nexport { DragHandle, setDragHandleCallbacks } from \"./DragHandle\";\nexport type { DragHandleCallbacks } from \"./DragHandle\";\nexport { TableKit, Table, TableCell, TableHeader, TableRow } from \"./Table\";\nexport { MarkdownPaste } from \"./MarkdownPaste\";\n","import { CodeBlockLowlight } from \"@tiptap/extension-code-block-lowlight\"\nimport { all, createLowlight } from \"lowlight\"\n\nconst lowlight = createLowlight(all)\n\nexport const CodeBlock = CodeBlockLowlight.configure({\n lowlight,\n})\n","import { mergeAttributes } from \"@tiptap/core\"\nimport TiptapLink from \"@tiptap/extension-link\"\nimport { Plugin } from \"@tiptap/pm/state\"\nimport { EditorView } from \"@tiptap/pm/view\"\n\nexport const Link = TiptapLink.extend({\n inclusive: false,\n\n parseHTML() {\n return [\n {\n tag: 'a[href]:not([data-type=\"button\"]):not([href *= \"javascript:\" i])',\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }: any) {\n return [\n \"a\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: \"link\",\n }),\n 0,\n ]\n },\n\n addProseMirrorPlugins() {\n const { editor } = this\n\n return [\n ...(((this as any).parent?.() as any[]) || []),\n new Plugin({\n props: {\n handleKeyDown: (view: EditorView, event: KeyboardEvent) => {\n const { selection } = editor.state\n\n if (event.key === \"Escape\" && selection.empty !== true) {\n editor.commands.focus(selection.to, { scrollIntoView: false })\n }\n\n return false\n },\n },\n }),\n ]\n },\n}).configure({\n openOnClick: false,\n autolink: true,\n enableClickSelection: true,\n})\n\nexport default Link","import { mergeAttributes, Range } from \"@tiptap/core\"\nimport { Image as TiptapImage } from \"@tiptap/extension-image\"\nimport { ReactNodeViewRenderer } from \"@tiptap/react\"\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\"\nimport { EditorView } from \"@tiptap/pm/view\"\n\nexport interface ImageBlockOptions {\n uploadImage?: (file: File) => Promise<string>\n browseAssets?: (onSelect: (url: string) => void) => void\n nodeView?: any\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n imageBlock: {\n setImageBlock: (attributes: { src: string }) => ReturnType\n setImageBlockAt: (attributes: {\n src: string\n pos: number | Range\n }) => ReturnType\n setImageBlockAlign: (align: \"left\" | \"center\" | \"right\") => ReturnType\n setImageBlockWidth: (width: number) => ReturnType\n }\n }\n}\n\nexport const ImageBlock = TiptapImage.extend<ImageBlockOptions>({\n name: \"imageBlock\",\n\n group: \"block\",\n\n defining: true,\n\n isolating: true,\n\n addOptions() {\n return {\n ...this.parent?.(),\n uploadImage: undefined,\n inline: false,\n }\n },\n\n addAttributes() {\n return {\n src: {\n default: \"\",\n parseHTML: (element) => element.getAttribute(\"src\"),\n renderHTML: (attributes) => ({\n src: attributes.src,\n }),\n },\n width: {\n default: \"100%\",\n parseHTML: (element) => element.getAttribute(\"data-width\"),\n renderHTML: (attributes) => ({\n \"data-width\": attributes.width,\n }),\n },\n align: {\n default: \"center\",\n parseHTML: (element) => element.getAttribute(\"data-align\"),\n renderHTML: (attributes) => ({\n \"data-align\": attributes.align,\n }),\n },\n alt: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"alt\"),\n renderHTML: (attributes) => ({\n alt: attributes.alt,\n }),\n },\n loading: {\n default: false,\n parseHTML: () => false,\n renderHTML: () => ({}),\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'img[src]:not([src^=\"data:\"])',\n getAttrs: (element) => {\n const el = element as HTMLElement\n return {\n src: el.getAttribute(\"src\"),\n alt: el.getAttribute(\"alt\"),\n width: el.getAttribute(\"data-width\") || \"100%\",\n align: el.getAttribute(\"data-align\") || \"center\",\n }\n },\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"img\", mergeAttributes(HTMLAttributes)]\n },\n\n addCommands() {\n return {\n setImageBlock:\n (attrs) =>\n ({ commands }) => {\n return commands.insertContent({\n type: \"imageBlock\",\n attrs: { src: attrs.src },\n })\n },\n\n setImageBlockAt:\n (attrs) =>\n ({ commands }) => {\n return commands.insertContentAt(attrs.pos, {\n type: \"imageBlock\",\n attrs: { src: attrs.src },\n })\n },\n\n setImageBlockAlign:\n (align) =>\n ({ commands }) =>\n commands.updateAttributes(\"imageBlock\", { align }),\n\n setImageBlockWidth:\n (width) =>\n ({ commands }) =>\n commands.updateAttributes(\"imageBlock\", {\n width: `${Math.max(0, Math.min(100, width))}%`,\n }),\n }\n },\n\n addNodeView() {\n if (this.options.nodeView) {\n return ReactNodeViewRenderer(this.options.nodeView)\n }\n // If no custom node view is provided, we fall back to default behavior\n // but avoid the circular dependency require()\n return null\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: new PluginKey(\"imageBlockDrop\"),\n props: {\n handleDOMEvents: {\n drop: (view: EditorView, event: DragEvent) => {\n const hasFiles =\n event.dataTransfer &&\n event.dataTransfer.files &&\n event.dataTransfer.files.length\n\n if (!hasFiles) {\n return false\n }\n\n const images = Array.from(event.dataTransfer.files).filter(\n (file) => /image/i.test(file.type)\n )\n\n if (images.length === 0) {\n return false\n }\n\n event.preventDefault()\n\n const { schema } = view.state\n const coordinates = view.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n })\n\n if (!coordinates) return false\n\n images.forEach(async (image) => {\n if (this.options.uploadImage) {\n try {\n // Insert placeholder first\n const placeholderNode = schema.nodes.imageBlock.create({\n src: \"\",\n loading: true,\n })\n const placeholderTr = view.state.tr.insert(\n coordinates.pos,\n placeholderNode\n )\n view.dispatch(placeholderTr)\n\n // Upload and replace\n const url = await this.options.uploadImage(image)\n const node = schema.nodes.imageBlock.create({ src: url })\n\n // Find and replace the placeholder\n const currentState = view.state\n let foundPos = -1\n currentState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"imageBlock\" &&\n node.attrs.loading\n ) {\n foundPos = pos\n return false\n }\n })\n\n if (foundPos !== -1) {\n const transaction = view.state.tr.replaceWith(\n foundPos,\n foundPos + 1,\n node\n )\n view.dispatch(transaction)\n }\n } catch (error) {\n console.error(\"Failed to upload image:\", error)\n // Remove placeholder on error\n const currentState = view.state\n let foundPos = -1\n currentState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"imageBlock\" &&\n node.attrs.loading\n ) {\n foundPos = pos\n return false\n }\n })\n\n if (foundPos !== -1) {\n const transaction = view.state.tr.delete(\n foundPos,\n foundPos + 1\n )\n view.dispatch(transaction)\n }\n }\n }\n })\n\n return true\n },\n paste: (view: EditorView, event: ClipboardEvent) => {\n const hasFiles =\n event.clipboardData &&\n event.clipboardData.files &&\n event.clipboardData.files.length\n\n if (!hasFiles) {\n return false\n }\n\n const images = Array.from(event.clipboardData.files).filter(\n (file) => /image/i.test(file.type)\n )\n\n if (images.length === 0) {\n return false\n }\n\n event.preventDefault()\n\n images.forEach(async (image) => {\n if (this.options.uploadImage) {\n try {\n // Insert placeholder first\n const placeholderNode =\n view.state.schema.nodes.imageBlock.create({\n src: \"\",\n loading: true,\n })\n view.dispatch(\n view.state.tr.replaceSelectionWith(placeholderNode)\n )\n\n // Upload and replace\n const url = await this.options.uploadImage(image)\n const node = view.state.schema.nodes.imageBlock.create({\n src: url,\n })\n\n // Find and replace the placeholder\n const currentState = view.state\n let foundPos = -1\n currentState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"imageBlock\" &&\n node.attrs.loading\n ) {\n foundPos = pos\n return false\n }\n })\n\n if (foundPos !== -1) {\n const transaction = view.state.tr.replaceWith(\n foundPos,\n foundPos + 1,\n node\n )\n view.dispatch(transaction)\n }\n } catch (error) {\n console.error(\"Failed to upload image:\", error)\n // Remove placeholder on error\n const currentState = view.state\n let foundPos = -1\n currentState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"imageBlock\" &&\n node.attrs.loading\n ) {\n foundPos = pos\n return false\n }\n })\n\n if (foundPos !== -1) {\n const transaction = view.state.tr.delete(\n foundPos,\n foundPos + 1\n )\n view.dispatch(transaction)\n }\n }\n }\n })\n\n return true\n },\n },\n },\n }),\n ]\n },\n})\n\nexport default ImageBlock\n","import { ReactRenderer, ReactNodeViewRenderer } from \"@tiptap/react\"\nimport Suggestion from \"@tiptap/suggestion\"\nimport Mention from \"@tiptap/extension-mention\"\nimport type { SuggestionOptions } from \"@tiptap/suggestion\"\nimport type { RefObject } from \"react\"\nimport { MentionCommand } from \"./mention-command\"\nimport { MentionNodeView } from \"./mention-node-view\"\n\nexport interface MentionItem {\n id: string\n label: string\n avatar?: string\n email?: string\n type?: \"node\" | \"article\" // For reference mentions\n nodeId?: string // For node references (user-facing ID like \"TSK-1\")\n slug?: string // For article references (URL slug)\n}\n\nexport interface MentionOptions {\n /**\n * Function to fetch/filter mentionable items based on query\n */\n items?: (query: string) => MentionItem[] | Promise<MentionItem[]>\n\n /**\n * Custom render function for mention nodes\n */\n renderLabel?: (props: { node: any; options: any }) => string\n\n /**\n * Character that triggers the mention autocomplete (default: @)\n */\n char?: string\n\n /**\n * Custom name for the extension (to avoid duplicates)\n */\n name?: string\n}\n\n/**\n * Create the mention extension with custom suggestion rendering\n */\nexport const createMentionExtension = (options?: MentionOptions) => {\n const extensionName = options?.name ?? \"mention\"\n\n return Mention.extend({\n name: extensionName,\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => {\n if (!attributes.id) {\n return {}\n }\n return {\n \"data-id\": attributes.id,\n }\n },\n },\n label: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-label\"),\n renderHTML: (attributes) => {\n if (!attributes.label) {\n return {}\n }\n return {\n \"data-label\": attributes.label,\n }\n },\n },\n avatar: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-avatar\"),\n renderHTML: (attributes) => {\n if (!attributes.avatar) {\n return {}\n }\n return {\n \"data-avatar\": attributes.avatar,\n }\n },\n },\n type: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-ref-type\"),\n renderHTML: (attributes) => {\n if (!attributes.type) {\n return {}\n }\n return {\n \"data-ref-type\": attributes.type,\n }\n },\n },\n nodeId: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-node-id\"),\n renderHTML: (attributes) => {\n if (!attributes.nodeId) {\n return {}\n }\n return {\n \"data-node-id\": attributes.nodeId,\n }\n },\n },\n slug: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-slug\"),\n renderHTML: (attributes) => {\n if (!attributes.slug) {\n return {}\n }\n return {\n \"data-slug\": attributes.slug,\n }\n },\n },\n }\n },\n addNodeView() {\n return ReactNodeViewRenderer(MentionNodeView)\n },\n }).configure({\n HTMLAttributes: {\n class: \"mention\",\n },\n suggestion: {\n char: options?.char ?? \"@\",\n items: async ({ query }: { query: string }) => {\n if (!options?.items) return []\n const items = await options.items(query)\n return items\n },\n command: ({ editor, range, props: item }: any) => {\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: extensionName,\n attrs: {\n id: item.id,\n label: item.label,\n avatar: item.avatar,\n type: item.type,\n nodeId: item.nodeId,\n slug: item.slug,\n },\n },\n ])\n .run()\n },\n render: renderMentionSuggestion,\n },\n renderLabel: options?.renderLabel ?? ((props) => {\n return `@${props.node.attrs.label ?? props.node.attrs.id}`\n }),\n })\n}\n\n/**\n * Render function for mention suggestions (autocomplete dropdown)\n */\nexport const renderMentionSuggestion = () => {\n let component: ReactRenderer | null = null\n let container: HTMLElement | null = null\n\n const destroy = () => {\n component?.destroy()\n component = null\n if (container) {\n container.remove()\n container = null\n }\n }\n\n const updatePosition = (clientRect?: DOMRect | null) => {\n if (!container || !clientRect) return\n\n const gap = 8\n const maxDropdownHeight = 300 // Match the maxHeight from MentionCommand\n const spaceBelow = window.innerHeight - clientRect.bottom\n const spaceAbove = clientRect.top\n\n // Position above if not enough space below, otherwise position below\n const shouldPositionAbove = spaceBelow < maxDropdownHeight && spaceAbove > spaceBelow\n\n const left = Math.round(clientRect.left)\n\n if (shouldPositionAbove) {\n const bottom = Math.round(window.innerHeight - clientRect.top + gap)\n container.style.bottom = `${bottom}px`\n container.style.top = 'auto'\n } else {\n const top = Math.round(clientRect.bottom + gap)\n container.style.top = `${top}px`\n container.style.bottom = 'auto'\n }\n\n container.style.left = `${left}px`\n }\n\n return {\n onStart: (props: any) => {\n component = new ReactRenderer(MentionCommand, {\n props: {\n items: props.items ?? [],\n command: props.command ?? (() => {}),\n query: props.query ?? \"\",\n },\n editor: props.editor,\n })\n\n container = document.createElement(\"div\")\n container.style.position = \"fixed\"\n container.style.zIndex = \"9999\"\n document.body.appendChild(container)\n container.appendChild(component.element)\n\n const rect =\n typeof props.clientRect === \"function\" ? props.clientRect() : null\n if (rect) updatePosition(rect)\n },\n onUpdate: (props: any) => {\n component?.updateProps({\n items: props.items ?? [],\n command: props.command ?? (() => {}),\n query: props.query ?? \"\",\n })\n const rect =\n typeof props.clientRect === \"function\" ? props.clientRect() : null\n if (rect) updatePosition(rect)\n },\n onKeyDown: ({ event }: { event: KeyboardEvent }) => {\n if (!component) return false\n\n if (event.key === \"Escape\") {\n event.preventDefault()\n event.stopPropagation()\n destroy()\n return true\n }\n\n // Handle arrow keys and enter\n if ([\"ArrowUp\", \"ArrowDown\", \"Enter\"].includes(event.key)) {\n event.preventDefault()\n event.stopPropagation()\n // Let the MentionList component handle keyboard navigation\n return (component.ref as any)?.onKeyDown?.({ event }) ?? false\n }\n\n return false\n },\n onExit: () => {\n destroy()\n },\n }\n}\n\nexport default createMentionExtension\n","import { forwardRef, useEffect, useImperativeHandle, useState } from \"react\"\nimport type { MentionItem } from \"./mention\"\n\ninterface MentionCommandProps {\n items: MentionItem[]\n command: (item: MentionItem) => void\n query: string\n}\n\n// Simple Avatar component with inline styles\nfunction Avatar({ src, fallback }: { src?: string; fallback: string }) {\n return (\n <div style={{\n position: \"relative\",\n display: \"flex\",\n height: \"24px\",\n width: \"24px\",\n flexShrink: 0,\n overflow: \"hidden\",\n borderRadius: \"9999px\",\n }}>\n {src ? (\n <img\n style={{\n aspectRatio: \"1\",\n height: \"100%\",\n width: \"100%\",\n }}\n src={src}\n alt={fallback}\n />\n ) : (\n <div style={{\n display: \"flex\",\n height: \"100%\",\n width: \"100%\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: \"9999px\",\n backgroundColor: \"var(--muted)\",\n color: \"var(--muted-foreground)\",\n fontSize: \"10px\",\n fontWeight: 600,\n }}>\n {fallback}\n </div>\n )}\n </div>\n )\n}\n\n// Icon component for reference types\nfunction ReferenceIcon({ type }: { type: \"node\" | \"article\" }) {\n if (type === \"node\") {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ flexShrink: 0 }}>\n <path d=\"M12 3l8 4.5v9l-8 4.5l-8-4.5v-9l8-4.5\"></path>\n <path d=\"M12 12l8-4.5\"></path>\n <path d=\"M12 12v9\"></path>\n <path d=\"M12 12l-8-4.5\"></path>\n </svg>\n )\n }\n\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ flexShrink: 0 }}>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\"></path>\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z\"></path>\n <path d=\"M9 9l1 0\"></path>\n <path d=\"M9 13l6 0\"></path>\n <path d=\"M9 17l6 0\"></path>\n </svg>\n )\n}\n\nexport const MentionCommand = forwardRef<any, MentionCommandProps>((props, ref) => {\n const [selectedIndex, setSelectedIndex] = useState(0)\n\n const selectItem = (index: number) => {\n const item = props.items[index]\n if (item) {\n props.command(item)\n }\n }\n\n const upHandler = () => {\n setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length)\n }\n\n const downHandler = () => {\n setSelectedIndex((selectedIndex + 1) % props.items.length)\n }\n\n const enterHandler = () => {\n selectItem(selectedIndex)\n }\n\n useEffect(() => setSelectedIndex(0), [props.items])\n\n useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: { event: KeyboardEvent }) => {\n if (event.key === \"ArrowUp\") {\n upHandler()\n return true\n }\n\n if (event.key === \"ArrowDown\") {\n downHandler()\n return true\n }\n\n if (event.key === \"Enter\") {\n enterHandler()\n return true\n }\n\n return false\n },\n }))\n\n return (\n <div\n id=\"mention-list\"\n style={{\n backgroundColor: \"var(--popover)\",\n color: \"var(--foreground)\",\n maxHeight: \"300px\",\n minWidth: \"280px\",\n overflow: \"hidden\",\n overflowY: \"auto\",\n borderRadius: \"12px\",\n border: \"1px solid var(--border)\",\n padding: \"4px\",\n boxShadow: \"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)\",\n }}\n >\n {props.items.length ? (\n props.items.map((item, index) => (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => selectItem(index)}\n onMouseEnter={() => setSelectedIndex(index)}\n style={{\n position: \"relative\",\n display: \"flex\",\n width: \"100%\",\n cursor: \"default\",\n userSelect: \"none\",\n alignItems: \"center\",\n gap: \"8px\",\n borderRadius: \"4px\",\n padding: \"10px 8px\",\n fontSize: \"14px\",\n outline: \"none\",\n backgroundColor: index === selectedIndex ? \"var(--accent)\" : \"transparent\",\n color: index === selectedIndex ? \"var(--accent-foreground)\" : \"inherit\",\n border: \"none\",\n textAlign: \"left\",\n }}\n >\n {item.type ? (\n <ReferenceIcon type={item.type} />\n ) : (\n <Avatar\n src={item.avatar}\n fallback={item.label.slice(0, 2).toUpperCase()}\n />\n )}\n <span style={{\n flex: 1,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}>\n {item.label}\n </span>\n </button>\n ))\n ) : (\n <div style={{\n padding: \"24px 0\",\n textAlign: \"center\",\n fontSize: \"14px\",\n color: \"var(--muted-foreground)\",\n }}>\n No results found\n </div>\n )}\n </div>\n )\n})\n\nMentionCommand.displayName = \"MentionCommand\"\n","import { NodeViewWrapper } from \"@tiptap/react\"\nimport type { NodeViewProps } from \"@tiptap/react\"\n\n// Icon components\nfunction NodeIcon() {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ flexShrink: 0 }}>\n <path d=\"M12 3l8 4.5v9l-8 4.5l-8-4.5v-9l8-4.5\"></path>\n <path d=\"M12 12l8-4.5\"></path>\n <path d=\"M12 12v9\"></path>\n <path d=\"M12 12l-8-4.5\"></path>\n </svg>\n )\n}\n\nfunction ArticleIcon() {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ flexShrink: 0 }}>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\"></path>\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z\"></path>\n <path d=\"M9 9l1 0\"></path>\n <path d=\"M9 13l6 0\"></path>\n <path d=\"M9 17l6 0\"></path>\n </svg>\n )\n}\n\nexport const MentionNodeView = (props: NodeViewProps) => {\n const { node } = props\n const { id, label, avatar, type } = node.attrs\n\n // Determine styling based on type\n const isNode = type === \"node\"\n const isArticle = type === \"article\"\n const isReference = isNode || isArticle\n\n const backgroundColor = isArticle\n ? \"rgba(249, 115, 22, 0.15)\" // Orange for articles\n : isNode\n ? \"rgba(107, 114, 128, 0.15)\" // Gray for nodes\n : \"var(--accent)\" // Default for user mentions\n\n const color = isArticle\n ? \"rgb(234, 88, 12)\" // Orange text\n : isNode\n ? \"rgb(75, 85, 99)\" // Gray text\n : \"var(--accent-foreground)\" // Default\n\n const border = isArticle\n ? \"1px solid rgba(249, 115, 22, 0.3)\"\n : isNode\n ? \"1px solid rgba(107, 114, 128, 0.3)\"\n : \"none\"\n\n return (\n <NodeViewWrapper\n as=\"span\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"3px\",\n backgroundColor,\n color,\n border,\n padding: isReference ? \"1px 6px\" : \"1px 6px 1px 1px\",\n borderRadius: \"12px\",\n fontSize: \"13px\",\n fontWeight: 500,\n verticalAlign: \"middle\",\n }}\n >\n {/* Show icon for references */}\n {isNode && <NodeIcon />}\n {isArticle && <ArticleIcon />}\n\n {/* Show avatar for user mentions */}\n {!isReference && avatar && (\n <img\n src={avatar}\n alt={label || id}\n style={{\n width: \"20px\",\n height: \"20px\",\n borderRadius: \"50%\",\n flexShrink: 0,\n }}\n />\n )}\n {!isReference && !avatar && (\n <div\n style={{\n width: \"20px\",\n height: \"20px\",\n borderRadius: \"50%\",\n backgroundColor: \"var(--muted)\",\n color: \"var(--muted-foreground)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"10px\",\n fontWeight: 600,\n flexShrink: 0,\n }}\n >\n {(label || id).slice(0, 2).toUpperCase()}\n </div>\n )}\n <span>{label || id}</span>\n </NodeViewWrapper>\n )\n}\n","import BaseDragHandle from \"@tiptap/extension-drag-handle\"\nimport type { Node } from \"@tiptap/pm/model\"\nimport type { Editor } from \"@tiptap/core\"\n\nexport interface DragHandleCallbacks {\n onAddBlock?: (editor: Editor, node: Node | null) => void\n onGripClick?: (editor: Editor, node: Node | null, element: HTMLElement) => void\n}\n\nlet currentCallbacks: DragHandleCallbacks = {}\nlet currentNode: Node | null = null\nlet currentEditor: Editor | null = null\n\nexport function setDragHandleCallbacks(callbacks: DragHandleCallbacks) {\n currentCallbacks = callbacks\n}\n\nfunction createDragHandleElement(): HTMLElement {\n const container = document.createElement(\"div\")\n container.className = \"nph-drag-handle\"\n\n const plusBtn = document.createElement(\"button\")\n plusBtn.className = \"nph-drag-handle__btn\"\n plusBtn.type = \"button\"\n plusBtn.setAttribute(\"aria-label\", \"Add block\")\n plusBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14\"/><path d=\"M5 12h14\"/></svg>`\n plusBtn.addEventListener(\"click\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n if (currentEditor) {\n currentCallbacks.onAddBlock?.(currentEditor, currentNode)\n }\n })\n\n const gripBtn = document.createElement(\"button\")\n gripBtn.className = \"nph-drag-handle__btn nph-drag-handle__grip\"\n gripBtn.type = \"button\"\n gripBtn.setAttribute(\"aria-label\", \"Drag to reorder\")\n gripBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"9\" cy=\"5\" r=\"1\"/><circle cx=\"9\" cy=\"12\" r=\"1\"/><circle cx=\"9\" cy=\"19\" r=\"1\"/><circle cx=\"15\" cy=\"5\" r=\"1\"/><circle cx=\"15\" cy=\"12\" r=\"1\"/><circle cx=\"15\" cy=\"19\" r=\"1\"/></svg>`\n gripBtn.addEventListener(\"click\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n if (currentEditor) {\n currentCallbacks.onGripClick?.(currentEditor, currentNode, container)\n }\n })\n\n container.appendChild(plusBtn)\n container.appendChild(gripBtn)\n\n return container\n}\n\nexport const DragHandle = BaseDragHandle.configure({\n render: createDragHandleElement,\n nested: true,\n onNodeChange: ({ node, editor }) => {\n currentNode = node\n currentEditor = editor\n },\n})\n\nexport default DragHandle\n","export { TableKit } from \"@tiptap/extension-table\"\nexport { Table, TableCell, TableHeader, TableRow } from \"@tiptap/extension-table\"\n","import { Extension } from \"@tiptap/core\"\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\"\nimport { MarkdownParser, defaultMarkdownParser } from \"@tiptap/pm/markdown\"\n\nconst markdownPastePluginKey = new PluginKey(\"markdownPaste\")\n\n/**\n * Heuristic: does the plain text look like it contains markdown syntax?\n */\nfunction looksLikeMarkdown(text: string): boolean {\n const patterns = [\n /^#{1,6}\\s/m, // headings\n /^\\s*[-*+]\\s/m, // unordered list\n /^\\s*\\d+\\.\\s/m, // ordered list\n /^\\s*>\\s/m, // blockquote\n /\\|.+\\|/m, // table\n /^```/m, // fenced code block\n /\\*\\*.+\\*\\*/, // bold\n /\\*.+\\*/, // italic\n /~~.+~~/, // strikethrough\n /`[^`]+`/, // inline code\n /^\\s*---\\s*$/m, // horizontal rule\n /^\\s*\\*\\*\\*\\s*$/m, // horizontal rule alt\n /\\[.+\\]\\(.+\\)/, // links\n /!\\[.*\\]\\(.+\\)/, // images\n ]\n // Need at least one markdown pattern match and it shouldn't be HTML\n const hasMarkdown = patterns.some((p) => p.test(text))\n const isHtml = /^<[a-z][\\s\\S]*>/i.test(text.trim())\n return hasMarkdown && !isHtml\n}\n\n/**\n * Build a MarkdownParser configured for TipTap's schema node/mark names.\n * Re-uses the markdown-it tokenizer from prosemirror-markdown's default parser.\n */\nfunction buildParser(schema: any): MarkdownParser | null {\n // Grab the markdown-it tokenizer instance from prosemirror-markdown's default parser\n const md = defaultMarkdownParser.tokenizer\n\n const tokens: Record<string, any> = {}\n\n // Block nodes\n if (schema.nodes.paragraph) tokens.paragraph = { block: \"paragraph\" }\n if (schema.nodes.heading) {\n tokens.heading = {\n block: \"heading\",\n getAttrs: (tok: any) => ({ level: Number(tok.tag.slice(1)) }),\n }\n }\n if (schema.nodes.blockquote) tokens.blockquote = { block: \"blockquote\" }\n if (schema.nodes.bulletList) tokens.bullet_list = { block: \"bulletList\" }\n if (schema.nodes.orderedList) {\n tokens.ordered_list = {\n block: \"orderedList\",\n getAttrs: (tok: any) => ({ start: Number(tok.attrGet(\"start\") || 1) }),\n }\n }\n if (schema.nodes.listItem) tokens.list_item = { block: \"listItem\" }\n if (schema.nodes.codeBlock) {\n tokens.code_block = { block: \"codeBlock\", noCloseToken: true }\n tokens.fence = {\n block: \"codeBlock\",\n getAttrs: (tok: any) => ({ language: tok.info || \"\" }),\n noCloseToken: true,\n }\n }\n if (schema.nodes.horizontalRule) {\n tokens.hr = { node: \"horizontalRule\" }\n }\n if (schema.nodes.hardBreak) {\n tokens.hardbreak = { node: \"hardBreak\" }\n }\n if (schema.nodes.image) {\n tokens.image = {\n node: \"image\",\n getAttrs: (tok: any) => ({\n src: tok.attrGet(\"src\"),\n title: tok.attrGet(\"title\") || null,\n alt: tok.children?.[0]?.content || null,\n }),\n }\n }\n\n // Table support — markdown-it needs the table plugin enabled\n if (schema.nodes.table) {\n tokens.table = { block: \"table\" }\n tokens.thead = { ignore: true }\n tokens.tbody = { ignore: true }\n tokens.tr = { block: \"tableRow\" }\n tokens.th = { block: \"tableHeader\" }\n tokens.td = { block: \"tableCell\" }\n }\n\n // Marks\n if (schema.marks.bold || schema.marks.strong) {\n tokens.strong = { mark: schema.marks.bold ? \"bold\" : \"strong\" }\n }\n if (schema.marks.italic || schema.marks.em) {\n tokens.em = { mark: schema.marks.italic ? \"italic\" : \"em\" }\n }\n if (schema.marks.code) {\n tokens.code_inline = { mark: \"code\", noCloseToken: true }\n }\n if (schema.marks.link) {\n tokens.link = {\n mark: \"link\",\n getAttrs: (tok: any) => ({\n href: tok.attrGet(\"href\"),\n title: tok.attrGet(\"title\") || null,\n }),\n }\n }\n if (schema.marks.strike || schema.marks.strikethrough) {\n tokens.s = { mark: schema.marks.strike ? \"strike\" : \"strikethrough\" }\n }\n\n try {\n return new MarkdownParser(schema, md, tokens)\n } catch {\n return null\n }\n}\n\nexport const MarkdownPaste = Extension.create({\n name: \"markdownPaste\",\n\n addProseMirrorPlugins() {\n const schema = this.editor.schema\n let parser: MarkdownParser | null = null\n\n return [\n new Plugin({\n key: markdownPastePluginKey,\n props: {\n handlePaste(view, event) {\n const clipboardData = event.clipboardData\n if (!clipboardData) return false\n\n // If there's HTML content, let ProseMirror handle it normally\n // (the browser/OS already converted rich content)\n const html = clipboardData.getData(\"text/html\")\n if (html && html.trim().length > 0) return false\n\n const text = clipboardData.getData(\"text/plain\")\n if (!text || !looksLikeMarkdown(text)) return false\n\n // Lazily build parser on first use\n if (!parser) {\n parser = buildParser(schema)\n }\n if (!parser) return false\n\n try {\n const doc = parser.parse(text)\n if (!doc || doc.content.size === 0) return false\n\n const { tr } = view.state\n const slice = doc.slice(0, doc.content.size)\n tr.replaceSelection(slice)\n view.dispatch(tr)\n return true\n } catch {\n // Fall back to default paste behavior\n return false\n }\n },\n },\n }),\n ]\n },\n})\n\nexport default MarkdownPaste\n","import Suggestion from \"@tiptap/suggestion\"\nimport { Extension } from \"@tiptap/core\"\nimport type { ReactNode } from \"react\"\nimport { queryAtom, rangeAtom, slashMenuOpenAtom, slashMenuRectAtom } from \"../utils/atoms\"\nimport { novelStore } from \"../utils/store\"\n\nexport const Command = Extension.create({\n name: \"slash-command\",\n addOptions() {\n return {\n suggestion: {\n char: \"/\",\n command: (ctx: any) => {\n ctx.props.command({ editor: ctx.editor, range: ctx.range })\n },\n } as any,\n }\n },\n addProseMirrorPlugins() {\n const base: any = this.options.suggestion ?? {}\n return [\n Suggestion({\n editor: this.editor,\n char: base.char ?? \"/\",\n startOfLine: base.startOfLine ?? true,\n items: base.items ?? (() => [\"/\"] as any),\n command: (ctx: any) => {\n if (typeof ctx?.props?.command === \"function\") {\n ctx.props.command({ editor: ctx.editor, range: ctx.range })\n }\n },\n ...base,\n render: () => {\n return {\n onStart: (props: any) => {\n const { selection } = props.editor.state\n const parentNode = selection.$from.node(selection.$from.depth)\n const blockType = parentNode.type.name\n\n if (blockType === \"codeBlock\") return false\n\n const { $from } = selection\n const marks = $from.marks()\n if (marks.some((mark: any) => mark.type.name === \"code\" || mark.type.name === \"link\")) {\n return false\n }\n\n novelStore.set(queryAtom, props.query ?? \"\")\n novelStore.set(rangeAtom, props.range ?? null)\n novelStore.set(slashMenuOpenAtom, true)\n\n const rect = typeof props.clientRect === \"function\" ? props.clientRect() : null\n novelStore.set(slashMenuRectAtom, rect)\n },\n onUpdate: (props: any) => {\n novelStore.set(queryAtom, props.query ?? \"\")\n novelStore.set(rangeAtom, props.range ?? null)\n\n const rect = typeof props.clientRect === \"function\" ? props.clientRect() : null\n novelStore.set(slashMenuRectAtom, rect)\n },\n onKeyDown: ({ event }: { event: KeyboardEvent }) => {\n if (event.key === \"Escape\") {\n novelStore.set(slashMenuOpenAtom, false)\n return true\n }\n\n if ([\"ArrowUp\", \"ArrowDown\", \"Enter\"].includes(event.key)) {\n const slashCommand = document.querySelector(\"#slash-command\")\n if (slashCommand) {\n slashCommand.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key: event.key,\n cancelable: true,\n bubbles: true,\n })\n )\n return true\n }\n }\n\n return false\n },\n onExit: () => {\n novelStore.set(slashMenuOpenAtom, false)\n novelStore.set(queryAtom, \"\")\n novelStore.set(rangeAtom, null)\n novelStore.set(slashMenuRectAtom, null)\n },\n }\n },\n }),\n ]\n },\n})\n\nexport const renderItems = () => ({\n onStart: () => {},\n onUpdate: () => {},\n onKeyDown: () => false,\n onExit: () => {},\n})\n\nexport interface SuggestionItem {\n title: string\n description: string\n icon: ReactNode\n searchTerms?: string[]\n command?: (props: {\n editor: any\n range: { from: number; to: number }\n }) => void\n}\n\nexport const createSuggestionItems = (items: SuggestionItem[]) => items\n\nexport const handleCommandNavigation = (event: KeyboardEvent) => {\n if ([\"ArrowUp\", \"ArrowDown\", \"Enter\"].includes(event.key)) {\n const slashCommand = document.querySelector(\"#slash-command\")\n if (slashCommand) return true\n }\n}\n"],"mappings":"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","names":["useCurrentEditor","jsx","forwardRef","useCurrentEditor","jsx","forwardRef","jsx","forwardRef","forwardRef","useCurrentEditor","useAtomValue","jsx","forwardRef","useCurrentEditor","useAtomValue","mergeAttributes","Plugin","node","ReactNodeViewRenderer","forwardRef","useEffect","useState","jsx","jsx","jsxs","ReactNodeViewRenderer","Plugin","PluginKey","Extension","Extension"]}
@@ -18,7 +18,7 @@ import {
18
18
  renderItems,
19
19
  renderMentionSuggestion,
20
20
  useCurrentEditor
21
- } from "../chunk-457ETWB6.js";
21
+ } from "../chunk-MSNTVITF.js";
22
22
  export {
23
23
  EditorBubble,
24
24
  EditorBubbleItem,
@@ -313,6 +313,7 @@ var ImageBlock = import_extension_image.Image.extend({
313
313
  return {
314
314
  ...this.parent?.(),
315
315
  uploadImage: void 0,
316
+ browseAssets: void 0,
316
317
  inline: false
317
318
  };
318
319
  },
@@ -1377,6 +1378,7 @@ var ExtensionKit = (options) => {
1377
1378
  import_extension_underline.default,
1378
1379
  ImageBlock.configure({
1379
1380
  uploadImage: options?.uploadImage,
1381
+ browseAssets: options?.browseAssets,
1380
1382
  nodeView: options?.imageBlockView
1381
1383
  }),
1382
1384
  VideoBlock.configure({
@@ -2695,13 +2697,14 @@ var ImageUploader = ({ onUpload, editor }) => {
2695
2697
  const [loading, setLoading] = (0, import_react24.useState)(false);
2696
2698
  const [draggedInside, setDraggedInside] = (0, import_react24.useState)(false);
2697
2699
  const fileInputRef = (0, import_react24.useRef)(null);
2700
+ const imageExtension = editor.extensionManager.extensions.find(
2701
+ (ext) => ext.name === "imageBlock"
2702
+ );
2703
+ const browseAssets = imageExtension?.options?.browseAssets;
2698
2704
  const uploadFile = (0, import_react24.useCallback)(
2699
2705
  async (file) => {
2700
2706
  setLoading(true);
2701
2707
  try {
2702
- const imageExtension = editor.extensionManager.extensions.find(
2703
- (ext) => ext.name === "imageBlock"
2704
- );
2705
2708
  const uploadImage = imageExtension?.options?.uploadImage;
2706
2709
  if (uploadImage) {
2707
2710
  const url = await uploadImage(file);
@@ -2715,7 +2718,7 @@ var ImageUploader = ({ onUpload, editor }) => {
2715
2718
  setLoading(false);
2716
2719
  }
2717
2720
  },
2718
- [editor, onUpload]
2721
+ [imageExtension, onUpload]
2719
2722
  );
2720
2723
  const handleUploadClick = (0, import_react24.useCallback)(() => {
2721
2724
  fileInputRef.current?.click();
@@ -2766,19 +2769,34 @@ var ImageUploader = ({ onUpload, editor }) => {
2766
2769
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_react8.IconPhoto, { size: 48, className: "nph-image-uploader__icon" }),
2767
2770
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "nph-image-uploader__content", children: [
2768
2771
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "nph-image-uploader__text", children: draggedInside ? "Drop image here" : "Drag and drop or" }),
2769
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2770
- "button",
2771
- {
2772
- type: "button",
2773
- disabled: draggedInside,
2774
- onClick: handleUploadClick,
2775
- className: "nph-btn nph-btn-ghost nph-btn-sm nph-image-uploader__button",
2776
- children: [
2777
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_react8.IconUpload, { size: 16 }),
2778
- "Upload an image"
2779
- ]
2780
- }
2781
- ) })
2772
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "nph-image-uploader__actions", children: [
2773
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2774
+ "button",
2775
+ {
2776
+ type: "button",
2777
+ disabled: draggedInside,
2778
+ onClick: handleUploadClick,
2779
+ className: "nph-btn nph-btn-ghost nph-btn-sm nph-image-uploader__button",
2780
+ children: [
2781
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_react8.IconUpload, { size: 16 }),
2782
+ "Upload an image"
2783
+ ]
2784
+ }
2785
+ ),
2786
+ browseAssets && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2787
+ "button",
2788
+ {
2789
+ type: "button",
2790
+ disabled: draggedInside,
2791
+ onClick: () => browseAssets(onUpload),
2792
+ className: "nph-btn nph-btn-ghost nph-btn-sm nph-image-uploader__button",
2793
+ children: [
2794
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_react8.IconPhoto, { size: 16 }),
2795
+ "Browse assets"
2796
+ ]
2797
+ }
2798
+ )
2799
+ ] })
2782
2800
  ] }),
2783
2801
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2784
2802
  "input",
@@ -3872,6 +3890,7 @@ function Editor5({
3872
3890
  onUpdate,
3873
3891
  onCreate,
3874
3892
  uploadImage,
3893
+ browseAssets,
3875
3894
  collaboration,
3876
3895
  mentionOptions,
3877
3896
  referenceOptions,
@@ -3944,6 +3963,7 @@ function Editor5({
3944
3963
  extensions: [
3945
3964
  ...extension_kit_default({
3946
3965
  uploadImage,
3966
+ browseAssets,
3947
3967
  collaboration,
3948
3968
  imageBlockView: ImageBlockView,
3949
3969
  videoBlockView: VideoBlockView,