fix: reposition cards inside devices after dagre auto-layout
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
X6 setPosition() does not translate children, so after dagre moves devices, cards stay at old absolute positions. Add fixDeviceChildren() that ensures device height fits visible cards and repositions each card at the correct offset within its parent device. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -4,6 +4,9 @@ import { LAYER_MAPPING } from '../../../constants/layer-mapping';
|
|||||||
import {
|
import {
|
||||||
SITE_PADDING,
|
SITE_PADDING,
|
||||||
SITE_HEADER_HEIGHT,
|
SITE_HEADER_HEIGHT,
|
||||||
|
DEVICE_HEADER_HEIGHT,
|
||||||
|
DEVICE_MIN_HEIGHT,
|
||||||
|
CARD_HEIGHT,
|
||||||
} from '../../../constants/sizes';
|
} from '../../../constants/sizes';
|
||||||
|
|
||||||
function getLayerForCategory(category: string): number {
|
function getLayerForCategory(category: string): number {
|
||||||
@ -137,6 +140,45 @@ function layoutSiteDevices(
|
|||||||
return { minX, minY, maxX, maxY };
|
return { minX, minY, maxX, maxY };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix device children after dagre layout:
|
||||||
|
* 1. Ensure device height accommodates all visible cards
|
||||||
|
* 2. Reposition card-nodes at correct absolute positions inside devices
|
||||||
|
*
|
||||||
|
* setPosition() in X6 does NOT translate children, so cards stay
|
||||||
|
* at their old positions when a device moves — this function corrects that.
|
||||||
|
*/
|
||||||
|
function fixDeviceChildren(graph: Graph): void {
|
||||||
|
for (const device of graph.getNodes()) {
|
||||||
|
if (device.shape === 'site-node' || device.shape === 'card-node') continue;
|
||||||
|
|
||||||
|
const cards = (device.getChildren() ?? []).filter(
|
||||||
|
(c): c is Node => c.isNode() && c.shape === 'card-node' && c.isVisible(),
|
||||||
|
);
|
||||||
|
if (cards.length === 0) continue;
|
||||||
|
|
||||||
|
const data = device.getData<{ collapsed?: boolean }>();
|
||||||
|
if (data?.collapsed) continue;
|
||||||
|
|
||||||
|
// Ensure device is tall enough for its visible cards
|
||||||
|
const size = device.getSize();
|
||||||
|
const cardsHeight = cards.length * (CARD_HEIGHT + 4) + 4;
|
||||||
|
const minHeight = Math.max(DEVICE_MIN_HEIGHT, DEVICE_HEADER_HEIGHT + cardsHeight + 6);
|
||||||
|
if (size.height < minHeight) {
|
||||||
|
device.resize(size.width, minHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place each card at the correct absolute position
|
||||||
|
const pos = device.getPosition();
|
||||||
|
for (let i = 0; i < cards.length; i++) {
|
||||||
|
cards[i].setPosition(
|
||||||
|
pos.x + 10,
|
||||||
|
pos.y + DEVICE_HEADER_HEIGHT + 4 + i * (CARD_HEIGHT + 4),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getDeviceChildren(siteNode: Node): Node[] {
|
function getDeviceChildren(siteNode: Node): Node[] {
|
||||||
return (siteNode.getChildren() ?? []).filter(
|
return (siteNode.getChildren() ?? []).filter(
|
||||||
(c): c is Node =>
|
(c): c is Node =>
|
||||||
@ -264,5 +306,7 @@ export function applyDagreLayout(graph: Graph): void {
|
|||||||
cursorY = rootSiteY + rootSiteH + siteGap;
|
cursorY = rootSiteY + rootSiteH + siteGap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixDeviceChildren(graph);
|
||||||
|
|
||||||
graph.stopBatch('dagre-layout');
|
graph.stopBatch('dagre-layout');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user