fix: Pasting document content in title should behave as expected

This commit is contained in:
Tom Moor
2022-11-16 23:29:29 -05:00
parent 19d33a7658
commit 552c0ecf01
2 changed files with 32 additions and 2 deletions

View File

@@ -118,8 +118,8 @@ const ContentEditable = React.forwardRef(
} }
}, [value, contentRef]); }, [value, contentRef]);
// Ensure only plain text can be pasted into title when pasting from another // Ensure only plain text can be pasted into input when pasting from another
// rich text editor // rich text source
const handlePaste = React.useCallback( const handlePaste = React.useCallback(
(event: React.ClipboardEvent<HTMLSpanElement>) => { (event: React.ClipboardEvent<HTMLSpanElement>) => {
event.preventDefault(); event.preventDefault();

View File

@@ -1,4 +1,5 @@
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Selection } from "prosemirror-state";
import * as React from "react"; import * as React from "react";
import styled from "styled-components"; import styled from "styled-components";
import breakpoint from "styled-components-breakpoint"; import breakpoint from "styled-components-breakpoint";
@@ -11,6 +12,7 @@ import {
import { DocumentValidation } from "@shared/validations"; import { DocumentValidation } from "@shared/validations";
import Document from "~/models/Document"; import Document from "~/models/Document";
import ContentEditable, { RefHandle } from "~/components/ContentEditable"; import ContentEditable, { RefHandle } from "~/components/ContentEditable";
import { useDocumentContext } from "~/components/DocumentContext";
import Star, { AnimatedStar } from "~/components/Star"; import Star, { AnimatedStar } from "~/components/Star";
import useEmojiWidth from "~/hooks/useEmojiWidth"; import useEmojiWidth from "~/hooks/useEmojiWidth";
import { isModKey } from "~/utils/keyboard"; import { isModKey } from "~/utils/keyboard";
@@ -50,6 +52,7 @@ const EditableTitle = React.forwardRef(
}: Props, }: Props,
ref: React.RefObject<RefHandle> ref: React.RefObject<RefHandle>
) => { ) => {
const { editor } = useDocumentContext();
const handleClick = React.useCallback(() => { const handleClick = React.useCallback(() => {
ref.current?.focus(); ref.current?.focus();
}, [ref]); }, [ref]);
@@ -112,6 +115,32 @@ const EditableTitle = React.forwardRef(
[ref, onChange] [ref, onChange]
); );
// Custom paste handling so that if a multiple lines are pasted we
// only take the first line and insert the rest directly into the editor.
const handlePaste = React.useCallback(
(event: React.ClipboardEvent) => {
event.preventDefault();
const text = event.clipboardData.getData("text/plain");
const [firstLine, ...rest] = text.split(`\n`);
const content = rest.join(`\n`).trim();
window.document.execCommand(
"insertText",
false,
firstLine.replace(/^#+\s?/, "")
);
if (editor && content) {
const { view, parser } = editor;
view.dispatch(
view.state.tr
.setSelection(Selection.atStart(view.state.doc))
.insert(0, parser.parse(content))
);
}
},
[editor]
);
const emojiWidth = useEmojiWidth(document.emoji, { const emojiWidth = useEmojiWidth(document.emoji, {
fontSize, fontSize,
lineHeight, lineHeight,
@@ -125,6 +154,7 @@ const EditableTitle = React.forwardRef(
onClick={handleClick} onClick={handleClick}
onChange={handleChange} onChange={handleChange}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onPaste={handlePaste}
onBlur={onBlur} onBlur={onBlur}
placeholder={placeholder} placeholder={placeholder}
value={value} value={value}