/* MIT License Copyright (c) Meta Platforms, Inc. and affiliates. This source code is licensed under the MIT license found in the LICENSE file in the /app/soapbox/features/compose/editor directory. */ import { $convertFromMarkdownString, $convertToMarkdownString } from '@lexical/markdown'; import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin'; import { LexicalComposer, InitialConfigType } from '@lexical/react/LexicalComposer'; import { ContentEditable } from '@lexical/react/LexicalContentEditable'; import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary'; import { HashtagPlugin } from '@lexical/react/LexicalHashtagPlugin'; import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'; import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'; import { ListPlugin } from '@lexical/react/LexicalListPlugin'; import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'; import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'; import clsx from 'clsx'; import { $createParagraphNode, $createTextNode, $getRoot } from 'lexical'; import React, { useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { useAppDispatch, useFeatures } from 'soapbox/hooks'; import nodes from './nodes'; import AutosuggestPlugin from './plugins/autosuggest-plugin'; import DraggableBlockPlugin from './plugins/draggable-block-plugin'; import FloatingLinkEditorPlugin from './plugins/floating-link-editor-plugin'; import FloatingTextFormatToolbarPlugin from './plugins/floating-text-format-toolbar-plugin'; import MentionPlugin from './plugins/mention-plugin'; import StatePlugin from './plugins/state-plugin'; import { TO_WYSIWYG_TRANSFORMERS } from './transformers'; interface IComposeEditor { className?: string composeId: string condensed?: boolean eventDiscussion?: boolean hasPoll?: boolean autoFocus?: boolean handleSubmit?: () => void onFocus?: React.FocusEventHandler onPaste?: (files: FileList) => void placeholder?: JSX.Element | string } const ComposeEditor = React.forwardRef(({ className, composeId, condensed, eventDiscussion, hasPoll, autoFocus, handleSubmit, onFocus, onPaste, placeholder, }, editorStateRef) => { const dispatch = useAppDispatch(); const features = useFeatures(); const [suggestionsHidden, setSuggestionsHidden] = useState(true); const initialConfig: InitialConfigType = useMemo(function() { return { namespace: 'ComposeForm', onError: console.error, nodes, theme: { hashtag: 'hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue', mention: 'hover:underline text-primary-600 dark:text-accent-blue hover:text-primary-800 dark:hover:text-accent-blue', text: { bold: 'font-bold', code: 'font-mono', italic: 'italic', strikethrough: 'line-through', underline: 'underline', underlineStrikethrough: 'underline-line-through', }, heading: { h1: 'text-2xl font-bold', h2: 'text-xl font-bold', h3: 'text-lg font-semibold', }, }, editorState: dispatch((_, getState) => { const state = getState(); const compose = state.compose.get(composeId); if (!compose) return; if (compose.editorState) { return compose.editorState; } return function() { if (compose.content_type === 'text/markdown') { $convertFromMarkdownString(compose.text, TO_WYSIWYG_TRANSFORMERS); } else { const paragraph = $createParagraphNode(); const textNode = $createTextNode(compose.text); paragraph.append(textNode); $getRoot() .clear() .append(paragraph); } }; }), }; }, []); const [floatingAnchorElem, setFloatingAnchorElem] = useState(null); const onRef = (_floatingAnchorElem: HTMLDivElement) => { if (_floatingAnchorElem !== null) { setFloatingAnchorElem(_floatingAnchorElem); } }; const handlePaste: React.ClipboardEventHandler = (e) => { if (onPaste && e.clipboardData && e.clipboardData.files.length === 1) { onPaste(e.clipboardData.files); e.preventDefault(); } }; let textareaPlaceholder = placeholder || ; if (eventDiscussion) { textareaPlaceholder = ; } else if (hasPoll) { textareaPlaceholder = ; } return (
alert('xd')}>
} placeholder={(
{textareaPlaceholder}
)} ErrorBoundary={LexicalErrorBoundary} /> {autoFocus && } { editor.update(() => { if (editorStateRef) (editorStateRef as any).current = $convertToMarkdownString(TO_WYSIWYG_TRANSFORMERS); }); }} /> {features.richText && } {features.richText && } {features.richText && floatingAnchorElem && ( <> )}
); }); export default ComposeEditor;