Merge branch 'dev'

This commit is contained in:
Jeff Emmett 2026-03-22 19:29:05 -07:00
commit 90e16d1016
2 changed files with 42 additions and 26 deletions

View File

@ -165,28 +165,29 @@ export class CommentPinManager {
this.createPin(anchor); this.createPin(anchor);
} }
handleCanvasClick(worldX: number, worldY: number) { handleCanvasClick(worldX: number, worldY: number, clientX?: number, clientY?: number) {
if (!this.#placementMode) return false; if (!this.#placementMode) return false;
// Check if clicking on a shape // Check if clicking on a shape — elementFromPoint needs viewport coords
const shapeEl = document.elementFromPoint( let shapeEl: HTMLElement | null = null;
worldX * this.#scale + this.#panX, if (clientX !== undefined && clientY !== undefined) {
worldY * this.#scale + this.#panY, shapeEl = document.elementFromPoint(clientX, clientY)
)?.closest?.("folk-shape, folk-markdown, folk-wrapper, folk-slide, folk-prompt, folk-zine-gen, folk-image-gen, folk-video-gen, folk-embed, folk-chat, folk-rapp") as HTMLElement | null; ?.closest?.("folk-shape, folk-markdown, folk-wrapper, folk-slide, folk-prompt, folk-zine-gen, folk-image-gen, folk-video-gen, folk-embed, folk-chat, folk-rapp") as HTMLElement | null;
}
let anchor: CommentPinAnchor; let anchor: CommentPinAnchor;
if (shapeEl?.id) { if (shapeEl?.id) {
const shapeRect = shapeEl.getBoundingClientRect(); const shapeData = this.#sync.doc.shapes?.[shapeEl.id];
const canvasRect = this.#container.getBoundingClientRect(); if (shapeData) {
// Offset relative to shape origin anchor = {
const shapeWorldX = (shapeRect.left - canvasRect.left - this.#panX) / this.#scale; type: "shape",
const shapeWorldY = (shapeRect.top - canvasRect.top - this.#panY) / this.#scale; shapeId: shapeEl.id,
anchor = { offsetX: worldX - shapeData.x,
type: "shape", offsetY: worldY - shapeData.y,
shapeId: shapeEl.id, };
offsetX: worldX - shapeWorldX, } else {
offsetY: worldY - shapeWorldY, anchor = { type: "canvas", offsetX: worldX, offsetY: worldY };
}; }
} else { } else {
anchor = { type: "canvas", offsetX: worldX, offsetY: worldY }; anchor = { type: "canvas", offsetX: worldX, offsetY: worldY };
} }

View File

@ -4021,6 +4021,8 @@
} }
if (wbTool) setWbTool(null); if (wbTool) setWbTool(null);
if (pendingTool) clearPendingTool(); if (pendingTool) clearPendingTool();
if (typeof exitCommentMode === "function") exitCommentMode();
pinManager.closePopover();
if (connectMode) { if (connectMode) {
connectMode = false; connectMode = false;
canvas.classList.remove("connect-mode"); canvas.classList.remove("connect-mode");
@ -4667,6 +4669,7 @@
function toggleConnectMode() { function toggleConnectMode() {
if (wbTool) setWbTool(null); if (wbTool) setWbTool(null);
if (pendingTool) clearPendingTool(); if (pendingTool) clearPendingTool();
exitCommentMode();
connectMode = !connectMode; connectMode = !connectMode;
canvas.classList.toggle("connect-mode", connectMode); canvas.classList.toggle("connect-mode", connectMode);
if (!connectMode && connectSource) { if (!connectMode && connectSource) {
@ -5153,6 +5156,7 @@
function setWbTool(tool) { function setWbTool(tool) {
wbTool = wbTool === tool ? null : tool; wbTool = wbTool === tool ? null : tool;
if (typeof exitCommentMode === "function") exitCommentMode();
if (wbTool) { if (wbTool) {
canvas.style.cursor = "crosshair"; canvas.style.cursor = "crosshair";
@ -5180,7 +5184,9 @@
function syncBottomToolbar() { function syncBottomToolbar() {
bottomToolBtns.forEach(b => b.classList.remove("active")); bottomToolBtns.forEach(b => b.classList.remove("active"));
if (wbTool) { if (pinManager?.placementMode) {
document.getElementById("tool-comment")?.classList.add("active");
} else if (wbTool) {
const map = { pencil: "tool-pencil", line: "tool-line", rect: "tool-rect", circle: "tool-circle", eraser: "tool-eraser" }; const map = { pencil: "tool-pencil", line: "tool-line", rect: "tool-rect", circle: "tool-circle", eraser: "tool-eraser" };
document.getElementById(map[wbTool])?.classList.add("active"); document.getElementById(map[wbTool])?.classList.add("active");
} else if (connectMode) { } else if (connectMode) {
@ -5202,6 +5208,7 @@
document.getElementById("tool-select").addEventListener("click", () => { document.getElementById("tool-select").addEventListener("click", () => {
if (wbTool) setWbTool(null); if (wbTool) setWbTool(null);
if (pendingTool) clearPendingTool(); if (pendingTool) clearPendingTool();
exitCommentMode();
if (connectMode) { if (connectMode) {
connectMode = false; connectMode = false;
canvas.classList.remove("connect-mode"); canvas.classList.remove("connect-mode");
@ -5232,19 +5239,27 @@
}); });
// ── Comment tool ── // ── Comment tool ──
document.getElementById("tool-comment").addEventListener("click", () => { function exitCommentMode() {
if (pendingTool) clearPendingTool();
setWbTool(null);
if (pinManager.placementMode) { if (pinManager.placementMode) {
pinManager.exitPinPlacementMode(); pinManager.exitPinPlacementMode();
document.getElementById("tool-comment").classList.remove("active"); document.getElementById("tool-comment").classList.remove("active");
}
}
document.getElementById("tool-comment").addEventListener("click", () => {
if (pendingTool) clearPendingTool();
if (wbTool) setWbTool(null);
if (connectMode) {
connectMode = false;
canvas.classList.remove("connect-mode");
if (connectSource) { connectSource.classList.remove("connect-source"); connectSource = null; }
}
if (pinManager.placementMode) {
exitCommentMode();
syncBottomToolbar();
} else { } else {
pinManager.enterPinPlacementMode(); pinManager.enterPinPlacementMode();
bottomToolBtns.forEach(b => b.classList.remove("active"));
document.getElementById("tool-comment").classList.add("active"); document.getElementById("tool-comment").classList.add("active");
// Deactivate other tools
document.querySelectorAll(".tool-btn").forEach(b => {
if (b.id !== "tool-comment") b.classList.remove("active");
});
} }
}); });
@ -5603,7 +5618,7 @@
const rect = canvas.getBoundingClientRect(); const rect = canvas.getBoundingClientRect();
const worldX = (e.clientX - rect.left - panX) / scale; const worldX = (e.clientX - rect.left - panX) / scale;
const worldY = (e.clientY - rect.top - panY) / scale; const worldY = (e.clientY - rect.top - panY) / scale;
pinManager.handleCanvasClick(worldX, worldY); pinManager.handleCanvasClick(worldX, worldY, e.clientX, e.clientY);
document.getElementById("tool-comment").classList.remove("active"); document.getElementById("tool-comment").classList.remove("active");
}, true); }, true);