[fix] Image insertion position at cursor position and Updated placeholder text. (#3224)

* Fix position bug in the UploadImagesPlugin widget decoration and adjust transaction to correctly insert image node and set meta data for image removal.

* Update CSS styles in editor.css to remove margin top and bottom on images and img placeholders and adjust the margin on the table in the editor container.

* Better typescript support for images extension.

Update the `Command` extension in `slash-commands.tsx` to include a `SlashCommandOptions` type for better TS support and allow spaces in the suggestion options and modify the `image` suggestion's search terms to include "img" in addition to "photo", "picture", and "media".
This commit is contained in:
M. Palanikannan 2023-12-22 14:10:42 +05:30 committed by GitHub
parent ac39bb9b1d
commit 1a2186cca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 9 deletions

View File

@ -23,6 +23,8 @@
/* Custom image styles */ /* Custom image styles */
.ProseMirror img { .ProseMirror img {
transition: filter 0.1s ease-in-out; transition: filter 0.1s ease-in-out;
margin-top: 0 !important;
margin-bottom: 0 !important;
&:hover { &:hover {
cursor: pointer; cursor: pointer;
@ -139,6 +141,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
.img-placeholder { .img-placeholder {
position: relative; position: relative;
width: 35%; width: 35%;
margin-top: 0 !important;
margin-bottom: 0 !important;
&:before { &:before {
content: ""; content: "";
@ -165,7 +169,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
table { table {
border-collapse: collapse; border-collapse: collapse;
table-layout: fixed; table-layout: fixed;
margin: 0; margin: 0.5em 0 0.5em 0;
border: 1px solid rgb(var(--color-border-200)); border: 1px solid rgb(var(--color-border-200));
width: 100%; width: 100%;

View File

@ -43,7 +43,7 @@ export const UploadImagesPlugin = (cancelUploadImage?: () => any) =>
cancelButton.appendChild(svgElement); cancelButton.appendChild(svgElement);
placeholder.appendChild(cancelButton); placeholder.appendChild(cancelButton);
const deco = Decoration.widget(pos + 1, placeholder, { const deco = Decoration.widget(pos, placeholder, {
id, id,
}); });
set = set.add(tr.doc, [deco]); set = set.add(tr.doc, [deco]);
@ -131,7 +131,8 @@ export async function startImageUpload(
const imageSrc = typeof src === "object" ? reader.result : src; const imageSrc = typeof src === "object" ? reader.result : src;
const node = schema.nodes.image.create({ src: imageSrc }); const node = schema.nodes.image.create({ src: imageSrc });
const transaction = view.state.tr.replaceWith(pos, pos, node).setMeta(uploadKey, { remove: { id } }); const transaction = view.state.tr.insert(pos - 1, node).setMeta(uploadKey, { remove: { id } });
view.dispatch(transaction); view.dispatch(transaction);
} catch (error) { } catch (error) {
console.error("Upload error: ", error); console.error("Upload error: ", error);

View File

@ -1,6 +1,6 @@
import { useState, useEffect, useCallback, ReactNode, useRef, useLayoutEffect } from "react"; import { useState, useEffect, useCallback, ReactNode, useRef, useLayoutEffect } from "react";
import { Editor, Range, Extension } from "@tiptap/core"; import { Editor, Range, Extension } from "@tiptap/core";
import Suggestion from "@tiptap/suggestion"; import Suggestion, { SuggestionOptions } from "@tiptap/suggestion";
import { ReactRenderer } from "@tiptap/react"; import { ReactRenderer } from "@tiptap/react";
import tippy from "tippy.js"; import tippy from "tippy.js";
import { import {
@ -40,7 +40,11 @@ interface CommandItemProps {
icon: ReactNode; icon: ReactNode;
} }
const Command = Extension.create({ export type SlashCommandOptions = {
suggestion: Omit<SuggestionOptions, "editor">;
};
const Command = Extension.create<SlashCommandOptions>({
name: "slash-command", name: "slash-command",
addOptions() { addOptions() {
return { return {
@ -49,6 +53,10 @@ const Command = Extension.create({
command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => { command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => {
props.command({ editor, range }); props.command({ editor, range });
}, },
allow({ editor }: { editor: Editor }) {
return !editor.isActive("table");
},
allowSpaces: true,
}, },
}; };
}, },
@ -56,9 +64,6 @@ const Command = Extension.create({
return [ return [
Suggestion({ Suggestion({
editor: this.editor, editor: this.editor,
allow({ editor }) {
return !editor.isActive("table");
},
...this.options.suggestion, ...this.options.suggestion,
}), }),
]; ];
@ -175,7 +180,7 @@ const getSuggestionItems =
key: "image", key: "image",
title: "Image", title: "Image",
description: "Upload an image from your computer.", description: "Upload an image from your computer.",
searchTerms: ["photo", "picture", "media"], searchTerms: ["img", "photo", "picture", "media"],
icon: <ImageIcon className="h-3.5 w-3.5" />, icon: <ImageIcon className="h-3.5 w-3.5" />,
command: ({ editor, range }: CommandProps) => { command: ({ editor, range }: CommandProps) => {
insertImageCommand(editor, uploadFile, setIsSubmitting, range); insertImageCommand(editor, uploadFile, setIsSubmitting, range);