[WEB-2528] fix: side menu rendering even if created already (#5687)

* fix: side menu rendering even if created already

* fix: drag handles position
This commit is contained in:
M. Palanikannan 2024-09-24 20:11:49 +05:30 committed by GitHub
parent 117afdb67f
commit 20e569294d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 11 additions and 60 deletions

View file

@ -145,7 +145,7 @@ export const CustomImageBlock: React.FC<CustomImageNodeViewProps> = (props) => {
src={src}
width={size.width}
height={size.height}
className={cn("block rounded-md", {
className={cn("image-component block rounded-md", {
hidden: isShimmerVisible,
"read-only-image": !editor.isEditable,
})}

View file

@ -78,10 +78,11 @@ const SideMenu = (options: SideMenuPluginProps) => {
hideSideMenu();
view?.dom.parentElement?.appendChild(editorSideMenu);
// side menu elements' initialization
if (handlesConfig.ai) {
if (handlesConfig.ai && !editorSideMenu.querySelector("#ai-handle")) {
aiHandleView(view, editorSideMenu);
}
if (handlesConfig.dragDrop) {
if (handlesConfig.dragDrop && !editorSideMenu.querySelector("#drag-handle")) {
dragHandleView(view, editorSideMenu);
}
@ -113,6 +114,10 @@ const SideMenu = (options: SideMenuPluginProps) => {
rect.top += (lineHeight - 20) / 2;
rect.top += paddingTop;
if (handlesConfig.ai) {
rect.left -= 20;
}
if (node.parentElement?.parentElement?.matches("td") || node.parentElement?.parentElement?.matches("th")) {
if (node.matches("ul:not([data-type=taskList]) li, ol li")) {
rect.left -= 5;

View file

@ -2,45 +2,12 @@ import { NodeSelection } from "@tiptap/pm/state";
import { EditorView } from "@tiptap/pm/view";
// extensions
import { SideMenuHandleOptions, SideMenuPluginProps } from "@/extensions";
// plugins
import { nodeDOMAtCoords } from "@/plugins/drag-handle";
const sparklesIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/></svg>';
const nodeDOMAtCoords = (coords: { x: number; y: number }) => {
const elements = document.elementsFromPoint(coords.x, coords.y);
const generalSelectors = [
"li",
"p:not(:first-child)",
".code-block",
"blockquote",
"img",
"h1, h2, h3, h4, h5, h6",
"[data-type=horizontalRule]",
".table-wrapper",
".issue-embed",
].join(", ");
for (const elem of elements) {
if (elem.matches("p:first-child") && elem.parentElement?.matches(".ProseMirror")) {
return elem;
}
// if the element is a <p> tag that is the first child of a td or th
if (
(elem.matches("td > p:first-child") || elem.matches("th > p:first-child")) &&
elem?.textContent?.trim() !== ""
) {
return elem; // Return only if p tag is not empty in td or th
}
// apply general selector
if (elem.matches(generalSelectors)) {
return elem;
}
}
return null;
};
const nodePosAtDOM = (node: Element, view: EditorView, options: SideMenuPluginProps) => {
const boundingRect = node.getBoundingClientRect();

View file

@ -37,39 +37,19 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => {
"p:not(:first-child)",
".code-block",
"blockquote",
"img",
"h1, h2, h3, h4, h5, h6",
"[data-type=horizontalRule]",
".table-wrapper",
".issue-embed",
".image-component",
".image-upload-component",
].join(", ");
const hasNestedImg = (el: Element): boolean => {
if (el.tagName.toLowerCase() === "img") return true;
// @ts-expect-error todo
for (const child of el.children) {
if (hasNestedImg(child)) return true;
}
return false;
};
for (const elem of elements) {
const elemHasNestedImg = hasNestedImg(elem);
if (elem.matches("p:first-child") && elem.parentElement?.matches(".ProseMirror")) {
return elem;
}
// if the element is a <p> tag and has a nested img i.e. the new image
// component
if (elem.matches("p") && elemHasNestedImg) {
return null;
}
if (elem.matches("div") && elemHasNestedImg) {
return elem;
}
// if the element is a <p> tag that is the first child of a td or th
if (
(elem.matches("td > p:first-child") || elem.matches("th > p:first-child")) &&

View file

@ -5,7 +5,6 @@
align-items: center;
opacity: 1;
transition: opacity 0.2s ease 0.2s;
transform: translateX(-50%);
&.side-menu-hidden {
opacity: 0;