diff --git a/packages/vue/src/canvas/text-edit/input.ts b/packages/vue/src/canvas/text-edit/input.ts index 9f1c32037..3667e9ab4 100644 --- a/packages/vue/src/canvas/text-edit/input.ts +++ b/packages/vue/src/canvas/text-edit/input.ts @@ -45,6 +45,11 @@ export function createTextEditInput(options: TextEditInputOptions) { const localY = cy - abs.y if (localX < 0 || localY < 0 || localX > editNode.width || localY > editNode.height) { editor.commitTextEdit() + const hit = hitTestInScope(cx, cy, true) + if (hit?.type === 'TEXT' && hit.id !== editNode.id) { + startTextEditingAt(hit, cx, cy) + return true + } return false } if (getClickCount() >= 3) { diff --git a/tests/e2e/text/double-click-edit.spec.ts b/tests/e2e/text/double-click-edit.spec.ts index c04f672fa..904893130 100644 --- a/tests/e2e/text/double-click-edit.spec.ts +++ b/tests/e2e/text/double-click-edit.spec.ts @@ -3,6 +3,23 @@ import { expect, test, type Page } from '@playwright/test' import { CanvasHelper } from '#tests/helpers/canvas' import { getEditingTextId } from '#tests/helpers/store' +async function addTwoTopLevelTexts(page: Page) { + return page.evaluate(() => { + const store = window.openPencil?.getStore?.() + if (!store) throw new Error('OpenPencil store not initialized') + store.state.zoom = 1 + store.state.panX = 0 + store.state.panY = 0 + const first = store.createShape('TEXT', 200, 200, 150, 30) + const second = store.createShape('TEXT', 200, 250, 150, 30) + store.graph.updateNode(first, { text: 'First label', fontSize: 18 }) + store.graph.updateNode(second, { text: 'Second label', fontSize: 18 }) + store.select([first]) + store.requestRender() + return { first, second } + }) +} + async function addTopLevelText(page: Page) { return page.evaluate(() => { const store = window.openPencil?.getStore?.() @@ -65,6 +82,22 @@ test('double-clicking top-level text enters text edit mode', async ({ page }) => await expect.poll(() => getEditingTextId(page), { timeout: 3000 }).toBe(textId) }) +test('single-clicking another text switches text edit target', async ({ page }) => { + await page.goto('/') + const canvas = new CanvasHelper(page) + await canvas.waitForInit() + canvas.errors.length = 0 + await canvas.clearCanvas() + + const ids = await addTwoTopLevelTexts(page) + await canvas.waitForRender() + await canvas.dblclick(245, 215) + await expect.poll(() => getEditingTextId(page), { timeout: 3000 }).toBe(ids.first) + + await canvas.click(250, 265) + await expect.poll(() => getEditingTextId(page), { timeout: 3000 }).toBe(ids.second) +}) + test('double-click drill enters nested text edit mode', async ({ page }) => { await page.goto('/') const canvas = new CanvasHelper(page)