mobile support
This commit is contained in:
@@ -211,23 +211,80 @@ export const Mermaid = Node.create({
|
|||||||
// Run validation
|
// Run validation
|
||||||
validateSyntax();
|
validateSyntax();
|
||||||
|
|
||||||
// Edit button overlay
|
// Edit button overlay - visible on mobile tap/selection, hover on desktop
|
||||||
const editBtn = document.createElement("button");
|
const editBtn = document.createElement("button");
|
||||||
editBtn.className =
|
editBtn.className =
|
||||||
"absolute top-2 right-2 bg-blue text-white px-3 py-1 rounded text-sm opacity-0 group-hover:opacity-100 transition-opacity duration-200 z-10";
|
"absolute top-2 right-2 bg-blue text-white px-3 py-1 rounded text-sm opacity-0 group-hover:opacity-100 transition-opacity duration-200 z-10 touch-manipulation";
|
||||||
editBtn.textContent = "Edit Diagram";
|
editBtn.textContent = "Edit Diagram";
|
||||||
editBtn.contentEditable = "false";
|
editBtn.contentEditable = "false";
|
||||||
|
|
||||||
editBtn.addEventListener("click", (e) => {
|
const openEditor = () => {
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
// Emit custom event to open modal
|
|
||||||
const pos = typeof getPos === "function" ? getPos() : 0;
|
const pos = typeof getPos === "function" ? getPos() : 0;
|
||||||
const event = new CustomEvent("edit-mermaid", {
|
const event = new CustomEvent("edit-mermaid", {
|
||||||
detail: { content: node.attrs.content, pos }
|
detail: { content: node.attrs.content, pos }
|
||||||
});
|
});
|
||||||
editor.view.dom.dispatchEvent(event);
|
editor.view.dom.dispatchEvent(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
editBtn.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
openEditor();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mobile support: Show button when node is selected (tapped)
|
||||||
|
let isSelected = false;
|
||||||
|
const updateButtonVisibility = () => {
|
||||||
|
if (typeof getPos !== "function") return;
|
||||||
|
|
||||||
|
const pos = getPos();
|
||||||
|
const { from, to } = editor.state.selection;
|
||||||
|
|
||||||
|
// Check if this node is selected
|
||||||
|
const nodeIsSelected = from === pos && to === pos + node.nodeSize;
|
||||||
|
|
||||||
|
if (nodeIsSelected !== isSelected) {
|
||||||
|
isSelected = nodeIsSelected;
|
||||||
|
if (isSelected) {
|
||||||
|
// Show button when selected (for mobile)
|
||||||
|
editBtn.style.opacity = "1";
|
||||||
|
} else {
|
||||||
|
// Hide button when not selected (reset to CSS control)
|
||||||
|
editBtn.style.opacity = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for selection changes
|
||||||
|
const plugin = editor.view.state.plugins.find(
|
||||||
|
(p: any) => p.spec?.key === "mermaidSelection"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use intersection observer to trigger update when visible
|
||||||
|
let updateInterval: ReturnType<typeof setInterval> | null = null;
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
// Check selection periodically when visible
|
||||||
|
updateInterval = setInterval(updateButtonVisibility, 100);
|
||||||
|
} else {
|
||||||
|
// Stop checking when not visible
|
||||||
|
if (updateInterval) {
|
||||||
|
clearInterval(updateInterval);
|
||||||
|
updateInterval = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ threshold: 0.01 }
|
||||||
|
);
|
||||||
|
|
||||||
|
observer.observe(dom);
|
||||||
|
|
||||||
|
// Also check on touch
|
||||||
|
dom.addEventListener("touchstart", () => {
|
||||||
|
setTimeout(updateButtonVisibility, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
dom.appendChild(pre);
|
dom.appendChild(pre);
|
||||||
@@ -244,7 +301,14 @@ export const Mermaid = Node.create({
|
|||||||
code.textContent = updatedNode.attrs.content || "";
|
code.textContent = updatedNode.attrs.content || "";
|
||||||
// Re-validate on update
|
// Re-validate on update
|
||||||
validateSyntax();
|
validateSyntax();
|
||||||
|
updateButtonVisibility();
|
||||||
return true;
|
return true;
|
||||||
|
},
|
||||||
|
destroy: () => {
|
||||||
|
if (updateInterval) {
|
||||||
|
clearInterval(updateInterval);
|
||||||
|
}
|
||||||
|
observer.disconnect();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user