@react-email/editor 0.0.0-experimental.22 → 0.0.0-experimental.24
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/columns-CUxUEHje.mjs +497 -0
- package/dist/columns-CUxUEHje.mjs.map +1 -0
- package/dist/columns-ZSaLdkg9.cjs +630 -0
- package/dist/core/index.cjs +8 -0
- package/dist/core/index.d.cts +2 -0
- package/dist/core/index.d.mts +2 -0
- package/dist/core/index.mjs +4 -0
- package/dist/core-BjmRceVw.mjs +1999 -0
- package/dist/core-BjmRceVw.mjs.map +1 -0
- package/dist/core-iuG1UrYN.cjs +2250 -0
- package/dist/extensions/index.cjs +46 -0
- package/dist/extensions/index.d.cts +389 -0
- package/dist/extensions/index.d.cts.map +1 -0
- package/dist/extensions/index.d.mts +389 -0
- package/dist/extensions/index.d.mts.map +1 -0
- package/dist/extensions/index.mjs +4 -0
- package/dist/index-CfslA7KT.d.cts +130 -0
- package/dist/index-CfslA7KT.d.cts.map +1 -0
- package/dist/index-hbHRR7oB.d.mts +130 -0
- package/dist/index-hbHRR7oB.d.mts.map +1 -0
- package/dist/set-text-alignment-Bx3bPteH.cjs +24 -0
- package/dist/set-text-alignment-DZvgnbvz.mjs +19 -0
- package/dist/set-text-alignment-DZvgnbvz.mjs.map +1 -0
- package/dist/ui/index.cjs +1646 -0
- package/dist/ui/index.d.cts +668 -0
- package/dist/ui/index.d.cts.map +1 -0
- package/dist/ui/index.d.mts +668 -0
- package/dist/ui/index.d.mts.map +1 -0
- package/dist/ui/index.mjs +1584 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/utils/index.cjs +3 -0
- package/dist/utils/index.d.cts +7 -0
- package/dist/utils/index.d.cts.map +1 -0
- package/dist/utils/index.d.mts +7 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +3 -0
- package/package.json +38 -11
- package/dist/index.cjs +0 -4228
- package/dist/index.d.cts +0 -1175
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.mts +0 -1175
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -4072
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["editor","editor","editor","editor","editor","editor","BubbleMenu","editor","offset","BubbleMenu","offset","BubbleMenu","offset","BubbleMenu","offset","SplitSquareVerticalIcon","Rows2Icon"],"sources":["../../src/ui/bubble-menu/context.tsx","../../src/ui/bubble-menu/item.tsx","../../src/ui/bubble-menu/align-center.tsx","../../src/ui/bubble-menu/align-left.tsx","../../src/ui/bubble-menu/align-right.tsx","../../src/ui/bubble-menu/create-mark-bubble-item.tsx","../../src/ui/bubble-menu/bold.tsx","../../src/ui/bubble-menu/code.tsx","../../src/ui/bubble-menu/group.tsx","../../src/ui/bubble-menu/italic.tsx","../../src/ui/bubble-menu/utils.ts","../../src/ui/bubble-menu/link-selector.tsx","../../src/ui/bubble-menu/node-selector.tsx","../../src/ui/bubble-menu/root.tsx","../../src/ui/bubble-menu/strike.tsx","../../src/ui/bubble-menu/underline.tsx","../../src/ui/bubble-menu/uppercase.tsx","../../src/ui/bubble-menu/default.tsx","../../src/ui/bubble-menu/separator.tsx","../../src/ui/bubble-menu/index.ts","../../src/ui/button-bubble-menu/context.tsx","../../src/ui/button-bubble-menu/edit-link.tsx","../../src/ui/button-bubble-menu/root.tsx","../../src/ui/button-bubble-menu/toolbar.tsx","../../src/ui/button-bubble-menu/default.tsx","../../src/ui/button-bubble-menu/index.ts","../../src/ui/image-bubble-menu/context.tsx","../../src/ui/image-bubble-menu/edit-link.tsx","../../src/ui/image-bubble-menu/root.tsx","../../src/ui/image-bubble-menu/toolbar.tsx","../../src/ui/image-bubble-menu/default.tsx","../../src/ui/image-bubble-menu/index.ts","../../src/ui/link-bubble-menu/context.tsx","../../src/ui/link-bubble-menu/edit-link.tsx","../../src/ui/link-bubble-menu/form.tsx","../../src/ui/link-bubble-menu/open-link.tsx","../../src/ui/link-bubble-menu/root.tsx","../../src/ui/link-bubble-menu/toolbar.tsx","../../src/ui/link-bubble-menu/unlink.tsx","../../src/ui/link-bubble-menu/default.tsx","../../src/ui/link-bubble-menu/index.ts","../../src/ui/slash-command/utils.ts","../../src/ui/slash-command/command-list.tsx","../../src/ui/slash-command/commands.tsx","../../src/ui/slash-command/search.ts","../../src/ui/slash-command/root.tsx","../../src/ui/slash-command/index.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core';\nimport * as React from 'react';\n\nexport interface BubbleMenuContextValue {\n editor: Editor;\n}\n\nexport const BubbleMenuContext =\n React.createContext<BubbleMenuContextValue | null>(null);\n\nexport function useBubbleMenuContext(): BubbleMenuContextValue {\n const context = React.useContext(BubbleMenuContext);\n if (!context) {\n throw new Error(\n 'BubbleMenu compound components must be used within <BubbleMenu.Root>',\n );\n }\n return context;\n}\n","import type * as React from 'react';\n\nexport interface BubbleMenuItemProps extends React.ComponentProps<'button'> {\n /** Used for aria-label and data-item attribute */\n name: string;\n /** Whether this item is currently active */\n isActive: boolean;\n /** Called when clicked */\n onCommand: () => void;\n}\n\nexport function BubbleMenuItem({\n name,\n isActive,\n onCommand,\n className,\n children,\n ...rest\n}: BubbleMenuItemProps) {\n return (\n <button\n type=\"button\"\n aria-label={name}\n aria-pressed={isActive}\n className={className}\n data-re-bubble-menu-item=\"\"\n data-item={name}\n {...(isActive ? { 'data-active': '' } : {})}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onCommand}\n {...rest}\n >\n {children}\n </button>\n );\n}\n","import { useEditorState } from '@tiptap/react';\nimport { AlignCenterIcon } from 'lucide-react';\nimport { setTextAlignment } from '../../utils/set-text-alignment';\nimport { useBubbleMenuContext } from './context';\nimport type { PreWiredItemProps } from './create-mark-bubble-item';\nimport { BubbleMenuItem } from './item';\n\nexport function BubbleMenuAlignCenter({\n className,\n children,\n}: PreWiredItemProps) {\n const { editor } = useBubbleMenuContext();\n\n const isActive = useEditorState({\n editor,\n selector: ({ editor }) =>\n editor?.isActive({ alignment: 'center' }) ?? false,\n });\n\n return (\n <BubbleMenuItem\n name=\"align-center\"\n isActive={isActive}\n onCommand={() => setTextAlignment(editor, 'center')}\n className={className}\n >\n {children ?? <AlignCenterIcon />}\n </BubbleMenuItem>\n );\n}\n","import { useEditorState } from '@tiptap/react';\nimport { AlignLeftIcon } from 'lucide-react';\nimport { setTextAlignment } from '../../utils/set-text-alignment';\nimport { useBubbleMenuContext } from './context';\nimport type { PreWiredItemProps } from './create-mark-bubble-item';\nimport { BubbleMenuItem } from './item';\n\nexport function BubbleMenuAlignLeft({\n className,\n children,\n}: PreWiredItemProps) {\n const { editor } = useBubbleMenuContext();\n\n const isActive = useEditorState({\n editor,\n selector: ({ editor }) => editor?.isActive({ alignment: 'left' }) ?? false,\n });\n\n return (\n <BubbleMenuItem\n name=\"align-left\"\n isActive={isActive}\n onCommand={() => setTextAlignment(editor, 'left')}\n className={className}\n >\n {children ?? <AlignLeftIcon />}\n </BubbleMenuItem>\n );\n}\n","import { useEditorState } from '@tiptap/react';\nimport { AlignRightIcon } from 'lucide-react';\nimport { setTextAlignment } from '../../utils/set-text-alignment';\nimport { useBubbleMenuContext } from './context';\nimport type { PreWiredItemProps } from './create-mark-bubble-item';\nimport { BubbleMenuItem } from './item';\n\nexport function BubbleMenuAlignRight({\n className,\n children,\n}: PreWiredItemProps) {\n const { editor } = useBubbleMenuContext();\n\n const isActive = useEditorState({\n editor,\n selector: ({ editor }) => editor?.isActive({ alignment: 'right' }) ?? false,\n });\n\n return (\n <BubbleMenuItem\n name=\"align-right\"\n isActive={isActive}\n onCommand={() => setTextAlignment(editor, 'right')}\n className={className}\n >\n {children ?? <AlignRightIcon />}\n </BubbleMenuItem>\n );\n}\n","import { useEditorState } from '@tiptap/react';\nimport type * as React from 'react';\nimport { useBubbleMenuContext } from './context';\nimport { BubbleMenuItem } from './item';\n\nexport interface PreWiredItemProps {\n className?: string;\n /** Override the default icon */\n children?: React.ReactNode;\n}\n\ninterface MarkBubbleItemConfig {\n name: string;\n activeName: string;\n activeParams?: Record<string, unknown>;\n command: string;\n icon: React.ReactNode;\n}\n\nexport function createMarkBubbleItem(config: MarkBubbleItemConfig) {\n function MarkBubbleItem({ className, children }: PreWiredItemProps) {\n const { editor } = useBubbleMenuContext();\n\n const isActive = useEditorState({\n editor,\n selector: ({ editor }) => {\n if (config.activeParams) {\n return (\n editor?.isActive(config.activeName, config.activeParams) ?? false\n );\n }\n return editor?.isActive(config.activeName) ?? false;\n },\n });\n\n const handleCommand = () => {\n const chain = editor.chain().focus();\n const method = (chain as unknown as Record<string, () => typeof chain>)[\n config.command\n ];\n if (method) {\n method.call(chain).run();\n }\n };\n\n return (\n <BubbleMenuItem\n name={config.name}\n isActive={isActive}\n onCommand={handleCommand}\n className={className}\n >\n {children ?? config.icon}\n </BubbleMenuItem>\n );\n }\n\n MarkBubbleItem.displayName = `BubbleMenu${config.name.charAt(0).toUpperCase() + config.name.slice(1)}`;\n\n return MarkBubbleItem;\n}\n","import { BoldIcon } from 'lucide-react';\nimport { createMarkBubbleItem } from './create-mark-bubble-item';\n\nexport const BubbleMenuBold = createMarkBubbleItem({\n name: 'bold',\n activeName: 'bold',\n command: 'toggleBold',\n icon: <BoldIcon />,\n});\n","import { CodeIcon } from 'lucide-react';\nimport { createMarkBubbleItem } from './create-mark-bubble-item';\n\nexport const BubbleMenuCode = createMarkBubbleItem({\n name: 'code',\n activeName: 'code',\n command: 'toggleCode',\n icon: <CodeIcon />,\n});\n","import type * as React from 'react';\n\nexport interface BubbleMenuItemGroupProps {\n className?: string;\n children: React.ReactNode;\n}\n\nexport function BubbleMenuItemGroup({\n className,\n children,\n}: BubbleMenuItemGroupProps) {\n return (\n <fieldset className={className} data-re-bubble-menu-group=\"\">\n {children}\n </fieldset>\n );\n}\n","import { ItalicIcon } from 'lucide-react';\nimport { createMarkBubbleItem } from './create-mark-bubble-item';\n\nexport const BubbleMenuItalic = createMarkBubbleItem({\n name: 'italic',\n activeName: 'italic',\n command: 'toggleItalic',\n icon: <ItalicIcon />,\n});\n","import type { Editor } from '@tiptap/core';\n\nconst SAFE_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:']);\n\n/**\n * Basic URL validation and auto-prefixing.\n * Rejects dangerous schemes (javascript:, data:, vbscript:, etc.).\n * Returns the valid URL string or null.\n */\nexport function getUrlFromString(str: string): string | null {\n if (str === '#') {\n return str;\n }\n\n try {\n const url = new URL(str);\n if (SAFE_PROTOCOLS.has(url.protocol)) {\n return str;\n }\n return null;\n } catch {\n // not a valid URL as-is\n }\n\n try {\n if (str.includes('.') && !str.includes(' ')) {\n return new URL(`https://${str}`).toString();\n }\n } catch {\n // still not valid\n }\n\n return null;\n}\n\nexport function setLinkHref(editor: Editor, href: string): void {\n if (href.length === 0) {\n editor.chain().unsetLink().run();\n return;\n }\n\n const { from, to } = editor.state.selection;\n if (from === to) {\n editor\n .chain()\n .extendMarkRange('link')\n .setLink({ href })\n .setTextSelection({ from, to })\n .run();\n return;\n }\n\n editor.chain().setLink({ href }).run();\n}\n\nexport function focusEditor(editor: Editor): void {\n setTimeout(() => {\n editor.commands.focus();\n }, 0);\n}\n","import type { Editor } from '@tiptap/core';\nimport { useEditorState } from '@tiptap/react';\nimport { Check, LinkIcon, UnlinkIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { editorEventBus } from '../../core/event-bus';\nimport { useBubbleMenuContext } from './context';\nimport { focusEditor, getUrlFromString, setLinkHref } from './utils';\n\nexport interface BubbleMenuLinkSelectorProps {\n className?: string;\n /** Whether to show the link icon toggle button (default: true) */\n showToggle?: boolean;\n /** Custom URL validator. Return the valid URL string or null. */\n validateUrl?: (value: string) => string | null;\n /** Called after link is applied */\n onLinkApply?: (href: string) => void;\n /** Called after link is removed */\n onLinkRemove?: () => void;\n /** Plugin slot: extra actions rendered inside the link input form */\n children?: React.ReactNode;\n /** Controlled open state */\n open?: boolean;\n /** Called when open state changes */\n onOpenChange?: (open: boolean) => void;\n}\n\nexport function BubbleMenuLinkSelector({\n className,\n showToggle = true,\n validateUrl,\n onLinkApply,\n onLinkRemove,\n children,\n open: controlledOpen,\n onOpenChange,\n}: BubbleMenuLinkSelectorProps) {\n const { editor } = useBubbleMenuContext();\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n const setIsOpen = React.useCallback(\n (value: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(value);\n }\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n const editorState = useEditorState({\n editor,\n selector: ({ editor }) => ({\n isLinkActive: editor?.isActive('link') ?? false,\n hasLink: Boolean(editor?.getAttributes('link').href),\n currentHref: (editor?.getAttributes('link').href as string) || '',\n }),\n });\n\n const setIsOpenRef = React.useRef(setIsOpen);\n setIsOpenRef.current = setIsOpen;\n\n React.useEffect(() => {\n const subscription = editorEventBus.on('bubble-menu:add-link', () => {\n setIsOpenRef.current(true);\n });\n\n return () => {\n setIsOpenRef.current(false);\n subscription.unsubscribe();\n };\n }, []);\n\n if (!editorState) {\n return null;\n }\n\n const handleOpenLink = () => {\n setIsOpen(!isOpen);\n };\n\n return (\n <div\n data-re-link-selector=\"\"\n {...(isOpen ? { 'data-open': '' } : {})}\n {...(editorState.hasLink ? { 'data-has-link': '' } : {})}\n className={className}\n >\n {showToggle && (\n <button\n type=\"button\"\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n aria-label=\"Add link\"\n aria-pressed={editorState.isLinkActive && editorState.hasLink}\n data-re-link-selector-trigger=\"\"\n onClick={handleOpenLink}\n >\n <LinkIcon />\n </button>\n )}\n {isOpen && (\n <LinkForm\n editor={editor}\n currentHref={editorState.currentHref}\n validateUrl={validateUrl}\n onLinkApply={onLinkApply}\n onLinkRemove={onLinkRemove}\n setIsOpen={setIsOpen}\n >\n {children}\n </LinkForm>\n )}\n </div>\n );\n}\n\ninterface LinkFormProps {\n editor: Editor;\n currentHref: string;\n validateUrl?: (value: string) => string | null;\n onLinkApply?: (href: string) => void;\n onLinkRemove?: () => void;\n setIsOpen: (state: boolean) => void;\n children?: React.ReactNode;\n}\n\nfunction LinkForm({\n editor,\n currentHref,\n validateUrl,\n onLinkApply,\n onLinkRemove,\n setIsOpen,\n children,\n}: LinkFormProps) {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const formRef = React.useRef<HTMLFormElement>(null);\n const displayHref = currentHref === '#' ? '' : currentHref;\n const [inputValue, setInputValue] = React.useState(displayHref);\n\n React.useEffect(() => {\n const timeoutId = setTimeout(() => {\n inputRef.current?.focus();\n }, 0);\n return () => clearTimeout(timeoutId);\n }, []);\n\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n if (editor.getAttributes('link').href === '#') {\n editor.chain().unsetLink().run();\n }\n setIsOpen(false);\n }\n };\n\n const handleClickOutside = (event: MouseEvent) => {\n if (formRef.current && !formRef.current.contains(event.target as Node)) {\n const form = formRef.current;\n const submitEvent = new Event('submit', {\n bubbles: true,\n cancelable: true,\n });\n form.dispatchEvent(submitEvent);\n setIsOpen(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [editor, setIsOpen]);\n\n function handleSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault();\n\n const value = inputValue.trim();\n\n if (value === '') {\n setLinkHref(editor, '');\n setIsOpen(false);\n focusEditor(editor);\n onLinkRemove?.();\n return;\n }\n\n const validate = validateUrl ?? getUrlFromString;\n const finalValue = validate(value);\n\n if (!finalValue) {\n setLinkHref(editor, '');\n setIsOpen(false);\n focusEditor(editor);\n onLinkRemove?.();\n return;\n }\n\n setLinkHref(editor, finalValue);\n setIsOpen(false);\n focusEditor(editor);\n onLinkApply?.(finalValue);\n }\n\n function handleUnlink(e: React.MouseEvent) {\n e.stopPropagation();\n setLinkHref(editor, '');\n setIsOpen(false);\n focusEditor(editor);\n onLinkRemove?.();\n }\n\n return (\n <form\n ref={formRef}\n data-re-link-selector-form=\"\"\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n onSubmit={handleSubmit}\n >\n <input\n ref={inputRef}\n data-re-link-selector-input=\"\"\n value={inputValue}\n onFocus={(e) => e.stopPropagation()}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder=\"Paste a link\"\n type=\"text\"\n />\n\n {children}\n\n {displayHref ? (\n <button\n type=\"button\"\n aria-label=\"Remove link\"\n data-re-link-selector-unlink=\"\"\n onClick={handleUnlink}\n >\n <UnlinkIcon />\n </button>\n ) : (\n <button\n type=\"submit\"\n aria-label=\"Apply link\"\n data-re-link-selector-apply=\"\"\n onMouseDown={(e) => e.stopPropagation()}\n >\n <Check />\n </button>\n )}\n </form>\n );\n}\n","import * as Popover from '@radix-ui/react-popover';\nimport { useEditorState } from '@tiptap/react';\nimport {\n Check,\n ChevronDown,\n Code,\n Heading1,\n Heading2,\n Heading3,\n List,\n ListOrdered,\n TextIcon,\n TextQuote,\n} from 'lucide-react';\nimport * as React from 'react';\nimport { useBubbleMenuContext } from './context';\n\nexport type NodeType =\n | 'Text'\n | 'Title'\n | 'Subtitle'\n | 'Heading'\n | 'Bullet List'\n | 'Numbered List'\n | 'Quote'\n | 'Code';\n\nexport interface NodeSelectorItem {\n name: NodeType;\n icon: React.ComponentType<React.SVGAttributes<SVGSVGElement>>;\n command: () => void;\n isActive: boolean;\n}\n\ninterface NodeSelectorContextValue {\n items: NodeSelectorItem[];\n activeItem: NodeSelectorItem | { name: 'Multiple' };\n isOpen: boolean;\n setIsOpen: (value: boolean) => void;\n}\n\nconst NodeSelectorContext =\n React.createContext<NodeSelectorContextValue | null>(null);\n\nfunction useNodeSelectorContext(): NodeSelectorContextValue {\n const context = React.useContext(NodeSelectorContext);\n if (!context) {\n throw new Error(\n 'NodeSelector compound components must be used within <NodeSelector.Root>',\n );\n }\n return context;\n}\n\nexport interface NodeSelectorRootProps {\n /** Block types to exclude */\n omit?: string[];\n /** Controlled open state */\n open?: boolean;\n /** Called when open state changes */\n onOpenChange?: (open: boolean) => void;\n className?: string;\n children: React.ReactNode;\n}\n\nexport function NodeSelectorRoot({\n omit = [],\n open: controlledOpen,\n onOpenChange,\n className,\n children,\n}: NodeSelectorRootProps) {\n const { editor } = useBubbleMenuContext();\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);\n\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n const setIsOpen = React.useCallback(\n (value: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(value);\n }\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n const editorState = useEditorState({\n editor,\n selector: ({ editor }) => ({\n isParagraphActive:\n (editor?.isActive('paragraph') ?? false) &&\n !editor?.isActive('bulletList') &&\n !editor?.isActive('orderedList'),\n isHeading1Active: editor?.isActive('heading', { level: 1 }) ?? false,\n isHeading2Active: editor?.isActive('heading', { level: 2 }) ?? false,\n isHeading3Active: editor?.isActive('heading', { level: 3 }) ?? false,\n isBulletListActive: editor?.isActive('bulletList') ?? false,\n isOrderedListActive: editor?.isActive('orderedList') ?? false,\n isBlockquoteActive: editor?.isActive('blockquote') ?? false,\n isCodeBlockActive: editor?.isActive('codeBlock') ?? false,\n }),\n });\n\n const allItems: NodeSelectorItem[] = React.useMemo(\n () => [\n {\n name: 'Text' as const,\n icon: TextIcon,\n command: () =>\n editor\n .chain()\n .focus()\n .clearNodes()\n .toggleNode('paragraph', 'paragraph')\n .run(),\n isActive: editorState?.isParagraphActive ?? false,\n },\n {\n name: 'Title' as const,\n icon: Heading1,\n command: () =>\n editor.chain().focus().clearNodes().toggleHeading({ level: 1 }).run(),\n isActive: editorState?.isHeading1Active ?? false,\n },\n {\n name: 'Subtitle' as const,\n icon: Heading2,\n command: () =>\n editor.chain().focus().clearNodes().toggleHeading({ level: 2 }).run(),\n isActive: editorState?.isHeading2Active ?? false,\n },\n {\n name: 'Heading' as const,\n icon: Heading3,\n command: () =>\n editor.chain().focus().clearNodes().toggleHeading({ level: 3 }).run(),\n isActive: editorState?.isHeading3Active ?? false,\n },\n {\n name: 'Bullet List' as const,\n icon: List,\n command: () =>\n editor.chain().focus().clearNodes().toggleBulletList().run(),\n isActive: editorState?.isBulletListActive ?? false,\n },\n {\n name: 'Numbered List' as const,\n icon: ListOrdered,\n command: () =>\n editor.chain().focus().clearNodes().toggleOrderedList().run(),\n isActive: editorState?.isOrderedListActive ?? false,\n },\n {\n name: 'Quote' as const,\n icon: TextQuote,\n command: () =>\n editor\n .chain()\n .focus()\n .clearNodes()\n .toggleNode('paragraph', 'paragraph')\n .toggleBlockquote()\n .run(),\n isActive: editorState?.isBlockquoteActive ?? false,\n },\n {\n name: 'Code' as const,\n icon: Code,\n command: () =>\n editor.chain().focus().clearNodes().toggleCodeBlock().run(),\n isActive: editorState?.isCodeBlockActive ?? false,\n },\n ],\n [editor, editorState],\n );\n\n const items = React.useMemo(\n () => allItems.filter((item) => !omit.includes(item.name)),\n [allItems, omit],\n );\n\n const activeItem = React.useMemo(\n () =>\n items.find((item) => item.isActive) ?? {\n name: 'Multiple' as const,\n },\n [items],\n );\n\n const contextValue = React.useMemo(\n () => ({ items, activeItem, isOpen, setIsOpen }),\n [items, activeItem, isOpen, setIsOpen],\n );\n\n if (!editorState || items.length === 0) {\n return null;\n }\n\n return (\n <NodeSelectorContext.Provider value={contextValue}>\n <Popover.Root open={isOpen} onOpenChange={setIsOpen}>\n <div\n data-re-node-selector=\"\"\n {...(isOpen ? { 'data-open': '' } : {})}\n className={className}\n >\n {children}\n </div>\n </Popover.Root>\n </NodeSelectorContext.Provider>\n );\n}\n\nexport interface NodeSelectorTriggerProps {\n className?: string;\n children?: React.ReactNode;\n}\n\nexport function NodeSelectorTrigger({\n className,\n children,\n}: NodeSelectorTriggerProps) {\n const { activeItem, isOpen, setIsOpen } = useNodeSelectorContext();\n\n return (\n <Popover.Trigger\n data-re-node-selector-trigger=\"\"\n className={className}\n onClick={() => setIsOpen(!isOpen)}\n >\n {children ?? (\n <>\n <span>{activeItem.name}</span>\n <ChevronDown />\n </>\n )}\n </Popover.Trigger>\n );\n}\n\nexport interface NodeSelectorContentProps {\n className?: string;\n /** Popover alignment (default: \"start\") */\n align?: 'start' | 'center' | 'end';\n /** Render-prop for full control over item rendering.\n * Receives the filtered items and a `close` function to dismiss the popover. */\n children?: (items: NodeSelectorItem[], close: () => void) => React.ReactNode;\n}\n\nexport function NodeSelectorContent({\n className,\n align = 'start',\n children,\n}: NodeSelectorContentProps) {\n const { items, setIsOpen } = useNodeSelectorContext();\n\n return (\n <Popover.Content\n align={align}\n data-re-node-selector-content=\"\"\n className={className}\n >\n {children\n ? children(items, () => setIsOpen(false))\n : items.map((item) => {\n const Icon = item.icon;\n return (\n <button\n key={item.name}\n type=\"button\"\n data-re-node-selector-item=\"\"\n {...(item.isActive ? { 'data-active': '' } : {})}\n onClick={() => {\n item.command();\n setIsOpen(false);\n }}\n >\n <Icon />\n <span>{item.name}</span>\n {item.isActive && <Check />}\n </button>\n );\n })}\n </Popover.Content>\n );\n}\n\nexport interface BubbleMenuNodeSelectorProps {\n /** Block types to exclude */\n omit?: string[];\n className?: string;\n /** Override the trigger content (default: active item name + chevron icon) */\n triggerContent?: React.ReactNode;\n /** Controlled open state */\n open?: boolean;\n /** Called when open state changes */\n onOpenChange?: (open: boolean) => void;\n}\n\nexport function BubbleMenuNodeSelector({\n omit = [],\n className,\n triggerContent,\n open,\n onOpenChange,\n}: BubbleMenuNodeSelectorProps) {\n return (\n <NodeSelectorRoot\n omit={omit}\n open={open}\n onOpenChange={onOpenChange}\n className={className}\n >\n <NodeSelectorTrigger>{triggerContent}</NodeSelectorTrigger>\n <NodeSelectorContent />\n </NodeSelectorRoot>\n );\n}\n","import { useCurrentEditor } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport type * as React from 'react';\nimport { BubbleMenuContext } from './context';\n\nexport interface BubbleMenuRootProps {\n /** Node types that should NOT trigger the bubble menu */\n excludeNodes?: string[];\n /** Placement relative to selection */\n placement?: 'top' | 'bottom';\n /** Offset from selection in px */\n offset?: number;\n /** Called when the bubble menu is hidden (e.g., click outside, selection cleared) */\n onHide?: () => void;\n /** Additional className on the outer wrapper */\n className?: string;\n children: React.ReactNode;\n}\n\nexport function BubbleMenuRoot({\n excludeNodes = [],\n placement = 'bottom',\n offset = 8,\n onHide,\n className,\n children,\n}: BubbleMenuRootProps) {\n const { editor } = useCurrentEditor();\n\n if (!editor) {\n return null;\n }\n\n return (\n <BubbleMenu\n editor={editor}\n data-re-bubble-menu=\"\"\n shouldShow={({ editor, view }) => {\n for (const node of excludeNodes) {\n if (editor.isActive(node)) {\n return false;\n }\n }\n if (view.dom.classList.contains('dragging')) {\n return false;\n }\n return editor.view.state.selection.content().size > 0;\n }}\n options={{\n placement,\n offset,\n onHide,\n }}\n className={className}\n >\n <BubbleMenuContext.Provider value={{ editor }}>\n {children}\n </BubbleMenuContext.Provider>\n </BubbleMenu>\n );\n}\n","import { StrikethroughIcon } from 'lucide-react';\nimport { createMarkBubbleItem } from './create-mark-bubble-item';\n\nexport const BubbleMenuStrike = createMarkBubbleItem({\n name: 'strike',\n activeName: 'strike',\n command: 'toggleStrike',\n icon: <StrikethroughIcon />,\n});\n","import { UnderlineIcon } from 'lucide-react';\nimport { createMarkBubbleItem } from './create-mark-bubble-item';\n\nexport const BubbleMenuUnderline = createMarkBubbleItem({\n name: 'underline',\n activeName: 'underline',\n command: 'toggleUnderline',\n icon: <UnderlineIcon />,\n});\n","import { CaseUpperIcon } from 'lucide-react';\nimport { createMarkBubbleItem } from './create-mark-bubble-item';\n\nexport const BubbleMenuUppercase = createMarkBubbleItem({\n name: 'uppercase',\n activeName: 'uppercase',\n command: 'toggleUppercase',\n icon: <CaseUpperIcon />,\n});\n","import * as React from 'react';\nimport { BubbleMenuAlignCenter } from './align-center';\nimport { BubbleMenuAlignLeft } from './align-left';\nimport { BubbleMenuAlignRight } from './align-right';\nimport { BubbleMenuBold } from './bold';\nimport { BubbleMenuCode } from './code';\nimport { BubbleMenuItemGroup } from './group';\nimport { BubbleMenuItalic } from './italic';\nimport { BubbleMenuLinkSelector } from './link-selector';\nimport { BubbleMenuNodeSelector } from './node-selector';\nimport { BubbleMenuRoot } from './root';\nimport { BubbleMenuStrike } from './strike';\nimport { BubbleMenuUnderline } from './underline';\nimport { BubbleMenuUppercase } from './uppercase';\n\ntype ExcludableItem =\n | 'bold'\n | 'italic'\n | 'underline'\n | 'strike'\n | 'code'\n | 'uppercase'\n | 'align-left'\n | 'align-center'\n | 'align-right'\n | 'node-selector'\n | 'link-selector';\n\nexport interface BubbleMenuDefaultProps {\n /** Items to exclude from the default layout */\n excludeItems?: ExcludableItem[];\n /** Node types that should NOT trigger the bubble menu (forwarded to Root) */\n excludeNodes?: string[];\n /** Placement relative to selection (forwarded to Root, default: 'bottom') */\n placement?: 'top' | 'bottom';\n /** Offset from selection in px (forwarded to Root, default: 8) */\n offset?: number;\n /** Called when the bubble menu hides (forwarded to Root) */\n onHide?: () => void;\n /** className applied to the Root wrapper */\n className?: string;\n}\n\nexport function BubbleMenuDefault({\n excludeItems = [],\n excludeNodes,\n placement,\n offset,\n onHide,\n className,\n}: BubbleMenuDefaultProps) {\n const [isNodeSelectorOpen, setIsNodeSelectorOpen] = React.useState(false);\n const [isLinkSelectorOpen, setIsLinkSelectorOpen] = React.useState(false);\n\n const has = (item: ExcludableItem) => !excludeItems.includes(item);\n\n const handleNodeSelectorOpenChange = React.useCallback((open: boolean) => {\n setIsNodeSelectorOpen(open);\n if (open) {\n setIsLinkSelectorOpen(false);\n }\n }, []);\n\n const handleLinkSelectorOpenChange = React.useCallback((open: boolean) => {\n setIsLinkSelectorOpen(open);\n if (open) {\n setIsNodeSelectorOpen(false);\n }\n }, []);\n\n const handleHide = React.useCallback(() => {\n setIsNodeSelectorOpen(false);\n setIsLinkSelectorOpen(false);\n onHide?.();\n }, [onHide]);\n\n const hasFormattingItems =\n has('bold') ||\n has('italic') ||\n has('underline') ||\n has('strike') ||\n has('code') ||\n has('uppercase');\n\n const hasAlignmentItems =\n has('align-left') || has('align-center') || has('align-right');\n\n return (\n <BubbleMenuRoot\n excludeNodes={excludeNodes}\n placement={placement}\n offset={offset}\n onHide={handleHide}\n className={className}\n >\n {has('node-selector') && (\n <BubbleMenuNodeSelector\n open={isNodeSelectorOpen}\n onOpenChange={handleNodeSelectorOpenChange}\n />\n )}\n {has('link-selector') && (\n <BubbleMenuLinkSelector\n open={isLinkSelectorOpen}\n onOpenChange={handleLinkSelectorOpenChange}\n />\n )}\n {hasFormattingItems && (\n <BubbleMenuItemGroup>\n {has('bold') && <BubbleMenuBold />}\n {has('italic') && <BubbleMenuItalic />}\n {has('underline') && <BubbleMenuUnderline />}\n {has('strike') && <BubbleMenuStrike />}\n {has('code') && <BubbleMenuCode />}\n {has('uppercase') && <BubbleMenuUppercase />}\n </BubbleMenuItemGroup>\n )}\n {hasAlignmentItems && (\n <BubbleMenuItemGroup>\n {has('align-left') && <BubbleMenuAlignLeft />}\n {has('align-center') && <BubbleMenuAlignCenter />}\n {has('align-right') && <BubbleMenuAlignRight />}\n </BubbleMenuItemGroup>\n )}\n </BubbleMenuRoot>\n );\n}\n","export interface BubbleMenuSeparatorProps {\n className?: string;\n}\n\nexport function BubbleMenuSeparator({ className }: BubbleMenuSeparatorProps) {\n return <hr className={className} data-re-bubble-menu-separator=\"\" />;\n}\n","import { BubbleMenuAlignCenter } from './align-center';\nimport { BubbleMenuAlignLeft } from './align-left';\nimport { BubbleMenuAlignRight } from './align-right';\nimport { BubbleMenuBold } from './bold';\nimport { BubbleMenuCode } from './code';\nimport { BubbleMenuDefault } from './default';\nimport { BubbleMenuItemGroup } from './group';\nimport { BubbleMenuItalic } from './italic';\nimport { BubbleMenuItem } from './item';\nimport { BubbleMenuLinkSelector } from './link-selector';\nimport {\n BubbleMenuNodeSelector,\n NodeSelectorContent,\n NodeSelectorRoot,\n NodeSelectorTrigger,\n} from './node-selector';\nimport { BubbleMenuRoot } from './root';\nimport { BubbleMenuSeparator } from './separator';\nimport { BubbleMenuStrike } from './strike';\nimport { BubbleMenuUnderline } from './underline';\nimport { BubbleMenuUppercase } from './uppercase';\n\nexport { BubbleMenuAlignCenter } from './align-center';\nexport { BubbleMenuAlignLeft } from './align-left';\nexport { BubbleMenuAlignRight } from './align-right';\nexport { BubbleMenuBold } from './bold';\nexport { BubbleMenuCode } from './code';\nexport type { PreWiredItemProps } from './create-mark-bubble-item';\nexport type { BubbleMenuDefaultProps } from './default';\nexport { BubbleMenuDefault } from './default';\nexport type { BubbleMenuItemGroupProps } from './group';\nexport { BubbleMenuItemGroup } from './group';\nexport { BubbleMenuItalic } from './italic';\nexport type { BubbleMenuItemProps } from './item';\nexport { BubbleMenuItem } from './item';\nexport type { BubbleMenuLinkSelectorProps } from './link-selector';\nexport { BubbleMenuLinkSelector } from './link-selector';\nexport type {\n BubbleMenuNodeSelectorProps,\n NodeSelectorContentProps,\n NodeSelectorItem,\n NodeSelectorRootProps,\n NodeSelectorTriggerProps,\n NodeType,\n} from './node-selector';\nexport {\n BubbleMenuNodeSelector,\n NodeSelectorContent,\n NodeSelectorRoot,\n NodeSelectorTrigger,\n} from './node-selector';\nexport type { BubbleMenuRootProps } from './root';\nexport { BubbleMenuRoot } from './root';\nexport type { BubbleMenuSeparatorProps } from './separator';\nexport { BubbleMenuSeparator } from './separator';\nexport { BubbleMenuStrike } from './strike';\nexport { BubbleMenuUnderline } from './underline';\nexport { BubbleMenuUppercase } from './uppercase';\n\n// Compound component namespace for convenient `BubbleMenu.Root` usage\nexport const BubbleMenu = {\n Root: BubbleMenuRoot,\n ItemGroup: BubbleMenuItemGroup,\n Separator: BubbleMenuSeparator,\n Item: BubbleMenuItem,\n Bold: BubbleMenuBold,\n Italic: BubbleMenuItalic,\n Underline: BubbleMenuUnderline,\n Strike: BubbleMenuStrike,\n Code: BubbleMenuCode,\n Uppercase: BubbleMenuUppercase,\n AlignLeft: BubbleMenuAlignLeft,\n AlignCenter: BubbleMenuAlignCenter,\n AlignRight: BubbleMenuAlignRight,\n NodeSelector: Object.assign(BubbleMenuNodeSelector, {\n Root: NodeSelectorRoot,\n Trigger: NodeSelectorTrigger,\n Content: NodeSelectorContent,\n }),\n LinkSelector: BubbleMenuLinkSelector,\n Default: BubbleMenuDefault,\n} as const;\n","import type { Editor } from '@tiptap/core';\nimport * as React from 'react';\n\nexport interface ButtonBubbleMenuContextValue {\n editor: Editor;\n isEditing: boolean;\n setIsEditing: (value: boolean) => void;\n}\n\nexport const ButtonBubbleMenuContext =\n React.createContext<ButtonBubbleMenuContextValue | null>(null);\n\nexport function useButtonBubbleMenuContext(): ButtonBubbleMenuContextValue {\n const context = React.useContext(ButtonBubbleMenuContext);\n if (!context) {\n throw new Error(\n 'ButtonBubbleMenu compound components must be used within <ButtonBubbleMenu.Root>',\n );\n }\n return context;\n}\n","import { LinkIcon } from 'lucide-react';\nimport type * as React from 'react';\nimport { useButtonBubbleMenuContext } from './context';\n\nexport interface ButtonBubbleMenuEditLinkProps\n extends Omit<React.ComponentProps<'button'>, 'type'> {}\n\nexport function ButtonBubbleMenuEditLink({\n className,\n children,\n onClick,\n onMouseDown,\n ...rest\n}: ButtonBubbleMenuEditLinkProps) {\n const { setIsEditing } = useButtonBubbleMenuContext();\n\n return (\n <button\n {...rest}\n type=\"button\"\n aria-label=\"Edit link\"\n data-re-btn-bm-item=\"\"\n data-item=\"edit-link\"\n className={className}\n onMouseDown={(e) => {\n e.preventDefault();\n onMouseDown?.(e);\n }}\n onClick={(e) => {\n onClick?.(e);\n setIsEditing(true);\n }}\n >\n {children ?? <LinkIcon />}\n </button>\n );\n}\n","import { useCurrentEditor } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport * as React from 'react';\nimport { ButtonBubbleMenuContext } from './context';\n\nexport interface ButtonBubbleMenuRootProps {\n /** Called when the bubble menu hides */\n onHide?: () => void;\n /** Placement relative to cursor (default: 'top') */\n placement?: 'top' | 'bottom';\n /** Offset from cursor in px (default: 8) */\n offset?: number;\n /** className on the outer wrapper */\n className?: string;\n children: React.ReactNode;\n}\n\nexport function ButtonBubbleMenuRoot({\n onHide,\n placement = 'top',\n offset = 8,\n className,\n children,\n}: ButtonBubbleMenuRootProps) {\n const { editor } = useCurrentEditor();\n const [isEditing, setIsEditing] = React.useState(false);\n\n if (!editor) {\n return null;\n }\n\n return (\n <BubbleMenu\n editor={editor}\n data-re-btn-bm=\"\"\n shouldShow={({ editor: e, view }) =>\n e.isActive('button') && !view.dom.classList.contains('dragging')\n }\n options={{\n placement,\n offset,\n onHide: () => {\n setIsEditing(false);\n onHide?.();\n },\n }}\n className={className}\n >\n <ButtonBubbleMenuContext.Provider\n value={{ editor, isEditing, setIsEditing }}\n >\n {children}\n </ButtonBubbleMenuContext.Provider>\n </BubbleMenu>\n );\n}\n","import type * as React from 'react';\nimport { useButtonBubbleMenuContext } from './context';\n\nexport interface ButtonBubbleMenuToolbarProps\n extends React.ComponentProps<'div'> {}\n\nexport function ButtonBubbleMenuToolbar({\n children,\n ...rest\n}: ButtonBubbleMenuToolbarProps) {\n const { isEditing } = useButtonBubbleMenuContext();\n\n if (isEditing) {\n return null;\n }\n\n return (\n <div data-re-btn-bm-toolbar=\"\" {...rest}>\n {children}\n </div>\n );\n}\n","import { ButtonBubbleMenuEditLink } from './edit-link';\nimport { ButtonBubbleMenuRoot } from './root';\nimport { ButtonBubbleMenuToolbar } from './toolbar';\n\ntype ExcludableItem = 'edit-link';\n\nexport interface ButtonBubbleMenuDefaultProps {\n excludeItems?: ExcludableItem[];\n placement?: 'top' | 'bottom';\n offset?: number;\n onHide?: () => void;\n className?: string;\n}\n\nexport function ButtonBubbleMenuDefault({\n excludeItems = [],\n placement,\n offset,\n onHide,\n className,\n}: ButtonBubbleMenuDefaultProps) {\n const hasEditLink = !excludeItems.includes('edit-link');\n\n return (\n <ButtonBubbleMenuRoot\n placement={placement}\n offset={offset}\n onHide={onHide}\n className={className}\n >\n {hasEditLink && (\n <ButtonBubbleMenuToolbar>\n <ButtonBubbleMenuEditLink />\n </ButtonBubbleMenuToolbar>\n )}\n </ButtonBubbleMenuRoot>\n );\n}\n","import { ButtonBubbleMenuDefault } from './default';\nimport { ButtonBubbleMenuEditLink } from './edit-link';\nimport { ButtonBubbleMenuRoot } from './root';\nimport { ButtonBubbleMenuToolbar } from './toolbar';\n\nexport { useButtonBubbleMenuContext } from './context';\nexport type { ButtonBubbleMenuDefaultProps } from './default';\nexport { ButtonBubbleMenuDefault } from './default';\nexport type { ButtonBubbleMenuEditLinkProps } from './edit-link';\nexport { ButtonBubbleMenuEditLink } from './edit-link';\nexport type { ButtonBubbleMenuRootProps } from './root';\nexport { ButtonBubbleMenuRoot } from './root';\nexport type { ButtonBubbleMenuToolbarProps } from './toolbar';\nexport { ButtonBubbleMenuToolbar } from './toolbar';\n\nexport const ButtonBubbleMenu = {\n Root: ButtonBubbleMenuRoot,\n Toolbar: ButtonBubbleMenuToolbar,\n EditLink: ButtonBubbleMenuEditLink,\n Default: ButtonBubbleMenuDefault,\n} as const;\n","import type { Editor } from '@tiptap/core';\nimport * as React from 'react';\n\nexport interface ImageBubbleMenuContextValue {\n editor: Editor;\n isEditing: boolean;\n setIsEditing: (value: boolean) => void;\n}\n\nexport const ImageBubbleMenuContext =\n React.createContext<ImageBubbleMenuContextValue | null>(null);\n\nexport function useImageBubbleMenuContext(): ImageBubbleMenuContextValue {\n const context = React.useContext(ImageBubbleMenuContext);\n if (!context) {\n throw new Error(\n 'ImageBubbleMenu compound components must be used within <ImageBubbleMenu.Root>',\n );\n }\n return context;\n}\n","import { LinkIcon } from 'lucide-react';\nimport type * as React from 'react';\nimport { useImageBubbleMenuContext } from './context';\n\nexport interface ImageBubbleMenuEditLinkProps\n extends Omit<React.ComponentProps<'button'>, 'type'> {}\n\nexport function ImageBubbleMenuEditLink({\n className,\n children,\n onClick,\n onMouseDown,\n ...rest\n}: ImageBubbleMenuEditLinkProps) {\n const { setIsEditing } = useImageBubbleMenuContext();\n\n return (\n <button\n {...rest}\n type=\"button\"\n aria-label=\"Edit link\"\n data-re-img-bm-item=\"\"\n data-item=\"edit-link\"\n className={className}\n onMouseDown={(e) => {\n e.preventDefault();\n onMouseDown?.(e);\n }}\n onClick={(e) => {\n onClick?.(e);\n setIsEditing(true);\n }}\n >\n {children ?? <LinkIcon />}\n </button>\n );\n}\n","import { useCurrentEditor } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport * as React from 'react';\nimport { ImageBubbleMenuContext } from './context';\n\nexport interface ImageBubbleMenuRootProps {\n /** Called when the bubble menu hides */\n onHide?: () => void;\n /** Placement relative to cursor (default: 'top') */\n placement?: 'top' | 'bottom';\n /** Offset from cursor in px (default: 8) */\n offset?: number;\n /** className on the outer wrapper */\n className?: string;\n children: React.ReactNode;\n}\n\nexport function ImageBubbleMenuRoot({\n onHide,\n placement = 'top',\n offset = 8,\n className,\n children,\n}: ImageBubbleMenuRootProps) {\n const { editor } = useCurrentEditor();\n const [isEditing, setIsEditing] = React.useState(false);\n\n if (!editor) {\n return null;\n }\n\n return (\n <BubbleMenu\n editor={editor}\n data-re-img-bm=\"\"\n shouldShow={({ editor: e, view }) =>\n e.isActive('image') && !view.dom.classList.contains('dragging')\n }\n options={{\n placement,\n offset,\n onHide: () => {\n setIsEditing(false);\n onHide?.();\n },\n }}\n className={className}\n >\n <ImageBubbleMenuContext.Provider\n value={{ editor, isEditing, setIsEditing }}\n >\n {children}\n </ImageBubbleMenuContext.Provider>\n </BubbleMenu>\n );\n}\n","import type * as React from 'react';\nimport { useImageBubbleMenuContext } from './context';\n\nexport interface ImageBubbleMenuToolbarProps\n extends React.ComponentProps<'div'> {}\n\nexport function ImageBubbleMenuToolbar({\n children,\n ...rest\n}: ImageBubbleMenuToolbarProps) {\n const { isEditing } = useImageBubbleMenuContext();\n\n if (isEditing) {\n return null;\n }\n\n return (\n <div data-re-img-bm-toolbar=\"\" {...rest}>\n {children}\n </div>\n );\n}\n","import { ImageBubbleMenuEditLink } from './edit-link';\nimport { ImageBubbleMenuRoot } from './root';\nimport { ImageBubbleMenuToolbar } from './toolbar';\n\ntype ExcludableItem = 'edit-link';\n\nexport interface ImageBubbleMenuDefaultProps {\n excludeItems?: ExcludableItem[];\n placement?: 'top' | 'bottom';\n offset?: number;\n onHide?: () => void;\n className?: string;\n}\n\nexport function ImageBubbleMenuDefault({\n excludeItems = [],\n placement,\n offset,\n onHide,\n className,\n}: ImageBubbleMenuDefaultProps) {\n const hasEditLink = !excludeItems.includes('edit-link');\n\n return (\n <ImageBubbleMenuRoot\n placement={placement}\n offset={offset}\n onHide={onHide}\n className={className}\n >\n {hasEditLink && (\n <ImageBubbleMenuToolbar>\n <ImageBubbleMenuEditLink />\n </ImageBubbleMenuToolbar>\n )}\n </ImageBubbleMenuRoot>\n );\n}\n","import { ImageBubbleMenuDefault } from './default';\nimport { ImageBubbleMenuEditLink } from './edit-link';\nimport { ImageBubbleMenuRoot } from './root';\nimport { ImageBubbleMenuToolbar } from './toolbar';\n\nexport { useImageBubbleMenuContext } from './context';\nexport type { ImageBubbleMenuDefaultProps } from './default';\nexport { ImageBubbleMenuDefault } from './default';\nexport type { ImageBubbleMenuEditLinkProps } from './edit-link';\nexport { ImageBubbleMenuEditLink } from './edit-link';\nexport type { ImageBubbleMenuRootProps } from './root';\nexport { ImageBubbleMenuRoot } from './root';\nexport type { ImageBubbleMenuToolbarProps } from './toolbar';\nexport { ImageBubbleMenuToolbar } from './toolbar';\n\nexport const ImageBubbleMenu = {\n Root: ImageBubbleMenuRoot,\n Toolbar: ImageBubbleMenuToolbar,\n EditLink: ImageBubbleMenuEditLink,\n Default: ImageBubbleMenuDefault,\n} as const;\n","import type { Editor } from '@tiptap/core';\nimport * as React from 'react';\n\nexport interface LinkBubbleMenuContextValue {\n editor: Editor;\n linkHref: string;\n isEditing: boolean;\n setIsEditing: (value: boolean) => void;\n}\n\nexport const LinkBubbleMenuContext =\n React.createContext<LinkBubbleMenuContextValue | null>(null);\n\nexport function useLinkBubbleMenuContext(): LinkBubbleMenuContextValue {\n const context = React.useContext(LinkBubbleMenuContext);\n if (!context) {\n throw new Error(\n 'LinkBubbleMenu compound components must be used within <LinkBubbleMenu.Root>',\n );\n }\n return context;\n}\n","import { PencilIcon } from 'lucide-react';\nimport type * as React from 'react';\nimport { useLinkBubbleMenuContext } from './context';\n\nexport interface LinkBubbleMenuEditLinkProps\n extends Omit<React.ComponentProps<'button'>, 'type'> {}\n\nexport function LinkBubbleMenuEditLink({\n className,\n children,\n onClick,\n onMouseDown,\n ...rest\n}: LinkBubbleMenuEditLinkProps) {\n const { setIsEditing } = useLinkBubbleMenuContext();\n\n return (\n <button\n type=\"button\"\n aria-label=\"Edit link\"\n data-re-link-bm-item=\"\"\n data-item=\"edit-link\"\n className={className}\n onMouseDown={(e) => {\n e.preventDefault();\n onMouseDown?.(e);\n }}\n onClick={(e) => {\n onClick?.(e);\n setIsEditing(true);\n }}\n {...rest}\n >\n {children ?? <PencilIcon />}\n </button>\n );\n}\n","import { Check, UnlinkIcon } from 'lucide-react';\nimport * as React from 'react';\nimport {\n focusEditor,\n getUrlFromString,\n setLinkHref,\n} from '../bubble-menu/utils';\nimport { useLinkBubbleMenuContext } from './context';\n\nexport interface LinkBubbleMenuFormProps {\n className?: string;\n /** Custom URL validator (default: getUrlFromString) */\n validateUrl?: (value: string) => string | null;\n /** Called after link is applied */\n onLinkApply?: (href: string) => void;\n /** Called after link is removed */\n onLinkRemove?: () => void;\n /** Extra content inside the form (e.g. a variables dropdown slot) */\n children?: React.ReactNode;\n}\n\nexport function LinkBubbleMenuForm({\n className,\n validateUrl,\n onLinkApply,\n onLinkRemove,\n children,\n}: LinkBubbleMenuFormProps) {\n const { editor, linkHref, isEditing, setIsEditing } =\n useLinkBubbleMenuContext();\n const inputRef = React.useRef<HTMLInputElement>(null);\n const formRef = React.useRef<HTMLFormElement>(null);\n const displayHref = linkHref === '#' ? '' : linkHref;\n const [inputValue, setInputValue] = React.useState(displayHref);\n\n React.useEffect(() => {\n if (!isEditing) {\n return;\n }\n const timeoutId = setTimeout(() => {\n inputRef.current?.focus();\n }, 0);\n return () => clearTimeout(timeoutId);\n }, [isEditing]);\n\n React.useEffect(() => {\n if (!isEditing) {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsEditing(false);\n }\n };\n\n const handleClickOutside = (event: MouseEvent) => {\n if (formRef.current && !formRef.current.contains(event.target as Node)) {\n const form = formRef.current;\n const submitEvent = new Event('submit', {\n bubbles: true,\n cancelable: true,\n });\n form.dispatchEvent(submitEvent);\n setIsEditing(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isEditing, setIsEditing]);\n\n if (!isEditing) {\n return null;\n }\n\n function handleSubmit(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault();\n\n const value = inputValue.trim();\n\n if (value === '') {\n setLinkHref(editor, '');\n setIsEditing(false);\n focusEditor(editor);\n onLinkRemove?.();\n return;\n }\n\n const validate = validateUrl ?? getUrlFromString;\n const finalValue = validate(value);\n\n if (!finalValue) {\n setLinkHref(editor, '');\n setIsEditing(false);\n focusEditor(editor);\n onLinkRemove?.();\n return;\n }\n\n setLinkHref(editor, finalValue);\n setIsEditing(false);\n focusEditor(editor);\n onLinkApply?.(finalValue);\n }\n\n function handleUnlink(e: React.MouseEvent) {\n e.stopPropagation();\n setLinkHref(editor, '');\n setIsEditing(false);\n focusEditor(editor);\n onLinkRemove?.();\n }\n\n return (\n <form\n ref={formRef}\n data-re-link-bm-form=\"\"\n className={className}\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n onSubmit={handleSubmit}\n >\n <input\n ref={inputRef}\n data-re-link-bm-input=\"\"\n value={inputValue}\n onFocus={(e) => e.stopPropagation()}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder=\"Paste a link\"\n type=\"text\"\n />\n\n {children}\n\n {displayHref ? (\n <button\n type=\"button\"\n aria-label=\"Remove link\"\n data-re-link-bm-unlink=\"\"\n onClick={handleUnlink}\n >\n <UnlinkIcon />\n </button>\n ) : (\n <button\n type=\"submit\"\n aria-label=\"Apply link\"\n data-re-link-bm-apply=\"\"\n onMouseDown={(e) => e.stopPropagation()}\n >\n <Check />\n </button>\n )}\n </form>\n );\n}\n","import { ExternalLinkIcon } from 'lucide-react';\nimport type * as React from 'react';\nimport { useLinkBubbleMenuContext } from './context';\n\nexport interface LinkBubbleMenuOpenLinkProps\n extends Omit<React.ComponentProps<'a'>, 'href' | 'target' | 'rel'> {}\n\nexport function LinkBubbleMenuOpenLink({\n className,\n children,\n ...rest\n}: LinkBubbleMenuOpenLinkProps) {\n const { linkHref } = useLinkBubbleMenuContext();\n\n return (\n <a\n {...rest}\n href={linkHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Open link\"\n data-re-link-bm-item=\"\"\n data-item=\"open-link\"\n className={className}\n >\n {children ?? <ExternalLinkIcon />}\n </a>\n );\n}\n","import { useCurrentEditor, useEditorState } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport * as React from 'react';\nimport { LinkBubbleMenuContext } from './context';\n\nexport interface LinkBubbleMenuRootProps {\n /** Called when the bubble menu hides */\n onHide?: () => void;\n /** Placement relative to cursor (default: 'top') */\n placement?: 'top' | 'bottom';\n /** Offset from cursor in px (default: 8) */\n offset?: number;\n /** className on the outer wrapper */\n className?: string;\n children: React.ReactNode;\n}\n\nexport function LinkBubbleMenuRoot({\n onHide,\n placement = 'top',\n offset = 8,\n className,\n children,\n}: LinkBubbleMenuRootProps) {\n const { editor } = useCurrentEditor();\n const [isEditing, setIsEditing] = React.useState(false);\n\n const linkHref = useEditorState({\n editor,\n selector: ({ editor: e }) =>\n (e?.getAttributes('link').href as string) ?? '',\n });\n\n if (!editor) {\n return null;\n }\n\n return (\n <BubbleMenu\n editor={editor}\n data-re-link-bm=\"\"\n shouldShow={({ editor: e }) =>\n e.isActive('link') && e.view.state.selection.content().size === 0\n }\n options={{\n placement,\n offset,\n onHide: () => {\n setIsEditing(false);\n onHide?.();\n },\n }}\n className={className}\n >\n <LinkBubbleMenuContext.Provider\n value={{ editor, linkHref: linkHref ?? '', isEditing, setIsEditing }}\n >\n {children}\n </LinkBubbleMenuContext.Provider>\n </BubbleMenu>\n );\n}\n","import type * as React from 'react';\nimport { useLinkBubbleMenuContext } from './context';\n\nexport interface LinkBubbleMenuToolbarProps\n extends React.ComponentProps<'div'> {}\n\nexport function LinkBubbleMenuToolbar({\n children,\n ...rest\n}: LinkBubbleMenuToolbarProps) {\n const { isEditing } = useLinkBubbleMenuContext();\n\n if (isEditing) {\n return null;\n }\n\n return (\n <div data-re-link-bm-toolbar=\"\" {...rest}>\n {children}\n </div>\n );\n}\n","import { UnlinkIcon } from 'lucide-react';\nimport type * as React from 'react';\nimport { useLinkBubbleMenuContext } from './context';\n\nexport interface LinkBubbleMenuUnlinkProps\n extends Omit<React.ComponentProps<'button'>, 'type'> {}\n\nexport function LinkBubbleMenuUnlink({\n className,\n children,\n onClick,\n onMouseDown,\n ...rest\n}: LinkBubbleMenuUnlinkProps) {\n const { editor } = useLinkBubbleMenuContext();\n\n return (\n <button\n type=\"button\"\n aria-label=\"Remove link\"\n data-re-link-bm-item=\"\"\n data-item=\"unlink\"\n className={className}\n onMouseDown={(e) => {\n e.preventDefault();\n onMouseDown?.(e);\n }}\n onClick={(e) => {\n onClick?.(e);\n editor.chain().focus().unsetLink().run();\n }}\n {...rest}\n >\n {children ?? <UnlinkIcon />}\n </button>\n );\n}\n","import { LinkBubbleMenuEditLink } from './edit-link';\nimport { LinkBubbleMenuForm } from './form';\nimport { LinkBubbleMenuOpenLink } from './open-link';\nimport { LinkBubbleMenuRoot } from './root';\nimport { LinkBubbleMenuToolbar } from './toolbar';\nimport { LinkBubbleMenuUnlink } from './unlink';\n\ntype ExcludableItem = 'edit-link' | 'open-link' | 'unlink';\n\nexport interface LinkBubbleMenuDefaultProps {\n excludeItems?: ExcludableItem[];\n placement?: 'top' | 'bottom';\n offset?: number;\n onHide?: () => void;\n className?: string;\n validateUrl?: (value: string) => string | null;\n onLinkApply?: (href: string) => void;\n onLinkRemove?: () => void;\n}\n\nexport function LinkBubbleMenuDefault({\n excludeItems = [],\n placement,\n offset,\n onHide,\n className,\n validateUrl,\n onLinkApply,\n onLinkRemove,\n}: LinkBubbleMenuDefaultProps) {\n const has = (item: ExcludableItem) => !excludeItems.includes(item);\n\n const hasToolbarItems = has('edit-link') || has('open-link') || has('unlink');\n\n return (\n <LinkBubbleMenuRoot\n placement={placement}\n offset={offset}\n onHide={onHide}\n className={className}\n >\n {hasToolbarItems && (\n <LinkBubbleMenuToolbar>\n {has('edit-link') && <LinkBubbleMenuEditLink />}\n {has('open-link') && <LinkBubbleMenuOpenLink />}\n {has('unlink') && <LinkBubbleMenuUnlink />}\n </LinkBubbleMenuToolbar>\n )}\n <LinkBubbleMenuForm\n validateUrl={validateUrl}\n onLinkApply={onLinkApply}\n onLinkRemove={onLinkRemove}\n />\n </LinkBubbleMenuRoot>\n );\n}\n","import { LinkBubbleMenuDefault } from './default';\nimport { LinkBubbleMenuEditLink } from './edit-link';\nimport { LinkBubbleMenuForm } from './form';\nimport { LinkBubbleMenuOpenLink } from './open-link';\nimport { LinkBubbleMenuRoot } from './root';\nimport { LinkBubbleMenuToolbar } from './toolbar';\nimport { LinkBubbleMenuUnlink } from './unlink';\n\nexport { useLinkBubbleMenuContext } from './context';\nexport type { LinkBubbleMenuDefaultProps } from './default';\nexport { LinkBubbleMenuDefault } from './default';\nexport type { LinkBubbleMenuEditLinkProps } from './edit-link';\nexport { LinkBubbleMenuEditLink } from './edit-link';\nexport type { LinkBubbleMenuFormProps } from './form';\nexport { LinkBubbleMenuForm } from './form';\nexport type { LinkBubbleMenuOpenLinkProps } from './open-link';\nexport { LinkBubbleMenuOpenLink } from './open-link';\nexport type { LinkBubbleMenuRootProps } from './root';\nexport { LinkBubbleMenuRoot } from './root';\nexport type { LinkBubbleMenuToolbarProps } from './toolbar';\nexport { LinkBubbleMenuToolbar } from './toolbar';\nexport type { LinkBubbleMenuUnlinkProps } from './unlink';\nexport { LinkBubbleMenuUnlink } from './unlink';\n\nexport const LinkBubbleMenu = {\n Root: LinkBubbleMenuRoot,\n Toolbar: LinkBubbleMenuToolbar,\n Form: LinkBubbleMenuForm,\n EditLink: LinkBubbleMenuEditLink,\n Unlink: LinkBubbleMenuUnlink,\n OpenLink: LinkBubbleMenuOpenLink,\n Default: LinkBubbleMenuDefault,\n} as const;\n","import type { Editor } from '@tiptap/core';\nimport { getColumnsDepth, MAX_COLUMNS_DEPTH } from '../../extensions/columns';\n\nexport function isInsideNode(editor: Editor, type: string): boolean {\n const { $from } = editor.state.selection;\n for (let d = $from.depth; d > 0; d--) {\n if ($from.node(d).type.name === type) return true;\n }\n return false;\n}\n\nexport function isAtMaxColumnsDepth(editor: Editor): boolean {\n const { from } = editor.state.selection;\n return getColumnsDepth(editor.state.doc, from) >= MAX_COLUMNS_DEPTH;\n}\n\nexport function updateScrollView(\n container: HTMLElement,\n item: HTMLElement,\n): void {\n const containerRect = container.getBoundingClientRect();\n const itemRect = item.getBoundingClientRect();\n\n if (itemRect.top < containerRect.top) {\n container.scrollTop -= containerRect.top - itemRect.top;\n } else if (itemRect.bottom > containerRect.bottom) {\n container.scrollTop += itemRect.bottom - containerRect.bottom;\n }\n}\n","import { useLayoutEffect, useRef } from 'react';\nimport type { CommandListProps, SlashCommandItem } from './types';\nimport { updateScrollView } from './utils';\n\nconst CATEGORY_ORDER = ['Text', 'Media', 'Layout', 'Utility'];\n\nfunction groupByCategory(\n items: SlashCommandItem[],\n): { category: string; items: SlashCommandItem[] }[] {\n const seen = new Map<string, SlashCommandItem[]>();\n\n for (const item of items) {\n const existing = seen.get(item.category);\n if (existing) {\n existing.push(item);\n } else {\n seen.set(item.category, [item]);\n }\n }\n\n const ordered: { category: string; items: SlashCommandItem[] }[] = [];\n for (const cat of CATEGORY_ORDER) {\n const group = seen.get(cat);\n if (group) {\n ordered.push({ category: cat, items: group });\n seen.delete(cat);\n }\n }\n for (const [category, group] of seen) {\n ordered.push({ category, items: group });\n }\n\n return ordered;\n}\n\ninterface CommandItemProps {\n item: SlashCommandItem;\n selected: boolean;\n onSelect: () => void;\n}\n\nfunction CommandItem({ item, selected, onSelect }: CommandItemProps) {\n return (\n <button\n data-re-slash-command-item=\"\"\n data-selected={selected || undefined}\n onClick={onSelect}\n type=\"button\"\n >\n {item.icon}\n <span>{item.title}</span>\n </button>\n );\n}\n\nexport function CommandList({\n items,\n query,\n selectedIndex,\n onSelect,\n}: CommandListProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const selected = container.querySelector<HTMLElement>('[data-selected]');\n if (selected) {\n updateScrollView(container, selected);\n }\n }, [selectedIndex]);\n\n if (items.length === 0) {\n return (\n <div data-re-slash-command=\"\">\n <div data-re-slash-command-empty=\"\">No results</div>\n </div>\n );\n }\n\n const isFiltering = query.trim().length > 0;\n\n if (isFiltering) {\n return (\n <div data-re-slash-command=\"\" ref={containerRef}>\n {items.map((item, index) => (\n <CommandItem\n item={item}\n key={item.title}\n onSelect={() => onSelect(index)}\n selected={index === selectedIndex}\n />\n ))}\n </div>\n );\n }\n\n const groups = groupByCategory(items);\n let flatIndex = 0;\n\n return (\n <div data-re-slash-command=\"\" ref={containerRef}>\n {groups.map((group) => (\n <div key={group.category}>\n <div data-re-slash-command-category=\"\">{group.category}</div>\n {group.items.map((item) => {\n const currentIndex = flatIndex++;\n return (\n <CommandItem\n item={item}\n key={item.title}\n onSelect={() => onSelect(currentIndex)}\n selected={currentIndex === selectedIndex}\n />\n );\n })}\n </div>\n ))}\n </div>\n );\n}\n","import {\n Columns2,\n Columns3,\n Columns4,\n Heading1,\n Heading2,\n Heading3,\n List,\n ListOrdered,\n MousePointer,\n Rows2 as Rows2Icon,\n SplitSquareVertical as SplitSquareVerticalIcon,\n SquareCode,\n Text,\n TextQuote,\n} from 'lucide-react';\nimport type { SlashCommandItem } from './types';\n\nexport const TEXT: SlashCommandItem = {\n title: 'Text',\n description: 'Plain text block',\n icon: <Text size={20} />,\n category: 'Text',\n searchTerms: ['p', 'paragraph'],\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .toggleNode('paragraph', 'paragraph')\n .run();\n },\n};\n\nexport const H1: SlashCommandItem = {\n title: 'Title',\n description: 'Large heading',\n icon: <Heading1 size={20} />,\n category: 'Text',\n searchTerms: ['title', 'big', 'large', 'h1'],\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode('heading', { level: 1 })\n .run();\n },\n};\n\nexport const H2: SlashCommandItem = {\n title: 'Subtitle',\n description: 'Medium heading',\n icon: <Heading2 size={20} />,\n category: 'Text',\n searchTerms: ['subtitle', 'medium', 'h2'],\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode('heading', { level: 2 })\n .run();\n },\n};\n\nexport const H3: SlashCommandItem = {\n title: 'Heading',\n description: 'Small heading',\n icon: <Heading3 size={20} />,\n category: 'Text',\n searchTerms: ['subtitle', 'small', 'h3'],\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode('heading', { level: 3 })\n .run();\n },\n};\n\nexport const BULLET_LIST: SlashCommandItem = {\n title: 'Bullet list',\n description: 'Unordered list',\n icon: <List size={20} />,\n category: 'Text',\n searchTerms: ['unordered', 'point'],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleBulletList().run();\n },\n};\n\nexport const NUMBERED_LIST: SlashCommandItem = {\n title: 'Numbered list',\n description: 'Ordered list',\n icon: <ListOrdered size={20} />,\n category: 'Text',\n searchTerms: ['ordered'],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleOrderedList().run();\n },\n};\n\nexport const QUOTE: SlashCommandItem = {\n title: 'Quote',\n description: 'Block quote',\n icon: <TextQuote size={20} />,\n category: 'Text',\n searchTerms: ['blockquote'],\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .toggleNode('paragraph', 'paragraph')\n .toggleBlockquote()\n .run();\n },\n};\n\nexport const CODE: SlashCommandItem = {\n title: 'Code block',\n description: 'Code snippet',\n icon: <SquareCode size={20} />,\n category: 'Text',\n searchTerms: ['codeblock'],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleCodeBlock().run();\n },\n};\n\nexport const BUTTON: SlashCommandItem = {\n title: 'Button',\n description: 'Clickable button',\n icon: <MousePointer size={20} />,\n category: 'Layout',\n searchTerms: ['button'],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).setButton().run();\n },\n};\n\nexport const DIVIDER: SlashCommandItem = {\n title: 'Divider',\n description: 'Horizontal separator',\n icon: <SplitSquareVerticalIcon size={20} />,\n category: 'Layout',\n searchTerms: ['hr', 'divider', 'separator'],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).setHorizontalRule().run();\n },\n};\n\nexport const SECTION: SlashCommandItem = {\n title: 'Section',\n description: 'Content section',\n icon: <Rows2Icon size={20} />,\n category: 'Layout',\n searchTerms: ['section', 'row', 'container'],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).insertSection().run();\n },\n};\n\nexport const TWO_COLUMNS: SlashCommandItem = {\n title: '2 columns',\n description: 'Two column layout',\n icon: <Columns2 size={20} />,\n category: 'Layout',\n searchTerms: [\n 'columns',\n 'column',\n 'layout',\n 'grid',\n 'split',\n 'side-by-side',\n 'multi-column',\n 'row',\n 'two',\n '2',\n ],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).insertColumns(2).run();\n },\n};\n\nexport const THREE_COLUMNS: SlashCommandItem = {\n title: '3 columns',\n description: 'Three column layout',\n icon: <Columns3 size={20} />,\n category: 'Layout',\n searchTerms: [\n 'columns',\n 'column',\n 'layout',\n 'grid',\n 'split',\n 'multi-column',\n 'row',\n 'three',\n '3',\n ],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).insertColumns(3).run();\n },\n};\n\nexport const FOUR_COLUMNS: SlashCommandItem = {\n title: '4 columns',\n description: 'Four column layout',\n icon: <Columns4 size={20} />,\n category: 'Layout',\n searchTerms: [\n 'columns',\n 'column',\n 'layout',\n 'grid',\n 'split',\n 'multi-column',\n 'row',\n 'four',\n '4',\n ],\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).insertColumns(4).run();\n },\n};\n\nexport const defaultSlashCommands: SlashCommandItem[] = [\n TEXT,\n H1,\n H2,\n H3,\n BULLET_LIST,\n NUMBERED_LIST,\n QUOTE,\n CODE,\n BUTTON,\n DIVIDER,\n SECTION,\n TWO_COLUMNS,\n THREE_COLUMNS,\n FOUR_COLUMNS,\n];\n","import type { SearchableItem } from './types';\n\nexport function scoreItem(item: SearchableItem, query: string): number {\n if (!query) return 100;\n\n const q = query.toLowerCase();\n const title = item.title.toLowerCase();\n const description = item.description.toLowerCase();\n const terms = item.searchTerms?.map((t) => t.toLowerCase()) ?? [];\n\n if (title === q) return 100;\n if (title.startsWith(q)) return 90;\n\n const titleWords = title.split(/\\s+/);\n if (titleWords.some((w) => w.startsWith(q))) return 80;\n\n if (terms.some((t) => t === q)) return 70;\n if (terms.some((t) => t.startsWith(q))) return 60;\n\n if (title.includes(q)) return 40;\n if (terms.some((t) => t.includes(q))) return 30;\n if (description.includes(q)) return 20;\n\n return 0;\n}\n\nexport function filterAndRankItems<T extends SearchableItem>(\n items: T[],\n query: string,\n): T[] {\n const trimmed = query.trim();\n if (!trimmed) return items;\n\n const scored = items\n .map((item) => ({ item, score: scoreItem(item, trimmed) }))\n .filter(({ score }) => score > 0);\n\n scored.sort((a, b) => b.score - a.score);\n\n return scored.map(({ item }) => item);\n}\n","import {\n autoUpdate,\n flip,\n offset,\n shift,\n useFloating,\n} from '@floating-ui/react-dom';\nimport type { Editor } from '@tiptap/core';\nimport { PluginKey } from '@tiptap/pm/state';\nimport { useCurrentEditor } from '@tiptap/react';\nimport Suggestion from '@tiptap/suggestion';\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { CommandList } from './command-list';\nimport { defaultSlashCommands } from './commands';\nimport { filterAndRankItems } from './search';\nimport type { SlashCommandItem, SlashCommandRootProps } from './types';\nimport { isAtMaxColumnsDepth } from './utils';\n\nconst pluginKey = new PluginKey('slash-command');\n\ninterface SuggestionState {\n active: boolean;\n query: string;\n items: SlashCommandItem[];\n clientRect: (() => DOMRect | null) | null;\n}\n\nconst INITIAL_STATE: SuggestionState = {\n active: false,\n query: '',\n items: [],\n clientRect: null,\n};\n\nfunction defaultFilterItems(\n items: SlashCommandItem[],\n query: string,\n editor: Editor,\n): SlashCommandItem[] {\n const filtered = isAtMaxColumnsDepth(editor)\n ? items.filter(\n (item) => item.category !== 'Layout' || !item.title.includes('column'),\n )\n : items;\n\n return filterAndRankItems(filtered, query);\n}\n\nexport function SlashCommandRoot({\n items: itemsProp,\n filterItems: filterItemsProp,\n char = '/',\n allow: allowProp,\n children,\n}: SlashCommandRootProps) {\n const { editor } = useCurrentEditor();\n const [state, setState] = useState<SuggestionState>(INITIAL_STATE);\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n const itemsRef = useRef(itemsProp ?? defaultSlashCommands);\n const filterRef = useRef(filterItemsProp ?? defaultFilterItems);\n const allowRef = useRef(\n allowProp ??\n (({ editor: e }: { editor: Editor }) => !e.isActive('codeBlock')),\n );\n\n itemsRef.current = itemsProp ?? defaultSlashCommands;\n filterRef.current = filterItemsProp ?? defaultFilterItems;\n allowRef.current =\n allowProp ??\n (({ editor: e }: { editor: Editor }) => !e.isActive('codeBlock'));\n\n const commandRef = useRef<((item: SlashCommandItem) => void) | null>(null);\n const suggestionItemsRef = useRef<SlashCommandItem[]>([]);\n const selectedIndexRef = useRef(0);\n\n suggestionItemsRef.current = state.items;\n selectedIndexRef.current = selectedIndex;\n\n const { refs, floatingStyles } = useFloating({\n open: state.active,\n placement: 'bottom-start',\n middleware: [offset(8), flip(), shift({ padding: 8 })],\n whileElementsMounted: autoUpdate,\n });\n\n useEffect(() => {\n if (!state.clientRect) return;\n refs.setReference({\n getBoundingClientRect: state.clientRect,\n });\n }, [state.clientRect, refs]);\n\n useEffect(() => {\n setSelectedIndex(0);\n }, [state.items]);\n\n const onSelect = useCallback((index: number) => {\n const item = suggestionItemsRef.current[index];\n if (item && commandRef.current) {\n commandRef.current(item);\n }\n }, []);\n\n useEffect(() => {\n if (!editor) return;\n\n const plugin = Suggestion<SlashCommandItem, SlashCommandItem>({\n pluginKey,\n editor,\n char,\n allow: ({ editor: e }) => allowRef.current({ editor: e }),\n command: ({ editor: e, range, props }) => {\n props.command({ editor: e, range });\n },\n items: ({ query, editor: e }) =>\n filterRef.current(itemsRef.current, query, e),\n render: () => ({\n onStart: (props) => {\n commandRef.current = props.command;\n setState({\n active: true,\n query: props.query,\n items: props.items,\n clientRect: props.clientRect ?? null,\n });\n },\n onUpdate: (props) => {\n commandRef.current = props.command;\n setState({\n active: true,\n query: props.query,\n items: props.items,\n clientRect: props.clientRect ?? null,\n });\n },\n onKeyDown: ({ event }) => {\n if (event.key === 'Escape') {\n setState(INITIAL_STATE);\n return true;\n }\n\n const items = suggestionItemsRef.current;\n if (items.length === 0) return false;\n\n if (event.key === 'ArrowUp') {\n setSelectedIndex((i) => (i + items.length - 1) % items.length);\n return true;\n }\n if (event.key === 'ArrowDown') {\n setSelectedIndex((i) => (i + 1) % items.length);\n return true;\n }\n if (event.key === 'Enter') {\n const item = items[selectedIndexRef.current];\n if (item && commandRef.current) {\n commandRef.current(item);\n }\n return true;\n }\n return false;\n },\n onExit: () => {\n setState(INITIAL_STATE);\n requestAnimationFrame(() => {\n commandRef.current = null;\n });\n },\n }),\n });\n\n editor.registerPlugin(plugin, (newPlugin, plugins) => [\n newPlugin,\n ...plugins,\n ]);\n return () => {\n editor.unregisterPlugin(pluginKey);\n };\n }, [editor, char]);\n\n if (!editor || !state.active) return null;\n\n const renderProps = {\n items: state.items,\n query: state.query,\n selectedIndex,\n onSelect,\n };\n\n let content: ReactNode;\n if (children) {\n content = children(renderProps);\n } else {\n content = <CommandList {...renderProps} />;\n }\n\n return createPortal(\n <div ref={refs.setFloating} style={floatingStyles}>\n {content}\n </div>,\n document.body,\n );\n}\n","import { CommandList } from './command-list';\nimport { SlashCommandRoot } from './root';\n\nexport const SlashCommand = {\n Root: SlashCommandRoot,\n CommandList,\n} as const;\n\nexport { CommandList } from './command-list';\nexport {\n BULLET_LIST,\n BUTTON,\n CODE,\n DIVIDER,\n defaultSlashCommands,\n FOUR_COLUMNS,\n H1,\n H2,\n H3,\n NUMBERED_LIST,\n QUOTE,\n SECTION,\n TEXT,\n THREE_COLUMNS,\n TWO_COLUMNS,\n} from './commands';\nexport { filterAndRankItems, scoreItem } from './search';\nexport type {\n CommandListProps,\n SearchableItem,\n SlashCommandItem,\n SlashCommandProps,\n SlashCommandRenderProps,\n SlashCommandRootProps,\n} from './types';\nexport { isAtMaxColumnsDepth, isInsideNode } from './utils';\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/utils/set-text-alignment.ts"],"sourcesContent":[],"mappings":";;;iBAEgB,gBAAA,SAAyB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/utils/set-text-alignment.ts"],"sourcesContent":[],"mappings":";;;iBAEgB,gBAAA,SAAyB"}
|
package/package.json
CHANGED
|
@@ -1,25 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-email/editor",
|
|
3
|
-
"version": "0.0.0-experimental.
|
|
3
|
+
"version": "0.0.0-experimental.24",
|
|
4
4
|
"description": "",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
7
7
|
],
|
|
8
|
-
"main": "./dist/index.js",
|
|
9
|
-
"module": "./dist/index.mjs",
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
8
|
"files": [
|
|
12
9
|
"dist/**"
|
|
13
10
|
],
|
|
14
11
|
"exports": {
|
|
15
|
-
"
|
|
12
|
+
"./core": {
|
|
16
13
|
"import": {
|
|
17
|
-
"types": "./dist/index.d.mts",
|
|
18
|
-
"default": "./dist/index.mjs"
|
|
14
|
+
"types": "./dist/core/index.d.mts",
|
|
15
|
+
"default": "./dist/core/index.mjs"
|
|
19
16
|
},
|
|
20
17
|
"require": {
|
|
21
|
-
"types": "./dist/index.d.cts",
|
|
22
|
-
"default": "./dist/index.cjs"
|
|
18
|
+
"types": "./dist/core/index.d.cts",
|
|
19
|
+
"default": "./dist/core/index.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"./extensions": {
|
|
23
|
+
"import": {
|
|
24
|
+
"types": "./dist/extensions/index.d.mts",
|
|
25
|
+
"default": "./dist/extensions/index.mjs"
|
|
26
|
+
},
|
|
27
|
+
"require": {
|
|
28
|
+
"types": "./dist/extensions/index.d.cts",
|
|
29
|
+
"default": "./dist/extensions/index.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"./ui": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/ui/index.d.mts",
|
|
35
|
+
"default": "./dist/ui/index.mjs"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/ui/index.d.cts",
|
|
39
|
+
"default": "./dist/ui/index.cjs"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"./utils": {
|
|
43
|
+
"import": {
|
|
44
|
+
"types": "./dist/utils/index.d.mts",
|
|
45
|
+
"default": "./dist/utils/index.mjs"
|
|
46
|
+
},
|
|
47
|
+
"require": {
|
|
48
|
+
"types": "./dist/utils/index.d.cts",
|
|
49
|
+
"default": "./dist/utils/index.cjs"
|
|
23
50
|
}
|
|
24
51
|
},
|
|
25
52
|
"./styles/bubble-menu.css": "./dist/ui/bubble-menu/bubble-menu.css",
|
|
@@ -93,9 +120,9 @@
|
|
|
93
120
|
"access": "public"
|
|
94
121
|
},
|
|
95
122
|
"scripts": {
|
|
96
|
-
"build": "tsdown
|
|
123
|
+
"build": "tsdown && pnpm run build:css",
|
|
97
124
|
"build:css": "tsx scripts/copy-css.ts",
|
|
98
|
-
"build:watch": "tsdown
|
|
125
|
+
"build:watch": "tsdown --watch",
|
|
99
126
|
"clean": "rm -rf dist",
|
|
100
127
|
"typecheck": "tsc --noEmit",
|
|
101
128
|
"test": "vitest run",
|