Skip to content

Commit a33d713

Browse files
committed
feature/COMPASS-9655 add getCoordinatesForNewNode
1 parent f9f288c commit a33d713

File tree

3 files changed

+82
-22
lines changed

3 files changed

+82
-22
lines changed

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from '@/components/diagram';
22
export * from '@/utilities/apply-layout';
33
export * from '@/utilities/add-nodes-within-bounds';
4+
export { getCoordinatesForNewNode } from '@/utilities/get-coordinates-for-new-node';
45
export * from '@/utilities/get-nodes-bounds';
56
export * from '@/types';
67
export { useDiagram, type DiagramInstance } from '@/hooks/use-diagram';
Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { DEFAULT_NODE_HEIGHT, DEFAULT_NODE_SPACING, DEFAULT_NODE_WIDTH } from '@/utilities/constants';
2-
import { BaseNode } from '@/types/layout';
1+
import type { BaseNode } from '@/types/layout';
2+
3+
import { getNodeWidth, getNodeHeight } from './node-dimensions';
4+
import { getCoordinatesForNewNodeFromMaxDimensions } from './get-coordinates-for-new-node';
35

46
/**
57
* Adds new nodes to an existing array of nodes, positioning them in a grid pattern.
@@ -14,28 +16,14 @@ import { BaseNode } from '@/types/layout';
1416
* @param newNodes A list of new nodes to add within the bounds of the diagram.
1517
*/
1618
export const addNodesWithinBounds = <N extends BaseNode>(nodes: N[], newNodes: N[]) => {
17-
const maxWidth = Math.max(0, ...nodes.map(n => n.position.x + (n.measured?.width || DEFAULT_NODE_WIDTH)));
18-
const maxHeight = Math.max(0, ...nodes.map(n => n.position.y + (n.measured?.height || DEFAULT_NODE_HEIGHT)));
19-
20-
let x = 0;
21-
let y = maxHeight + DEFAULT_NODE_SPACING;
22-
let rowHeight = 0;
19+
const maxWidth = Math.max(0, ...nodes.map(n => n.position.x + getNodeWidth(n)));
20+
const maxHeight = Math.max(0, ...nodes.map(n => n.position.y + getNodeHeight(n)));
2321

2422
return [
2523
...nodes,
26-
...newNodes.map(n => {
27-
if (!n.measured || !n.measured.height || !n.measured.width) return n;
28-
29-
if (x + n.measured.width + DEFAULT_NODE_SPACING > maxWidth) {
30-
x = 0;
31-
y += rowHeight + DEFAULT_NODE_SPACING;
32-
rowHeight = 0;
33-
}
34-
35-
x += n.measured.width + DEFAULT_NODE_SPACING;
36-
rowHeight = Math.max(rowHeight, n.measured.height);
37-
38-
return { ...n, position: { x, y } };
39-
}),
24+
...newNodes.map(n => ({
25+
...n,
26+
position: getCoordinatesForNewNodeFromMaxDimensions({ maxWidth, maxHeight, newNode: n }),
27+
})),
4028
];
4129
};
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { DEFAULT_NODE_SPACING } from '@/utilities/constants';
2+
import type { BaseNode } from '@/types/layout';
3+
4+
import { getNodeHeight, getNodeWidth } from './node-dimensions';
5+
6+
/**
7+
* Get coordinates for a new node, positioning it in a grid pattern.
8+
*
9+
* This function takes maximum width and height of the existing nodes
10+
* and then finds place for a new one.
11+
*
12+
* The node is positioned such that it fits within the maximum width of the existing nodes,
13+
* and when the width is exceeded, it wraps to the next row.
14+
*
15+
* @param nodes A list of existing nodes, used to calculate the bounds of the diagram.
16+
* @param newNode A new node to add within the bounds of the diagram.
17+
*/
18+
export const getCoordinatesForNewNodeFromMaxDimensions = <N extends BaseNode>({
19+
maxWidth,
20+
maxHeight,
21+
newNode,
22+
}: {
23+
newNode: N;
24+
maxWidth: number;
25+
maxHeight: number;
26+
}) => {
27+
const newNodeWidth = getNodeWidth(newNode);
28+
const newNodeHeight = getNodeHeight(newNode);
29+
30+
let x = 0;
31+
let y = maxHeight + DEFAULT_NODE_SPACING;
32+
let rowHeight = 0;
33+
34+
if (x + newNodeWidth + DEFAULT_NODE_SPACING > maxWidth) {
35+
x = 0;
36+
y += rowHeight + DEFAULT_NODE_SPACING;
37+
rowHeight = 0;
38+
}
39+
40+
x += newNodeWidth + DEFAULT_NODE_SPACING;
41+
rowHeight = Math.max(rowHeight, newNodeHeight);
42+
43+
return { x, y };
44+
};
45+
46+
/**
47+
* Get coordinates for a new node, positioning it in a grid pattern.
48+
*
49+
* This function calculates the maximum width and height of the existing nodes
50+
* and then finds a place for the new node.
51+
*
52+
* The node is positioned such that it fits within the maximum width of the existing nodes,
53+
* and when the width is exceeded, it wraps to the next row.
54+
*
55+
* @param nodes A list of existing nodes, used to calculate the bounds of the diagram.
56+
* @param newNode A new node to add within the bounds of the diagram.
57+
*/
58+
export const getCoordinatesForNewNode = <N extends BaseNode>(nodes: N[], newNode: N): { x: number; y: number } => {
59+
if (nodes.length === 0) {
60+
return { x: DEFAULT_NODE_SPACING, y: DEFAULT_NODE_SPACING };
61+
}
62+
63+
const maxWidth = Math.max(...nodes.map(node => getNodeWidth(node))) + DEFAULT_NODE_SPACING;
64+
const maxHeight = Math.max(...nodes.map(node => getNodeHeight(node))) + DEFAULT_NODE_SPACING;
65+
66+
return getCoordinatesForNewNodeFromMaxDimensions({
67+
newNode,
68+
maxWidth,
69+
maxHeight,
70+
});
71+
};

0 commit comments

Comments
 (0)