import { MinusOutlined } from '@ant-design/icons' import { useEditorState } from '@tiptap/react' import { useState } from 'react' import { Button, Card, Checkbox, Flex, Input, Popover, Select, Space } from 'antd' import PropTypes from 'prop-types' import Tooltip from './Tooltip' import BlockquoteIcon from '../../Icons/BlockquoteIcon' import BoldIcon from '../../Icons/BoldIcon' import BulletListIcon from '../../Icons/BulletListIcon' import CheckIcon from '../../Icons/CheckIcon' import ItalicIcon from '../../Icons/ItalicIcon' import NumberedListIcon from '../../Icons/NumberedListIcon' import JsonObjectIcon from '../../Icons/JsonObjectIcon' import LinkIcon from '../../Icons/LinkIcon' import TextFormatIcon from '../../Icons/TextFormatIcon' import UnderlineIcon from '../../Icons/UnderlineIcon' const BLOCK_TYPE_OPTIONS = [ { label: 'Paragraph', value: 'paragraph' }, { label: 'Heading 1', value: 'h1' }, { label: 'Heading 2', value: 'h2' }, { label: 'Heading 3', value: 'h3' }, { label: 'Heading 4', value: 'h4' }, { label: 'Quote', value: 'quote' } ] const getBlockTypeValue = (editor) => { if (!editor) { return 'paragraph' } if (editor.isActive('blockquote')) { return 'quote' } for (const level of [1, 2, 3, 4]) { if (editor.isActive('heading', { level })) { return `h${level}` } } return 'paragraph' } const VIEW_ITEMS = [ { key: 'editor', label: 'Editor' }, { key: 'code', label: 'Code' } ] const MarkdownToolbar = ({ editor, size = 'small', showCard = true, viewState = { editor: true, code: false }, onViewStateChange = () => {}, editingToolsDisabled = false }) => { const [linkPopoverOpen, setLinkPopoverOpen] = useState(false) const [linkUrl, setLinkUrl] = useState('') const editorState = useEditorState({ editor, selector: ({ editor }) => ({ blockTypeValue: getBlockTypeValue(editor), isBold: editor?.isActive('bold') ?? false, isItalic: editor?.isActive('italic') ?? false, isUnderline: editor?.isActive('underline') ?? false, isBulletList: editor?.isActive('bulletList') ?? false, isOrderedList: editor?.isActive('orderedList') ?? false }) }) const handleViewStateChange = (key, checked) => { const nextState = { ...viewState, [key]: checked } if (!nextState.editor && !nextState.code) { nextState[key] = true } onViewStateChange(nextState) } const handleLinkPopoverOpenChange = (open) => { setLinkPopoverOpen(open) if (open) { setLinkUrl(editor?.getAttributes('link').href ?? '') } } const handleLinkSubmit = () => { if (!editor) { return } const trimmedUrl = linkUrl.trim() if (!trimmedUrl) { editor.chain().focus().extendMarkRange('link').unsetLink().run() } else { editor .chain() .focus() .extendMarkRange('link') .setLink({ href: trimmedUrl }) .run() } setLinkPopoverOpen(false) } const handleBlockTypeChange = (nextBlockType) => { if (!editor) { return } const chain = editor.chain().focus() if (editor.isActive('blockquote') && nextBlockType !== 'quote') { chain.toggleBlockquote() } if (nextBlockType === 'paragraph') { chain.setParagraph().run() return } if (nextBlockType === 'quote') { if (editor.isActive('heading')) { chain.setParagraph() } chain.toggleBlockquote().run() return } const headingLevel = Number(nextBlockType.replace('h', '')) chain.setHeading({ level: headingLevel }).run() } const linkPopoverContent = ( setLinkUrl(e.target.value)} onPressEnter={handleLinkSubmit} style={{ flex: 1 }} />