import { observer } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; import { useRouteMatch } from "react-router-dom"; import fullPackage from "@shared/editor/packages/full"; import Document from "~/models/Document"; import ClickablePadding from "~/components/ClickablePadding"; import DocumentMetaWithViews from "~/components/DocumentMetaWithViews"; import Editor, { Props as EditorProps } from "~/components/Editor"; import Flex from "~/components/Flex"; import HoverPreview from "~/components/HoverPreview"; import { documentHistoryUrl, documentUrl, matchDocumentHistory, } from "~/utils/routeHelpers"; import MultiplayerEditor from "./AsyncMultiplayerEditor"; import EditableTitle from "./EditableTitle"; type Props = Omit & { onChangeTitle: (text: string) => void; title: string; id: string; document: Document; isDraft: boolean; multiplayer?: boolean; onSave: (options: { done?: boolean; autosave?: boolean; publish?: boolean; }) => void; children: React.ReactNode; }; /** * The main document editor includes an editable title with metadata below it, * and support for hover previews of internal links. */ function DocumentEditor(props: Props, ref: React.RefObject) { const [ activeLinkEvent, setActiveLinkEvent, ] = React.useState(null); const titleRef = React.useRef(null); const { t } = useTranslation(); const match = useRouteMatch(); const focusAtStart = React.useCallback(() => { if (ref.current) { ref.current.focusAtStart(); } }, [ref]); const focusAtEnd = React.useCallback(() => { if (ref.current) { ref.current.focusAtEnd(); } }, [ref]); const handleLinkActive = React.useCallback((event: MouseEvent) => { setActiveLinkEvent(event); return false; }, []); const handleLinkInactive = React.useCallback(() => { setActiveLinkEvent(null); }, []); const handleGoToNextInput = React.useCallback( (insertParagraph: boolean) => { if (insertParagraph && ref.current) { const { view } = ref.current; const { dispatch, state } = view; dispatch(state.tr.insert(0, state.schema.nodes.paragraph.create())); } focusAtStart(); }, [focusAtStart, ref] ); const { document, title, onChangeTitle, isDraft, shareId, readOnly, children, multiplayer, ...rest } = props; const EditorComponent = multiplayer ? MultiplayerEditor : Editor; return ( {!shareId && ( )} {!readOnly && } {activeLinkEvent && !shareId && ( )} {children} ); } export default observer(React.forwardRef(DocumentEditor));