Lexical: Fix autofocus

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2023-07-22 17:20:47 +02:00
parent 176a3b5ece
commit b3f9edd41e
4 changed files with 58 additions and 23 deletions

View File

@ -6,7 +6,6 @@ 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 { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
import { AutoLinkPlugin, createLinkMatcherWithRegExp } from '@lexical/react/LexicalAutoLinkPlugin';
import { LexicalComposer, InitialConfigType } from '@lexical/react/LexicalComposer';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
@ -25,6 +24,15 @@ import { FormattedMessage } from 'react-intl';
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
import { useNodes } from './nodes';
import AutosuggestPlugin from './plugins/autosuggest-plugin';
import FloatingBlockTypeToolbarPlugin from './plugins/floating-block-type-toolbar-plugin';
import FloatingLinkEditorPlugin from './plugins/floating-link-editor-plugin';
import FloatingTextFormatToolbarPlugin from './plugins/floating-text-format-toolbar-plugin';
import FocusPlugin from './plugins/focus-plugin';
import MentionPlugin from './plugins/mention-plugin';
import StatePlugin from './plugins/state-plugin';
const LINK_MATCHERS = [
createLinkMatcherWithRegExp(
/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/,
@ -32,14 +40,6 @@ const LINK_MATCHERS = [
),
];
import { useNodes } from './nodes';
import AutosuggestPlugin from './plugins/autosuggest-plugin';
import FloatingBlockTypeToolbarPlugin from './plugins/floating-block-type-toolbar-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';
interface IComposeEditor {
className?: string
placeholderClassName?: string
@ -104,7 +104,7 @@ const ComposeEditor = React.forwardRef<string, IComposeEditor>(({
return compose.editorState;
}
return function() {
return () => {
if (compose.content_type === 'text/markdown') {
$createRemarkImport({})(compose.text);
} else {
@ -152,11 +152,10 @@ const ComposeEditor = React.forwardRef<string, IComposeEditor>(({
contentEditable={
<div className='editor' ref={onRef} onFocus={onFocus} onPaste={handlePaste}>
<ContentEditable
className={clsx('mr-4 pb-8 outline-none transition-[min-height] motion-reduce:transition-none', {
'min-h-[40px]': condensed,
'min-h-[100px]': !condensed,
className={clsx('outline-none transition-[min-height] motion-reduce:transition-none', {
'min-h-[40px] pb-4': condensed,
'min-h-[100px] pb-8': !condensed,
})}
autoFocus={autoFocus}
/>
</div>
}
@ -172,7 +171,6 @@ const ComposeEditor = React.forwardRef<string, IComposeEditor>(({
)}
ErrorBoundary={LexicalErrorBoundary}
/>
{autoFocus && <AutoFocusPlugin />}
<OnChangePlugin onChange={(_, editor) => {
if (editorStateRef) (editorStateRef as any).current = editor.getEditorState().read($createRemarkExport());
}}
@ -192,6 +190,7 @@ const ComposeEditor = React.forwardRef<string, IComposeEditor>(({
</>
)}
<StatePlugin composeId={composeId} handleSubmit={handleSubmit} />
<FocusPlugin autoFocus={autoFocus} />
</div>
</LexicalComposer>
);

View File

@ -42,7 +42,7 @@ import type {
const imageCache = new Set();
function useSuspenseImage(src: string) {
const useSuspenseImage = (src: string) => {
if (!imageCache.has(src)) {
throw new Promise((resolve) => {
const img = new Image();
@ -53,9 +53,9 @@ function useSuspenseImage(src: string) {
};
});
}
}
};
function LazyImage({
const LazyImage = ({
altText,
className,
imageRef,
@ -65,7 +65,7 @@ function LazyImage({
className: string | null
imageRef: {current: null | HTMLImageElement}
src: string
}): JSX.Element {
}): JSX.Element => {
useSuspenseImage(src);
return (
<img
@ -76,9 +76,9 @@ function LazyImage({
draggable='false'
/>
);
}
};
export default function ImageComponent({
const ImageComponent = ({
src,
altText,
nodeKey,
@ -86,7 +86,7 @@ export default function ImageComponent({
altText: string
nodeKey: NodeKey
src: string
}): JSX.Element {
}): JSX.Element => {
const imageRef = useRef<null | HTMLImageElement>(null);
const buttonRef = useRef<HTMLButtonElement | null>(null);
const [isSelected, setSelected, clearSelection] =
@ -270,4 +270,6 @@ export default function ImageComponent({
</>
</Suspense>
);
}
};
export default ImageComponent;

View File

@ -0,0 +1,33 @@
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { useEffect } from 'react';
interface IFocusPlugin {
autoFocus?: boolean
}
const FocusPlugin: React.FC<IFocusPlugin> = ({ autoFocus }) => {
const [editor] = useLexicalComposerContext();
const focus = () => {
editor.focus(
() => {
const activeElement = document.activeElement;
const rootElement = editor.getRootElement();
if (
rootElement !== null &&
(activeElement === null || !rootElement.contains(activeElement))
) {
rootElement.focus({ preventScroll: true });
}
}, { defaultSelection: 'rootEnd' },
);
};
useEffect(() => {
if (autoFocus) focus();
}, []);
return null;
};
export default FocusPlugin;

View File

@ -86,6 +86,7 @@ const ComposeModal: React.FC<IComposeModal> = ({ onClose, composeId = 'compose-m
<ComposeForm
id={composeId}
extra={<ComposeFormGroupToggle composeId={composeId} groupId={groupId} />}
autoFocus
/>
</Modal>
);