import { Input } from '@headlessui/react' import { ArrowUturnLeftIcon, ArrowUturnRightIcon, Bars3BottomLeftIcon, Bars3BottomRightIcon, Bars3Icon, Bars4Icon, BoldIcon, CloudArrowUpIcon, CodeBracketIcon, DocumentTextIcon, H1Icon, H2Icon, H3Icon, ItalicIcon, LinkIcon, LinkSlashIcon, ListBulletIcon, NumberedListIcon, PhotoIcon, StrikethroughIcon, SwatchIcon, } from '@heroicons/react/20/solid' import type { Editor } from '@tiptap/react' import { type SetStateAction, type Dispatch, useState, useRef, useCallback, useEffect, } from 'react' import { HexColorInput, HexColorPicker } from 'react-colorful' import { Button } from '~/components/ui/button' import { useAdminContext } from '~/contexts/admin' import { useClickOutside } from '~/hooks/use-click-outside' import { isHexCompatible, rgbToHex } from '~/utils/color' import { EditorButton } from './editor-button' type TProperties = { editor: Editor | null setIsPlainHTML: Dispatch> category: string disabled?: boolean } export const EditorMenuBar = (properties: TProperties) => { const { editor, setIsPlainHTML, // category, disabled = false, } = properties const { setIsUploadOpen, uploadedFile, setUploadedFile } = useAdminContext() const [isOpenImage, setIsOpenImage] = useState(false) const [imageUrl, setImageUrl] = useState('') const [isOpenColor, setIsOpenColor] = useState(false) const popover = useRef(null) const close = useCallback(() => { setIsOpenColor(false) setIsOpenImage(false) if (imageUrl) { addImage(imageUrl) } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) useEffect(() => { if (uploadedFile) { addImage(uploadedFile) setUploadedFile(undefined) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [uploadedFile]) useClickOutside(popover, close) const setLink = useCallback(() => { const previousUrl = editor?.getAttributes('link').href const url = globalThis.prompt('URL', previousUrl) // cancelled if (url === null) { return } // empty if (url === '') { editor?.chain().focus().extendMarkRange('link').unsetLink().run() return } // update link editor?.chain().focus().extendMarkRange('link').setLink({ href: url }).run() }, [editor]) if (!editor) { return } const addImage = (url: string) => { if (url) { editor.chain().focus().setImage({ src: url }).run() } } const currentColor: string = editor.getAttributes('textStyle').color const rgbColor = isHexCompatible(currentColor) ? currentColor : rgbToHex(currentColor) const handleChangeColor = (selectedColor: string) => { if (selectedColor.length === 7) { editor.chain().focus().setColor(selectedColor).run() } } return (
editor.chain().focus().toggleBold().run()} disabled={ disabled || !editor.can().chain().focus().toggleBold().run() } isActive={editor.isActive('bold')} title="Bold" > editor.chain().focus().toggleItalic().run()} disabled={ disabled || !editor.can().chain().focus().toggleItalic().run() } isActive={editor.isActive('italic')} title="Italic" > editor.chain().focus().toggleStrike().run()} disabled={ disabled || !editor.can().chain().focus().toggleStrike().run() } isActive={editor.isActive('strike')} title="Strike" >
setIsOpenColor(true)} title="Text Color" style={{ color: rgbColor, }} isActive={true} disabled={disabled} > {isOpenColor && (
)}
editor.chain().focus().setTextAlign('left').run()} disabled={ disabled || !editor.can().chain().focus().setTextAlign('left').run() } isActive={editor.isActive({ textAlign: 'left' })} title="Align Left" > editor.chain().focus().setTextAlign('center').run()} disabled={ disabled || !editor.can().chain().focus().setTextAlign('center').run() } isActive={editor.isActive({ textAlign: 'center' })} title="Align Center" > editor.chain().focus().setTextAlign('right').run()} disabled={ disabled || !editor.can().chain().focus().setTextAlign('right').run() } isActive={editor.isActive({ textAlign: 'right' })} title="Align Right" > editor.chain().focus().setTextAlign('justify').run()} disabled={ disabled || !editor.can().chain().focus().setTextAlign('justify').run() } isActive={editor.isActive({ textAlign: 'justify' })} title="Align Justify" >
editor.chain().focus().toggleHeading({ level: 1 }).run() } isActive={editor.isActive('heading', { level: 1 })} title="Heading 1" disabled={disabled} > editor.chain().focus().toggleHeading({ level: 2 }).run() } isActive={editor.isActive('heading', { level: 2 })} title="Heading 2" disabled={disabled} > editor.chain().focus().toggleHeading({ level: 3 }).run() } isActive={editor.isActive('heading', { level: 3 })} title="Heading 3" disabled={disabled} > {/* editor.chain().focus().setParagraph().run()} isActive={editor.isActive('paragraph')} title="Paragraph" disabled={disabled} > */} editor.chain().focus().toggleBulletList().run()} isActive={editor.isActive('bulletList')} title="Bullet List" disabled={disabled} > editor.chain().focus().toggleOrderedList().run()} isActive={editor.isActive('orderedList')} title="Ordered List" disabled={disabled} > editor.chain().focus().toggleCodeBlock().run()} isActive={editor.isActive('codeBlock')} title="Code Block" disabled={disabled} >
{/*
editor.chain().focus().toggleBlockquote().run()} isActive={editor.isActive('blockquote')} title="Blockquote" disabled={disabled} > editor.chain().focus().setHorizontalRule().run()} title="Horizontal Rule" disabled={disabled} >
*/} {/*
editor.chain().focus().setHardBreak().run()} title="Hard Break" disabled={disabled} > { editor.chain().focus().unsetAllMarks().run() editor.chain().focus().clearNodes().run() }} title="Clear Format" disabled={disabled} >
*/}
setIsOpenImage(true)} title="Insert Image" disabled={disabled} > {isOpenImage && (
{ setImageUrl(event.target.value) }} className="z-10 flex h-[42px] w-full rounded-lg border-0 bg-white p-2 pr-8 text-sm shadow read-only:bg-gray-100 focus:ring-1 focus:ring-[#2E2F7C] focus:outline-none focus-visible:outline-0 disabled:bg-gray-100" />
)}
setLink()} disabled={ disabled || !editor .can() .chain() .focus() .extendMarkRange('link') .setLink({ href: '' }) .run() } isActive={editor.isActive('link')} title="Set Link" > editor.chain().focus().unsetLink().run()} disabled={disabled || !editor.isActive('link')} title="Unset Link" >
editor.chain().focus().undo().run()} disabled={disabled || !editor.can().chain().focus().undo().run()} title="Undo" > editor.chain().focus().redo().run()} disabled={disabled || !editor.can().chain().focus().redo().run()} title="Redo" >
setIsPlainHTML(true)} title="Switch to Plain Text" >
) }