[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:
parent
117afdb67f
commit
20e569294d
5 changed files with 11 additions and 60 deletions
|
|
@ -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,
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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")) &&
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
align-items: center;
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s ease 0.2s;
|
||||
transform: translateX(-50%);
|
||||
|
||||
&.side-menu-hidden {
|
||||
opacity: 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue