import { Field, Label } from '@headlessui/react' import { Color } from '@tiptap/extension-color' import Highlight from '@tiptap/extension-highlight' import Image from '@tiptap/extension-image' import Link from '@tiptap/extension-link' import TextAlign from '@tiptap/extension-text-align' import TextStyle from '@tiptap/extension-text-style' import { EditorContent, useEditor } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import { useEffect, useId, useState } from 'react' import { get, type FieldError, type FieldValues, type Path, type RegisterOptions, } from 'react-hook-form' import { useRemixFormContext } from 'remix-hook-form' import { twMerge } from 'tailwind-merge' import { EditorMenuBar } from './editor-menubar' import { EditorTextArea } from './editor-textarea' type TProperties = { id?: string name: Path label?: string placeholder?: string labelClassName?: string className?: string inputClassName?: string containerClassName?: string rules?: RegisterOptions disabled?: boolean isRequired?: boolean category: string } export const TextEditor = >( properties: TProperties, ) => { const { id, label, name, labelClassName, className, inputClassName, category, disabled = false, containerClassName, } = properties const [isPlainHTML, setIsPlainHTML] = useState(false) const [init, setInit] = useState(true) const [darkMode, setDarkMode] = useState(false) const generatedId = useId() const { setValue, watch, formState: { errors }, } = useRemixFormContext() const watchContent = watch(name) const error: FieldError = get(errors, name) const editor = useEditor({ editable: !disabled, extensions: [ StarterKit, Highlight, Image.configure({ inline: true, }), TextStyle, Color.configure({ types: ['textStyle'], }), Link.configure({ openOnClick: false, }), TextAlign.configure({ types: ['heading', 'paragraph'], }), ], content: watchContent, onUpdate: ({ editor }) => { setValue(name, editor.getHTML() as any) // eslint-disable-line @typescript-eslint/no-explicit-any }, }) useEffect(() => { if ( watchContent && watchContent.length > 0 && editor && (isPlainHTML || init) ) { editor.commands.setContent(watchContent) setInit(false) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [watchContent]) return ( {label && ( )} {isPlainHTML ? ( ) : (
editor?.commands.focus()} />
)}
) }