fix: reset content bounds on workflow switch and update stale docs

- Detect workflow switches by sampling a node ID: when the sampled
  node disappears from the map, the entire node set was replaced,
  so reset bounds to prevent unbounded growth across workflows.
- Update @example in useTransformState to reflect direct DOM mutation
  pattern used by TransformPane (replaces deprecated :style binding).
This commit is contained in:
Rizumu Ayaka
2026-04-10 19:49:53 +08:00
parent b0e6942e92
commit 20198f1465
2 changed files with 22 additions and 10 deletions

View File

@@ -47,18 +47,32 @@ const contentBounds = useContentBounds()
const allNodes = layoutStore.getAllNodes()
const storeVersion = layoutStore.getVersion()
let lastTrackedVersion = -1
let sampleNodeId: string | null = null
/**
* When the layout store version changes, expand the tracked content
* bounds to include any nodes that moved beyond the current area.
* Uses grow-only strategy: bounds expand but never shrink.
*
* Detects workflow switches by checking whether a previously tracked
* node still exists. When the entire node set is replaced (e.g. on
* workflow load), resets bounds so they don't accumulate across
* unrelated workflows.
*/
function updateContentBounds() {
const currentVersion = storeVersion.value
if (currentVersion === lastTrackedVersion) return
lastTrackedVersion = currentVersion
for (const [, layout] of allNodes.value) {
const nodes = allNodes.value
// Detect workflow switch: if the sampled node is gone, the node set
// was replaced wholesale — reset bounds to avoid unbounded growth.
if (sampleNodeId !== null && nodes.size > 0 && !nodes.has(sampleNodeId)) {
contentBounds.reset()
}
sampleNodeId = nodes.size > 0 ? nodes.keys().next().value ?? null : null
for (const [, layout] of nodes) {
contentBounds.expandToInclude(layout.bounds)
}
}

View File

@@ -35,15 +35,13 @@
*
* @example
* ```typescript
* const { camera, transformStyle, canvasToScreen } = useTransformState()
* const { camera, syncWithCanvas, canvasToScreen } = useTransformState()
*
* // In template
* <div :style="transformStyle">
* <NodeComponent
* v-for="node in nodes"
* :style="{ left: node.x + 'px', top: node.y + 'px' }"
* />
* </div>
* // Sync camera from LiteGraph each frame (via RAF)
* syncWithCanvas(canvas)
*
* // Apply transform via direct DOM mutation for performance
* el.style.transform = `scale3d(${camera.z}, ${camera.z}, ${camera.z}) translate3d(${camera.x}px, ${camera.y}px, 0)`
*
* // Convert coordinates
* const screenPos = canvasToScreen({ x: nodeX, y: nodeY })