Skip to content

Commit 0ec6769

Browse files
committed
feat: keep node position after expand
1 parent 52d4e3b commit 0ec6769

File tree

6 files changed

+47
-20
lines changed

6 files changed

+47
-20
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mind-elixir",
3-
"version": "5.0.5",
3+
"version": "5.0.6",
44
"type": "module",
55
"description": "Mind elixir is a free open source mind map core.",
66
"keywords": [

src/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ function MindElixir(
9595
// infrastructure
9696
const canvas = $d.createElement('div') // map-canvas Element
9797
canvas.className = 'map-canvas'
98-
setTimeout(() => {
99-
// prevent map move when initialized
100-
canvas.style.transition = 'all 0.3s'
101-
}, 300)
10298
this.map = canvas
10399
this.container.setAttribute('tabindex', '0')
104100
this.container.appendChild(this.map)

src/interact.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const scrollIntoView = function (this: MindElixirInstance, el: HTMLElemen
2929
const containerCenterY = containerRect.top + containerRect.height / 2
3030
const offsetX = elCenterX - containerCenterX
3131
const offsetY = elCenterY - containerCenterY
32-
this.move(-offsetX, -offsetY)
32+
this.move(-offsetX, -offsetY, true)
3333
}
3434
}
3535

@@ -154,14 +154,21 @@ export const scaleFit = function (this: MindElixirInstance) {
154154
/**
155155
* Move the map by `dx` and `dy`.
156156
*/
157-
export const move = function (this: MindElixirInstance, dx: number, dy: number) {
157+
export const move = function (this: MindElixirInstance, dx: number, dy: number, smooth = false) {
158158
const { map, scaleVal, bus } = this
159159
const transform = map.style.transform
160160
let { x, y } = getTranslate(transform)
161161
x += dx
162162
y += dy
163163

164+
if (smooth) {
165+
map.style.transition = 'transform 0.3s'
166+
setTimeout(() => {
167+
map.style.transition = 'none'
168+
}, 300)
169+
}
164170
map.style.transform = `translate(${x}px, ${y}px) scale(${scaleVal})`
171+
165172
bus.fire('move', { dx, dy })
166173
}
167174

@@ -310,6 +317,14 @@ export const expandNode = function (this: MindElixirInstance, el: Topic, isExpan
310317
} else {
311318
node.expanded = true
312319
}
320+
321+
// Calculate position before expansion
322+
const expanderRect = el.getBoundingClientRect()
323+
const beforePosition = {
324+
x: expanderRect.left,
325+
y: expanderRect.top,
326+
}
327+
313328
const parent = el.parentNode
314329
const expander = parent.children[1]!
315330
expander.expanded = node.expanded
@@ -331,22 +346,40 @@ export const expandNode = function (this: MindElixirInstance, el: Topic, isExpan
331346

332347
this.linkDiv(el.closest('me-main > me-wrapper') as Wrapper)
333348

334-
// scroll into view if the node is out of view
335-
const elRect = el.getBoundingClientRect()
336-
const containerRect = this.container.getBoundingClientRect()
337-
const isOutOfView =
338-
elRect.bottom > containerRect.bottom || elRect.top < containerRect.top || elRect.right > containerRect.right || elRect.left < containerRect.left
339-
if (isOutOfView) {
340-
this.scrollIntoView(el)
349+
// Calculate position after expansion and compensate for drift
350+
const afterRect = el.getBoundingClientRect()
351+
const afterPosition = {
352+
x: afterRect.left,
353+
y: afterRect.top,
341354
}
342355

356+
// Calculate the drift and move to compensate
357+
const driftX = beforePosition.x - afterPosition.x
358+
const driftY = beforePosition.y - afterPosition.y
359+
360+
this.move(driftX, driftY)
361+
343362
this.bus.fire('expandNode', node)
344363
}
345364

346365
export const expandNodeAll = function (this: MindElixirInstance, el: Topic, isExpand?: boolean) {
347366
const node = el.nodeObj
367+
const beforeRect = el.getBoundingClientRect()
368+
const beforePosition = {
369+
x: beforeRect.left,
370+
y: beforeRect.top,
371+
}
348372
setExpand(node, isExpand ?? !node.expanded)
349373
this.refresh()
374+
const afterRect = this.findEle(node.id).getBoundingClientRect()
375+
const afterPosition = {
376+
x: afterRect.left,
377+
y: afterRect.top,
378+
}
379+
const driftX = beforePosition.x - afterPosition.x
380+
const driftY = beforePosition.y - afterPosition.y
381+
382+
this.move(driftX, driftY)
350383
}
351384

352385
/**

src/mouse.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ export default function (mind: MindElixirInstance) {
8585
if (target.className === 'circle') return
8686
if (target.contentEditable !== 'plaintext-only') {
8787
dragMoveHelper.mousedown = true
88-
mind.map.style.transition = 'none'
8988
// Capture pointer to ensure we receive all pointer events even if pointer moves outside the element
9089
target.setPointerCapture(e.pointerId)
9190
}
@@ -143,9 +142,7 @@ export default function (mind: MindElixirInstance) {
143142
} else if (e.shiftKey) {
144143
mind.move(-e.deltaY, 0)
145144
} else {
146-
mind.map.style.transition = 'none'
147145
mind.move(-e.deltaX, -e.deltaY)
148-
mind.map.style.transition = 'transform 0.3s'
149146
}
150147
}
151148

src/utils/dragMoveHelper.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export function createDragMoveHelper(mei: MindElixirInstance) {
1414
},
1515
clear() {
1616
this.mousedown = false
17-
mei.map.style.transition = 'transform 0.3s'
1817
},
1918
}
2019
}

tests/expand-collapse.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,10 @@ test('Expand all children recursively', async ({ page, me }) => {
109109
await expect(page.getByText('Child 2', { exact: true })).not.toBeVisible()
110110
await expect(page.getByText('Grandchild 1', { exact: true })).not.toBeVisible()
111111

112-
// Double-click expand button for recursive expansion
113-
await branch1Button.dblclick()
112+
// Ctrl click for recursive expansion
113+
await page.keyboard.down("Control");
114+
await branch1Button.click()
115+
await page.keyboard.up("Control");
114116

115117
// Verify all levels of child nodes are visible
116118
await expect(page.getByText('Child 1', { exact: true })).toBeVisible()

0 commit comments

Comments
 (0)