2022-12-01 12:32:55 -08:00
|
|
|
import {
|
|
|
|
$convertToMarkdownString,
|
|
|
|
TRANSFORMERS,
|
|
|
|
} from '@lexical/markdown';
|
2023-01-01 14:01:21 -08:00
|
|
|
import { LexicalComposer, InitialConfigType } from '@lexical/react/LexicalComposer';
|
2022-12-01 12:32:55 -08:00
|
|
|
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
|
|
|
|
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
|
|
|
|
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
|
|
|
|
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
|
|
|
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
|
|
|
|
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
|
2023-01-01 14:01:21 -08:00
|
|
|
import classNames from 'clsx';
|
2022-12-01 12:32:55 -08:00
|
|
|
import React, { useState } from 'react';
|
|
|
|
import { FormattedMessage } from 'react-intl';
|
|
|
|
|
2023-01-01 14:01:21 -08:00
|
|
|
import { useFeatures } from 'soapbox/hooks';
|
|
|
|
|
2022-12-01 12:32:55 -08:00
|
|
|
import nodes from './nodes';
|
|
|
|
import FloatingLinkEditorPlugin from './plugins/floating-link-editor-plugin';
|
|
|
|
import FloatingTextFormatToolbarPlugin from './plugins/floating-text-format-toolbar-plugin';
|
|
|
|
|
|
|
|
// import type { EditorState } from 'lexical';
|
|
|
|
|
2023-01-01 14:01:21 -08:00
|
|
|
const initialConfig: InitialConfigType = {
|
2022-12-01 12:32:55 -08:00
|
|
|
namespace: 'ComposeForm',
|
|
|
|
onError: console.error,
|
|
|
|
nodes,
|
2023-01-01 14:01:21 -08:00
|
|
|
theme: {
|
|
|
|
text: {
|
|
|
|
bold: 'font-bold',
|
|
|
|
code: 'font-mono',
|
|
|
|
italic: 'italic',
|
|
|
|
strikethrough: 'line-through',
|
|
|
|
underline: 'underline',
|
|
|
|
underlineStrikethrough: 'underline-line-through',
|
|
|
|
},
|
|
|
|
},
|
2022-12-01 12:32:55 -08:00
|
|
|
};
|
|
|
|
|
2023-01-01 14:01:21 -08:00
|
|
|
const ComposeEditor = React.forwardRef<string, any>(({ condensed, onFocus }, editorStateRef) => {
|
|
|
|
const features = useFeatures();
|
|
|
|
|
2022-12-01 12:32:55 -08:00
|
|
|
const [floatingAnchorElem, setFloatingAnchorElem] =
|
|
|
|
useState<HTMLDivElement | null>(null);
|
|
|
|
|
|
|
|
const onRef = (_floatingAnchorElem: HTMLDivElement) => {
|
|
|
|
if (_floatingAnchorElem !== null) {
|
|
|
|
setFloatingAnchorElem(_floatingAnchorElem);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<LexicalComposer initialConfig={initialConfig}>
|
2023-01-01 14:01:21 -08:00
|
|
|
<div className='lexical relative' data-markup>
|
2022-12-01 12:32:55 -08:00
|
|
|
<RichTextPlugin
|
|
|
|
contentEditable={
|
2023-01-01 14:01:21 -08:00
|
|
|
<div className='editor' ref={onRef} onFocus={onFocus}>
|
|
|
|
<ContentEditable
|
|
|
|
className={classNames('outline-none py-2 transition-[min-height] motion-reduce:transition-none', {
|
|
|
|
'min-h-[40px]': condensed,
|
|
|
|
'min-h-[100px]': !condensed,
|
|
|
|
})}
|
|
|
|
/>
|
2022-12-01 12:32:55 -08:00
|
|
|
</div>
|
|
|
|
}
|
|
|
|
placeholder={(
|
|
|
|
<div className='absolute top-2 text-gray-600 dark:placeholder:text-gray-600 pointer-events-none select-none'>
|
|
|
|
<FormattedMessage id='compose_form.placeholder' defaultMessage="What's on your mind" />
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
ErrorBoundary={LexicalErrorBoundary}
|
|
|
|
/>
|
|
|
|
<OnChangePlugin onChange={(_, editor) => {
|
|
|
|
editor.update(() => {
|
|
|
|
if (editorStateRef) (editorStateRef as any).current = $convertToMarkdownString(TRANSFORMERS);
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
<HistoryPlugin />
|
2023-01-01 14:01:21 -08:00
|
|
|
{features.richText && <LinkPlugin />}
|
|
|
|
{features.richText && floatingAnchorElem && (
|
2022-12-01 12:32:55 -08:00
|
|
|
<>
|
|
|
|
<FloatingTextFormatToolbarPlugin anchorElem={floatingAnchorElem} />
|
|
|
|
<FloatingLinkEditorPlugin anchorElem={floatingAnchorElem} />
|
|
|
|
</>
|
2023-01-01 14:01:21 -08:00
|
|
|
)}
|
2022-12-01 12:32:55 -08:00
|
|
|
</div>
|
|
|
|
</LexicalComposer>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
export default ComposeEditor;
|