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 }}
/>
}
style={{ minWidth: 32 }}
/>
)
const cardContent = (
{VIEW_ITEMS.map((item) => (
handleViewStateChange(item.key, e.target.checked)
}
>
{item.label}
))}
}
placement='bottomLeft'
trigger='hover'
arrow={false}
>
}
style={{ width: 160 }}
status={'defult'}
disabled={!editor || editingToolsDisabled}
/>
}
onClick={() => editor?.chain().focus().toggleBold().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() => editor?.chain().focus().toggleItalic().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() => editor?.chain().focus().toggleUnderline().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() => editor?.chain().focus().toggleBulletList().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() => editor?.chain().focus().toggleOrderedList().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() =>
handleBlockTypeChange(
editorState.blockTypeValue === 'quote' ? 'paragraph' : 'quote'
)
}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() => editor?.chain().focus().toggleCodeBlock().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
}
onClick={() => editor?.chain().focus().setHorizontalRule().run()}
disabled={!editor || editingToolsDisabled}
style={{ minWidth: 32 }}
/>
)
return (
<>
{showCard ? (
{cardContent}
) : (
cardContent
)}
>
)
}
MarkdownToolbar.propTypes = {
editor: PropTypes.shape({
chain: PropTypes.func,
getAttributes: PropTypes.func,
isActive: PropTypes.func
}),
size: PropTypes.string,
showCard: PropTypes.bool,
viewState: PropTypes.object,
onViewStateChange: PropTypes.func,
editingToolsDisabled: PropTypes.bool
}
export default MarkdownToolbar