Skip to content

Commit e52fd8c

Browse files
committed
Fix circular-dep TDZ crash and picker alias mismatch
Move coerceBrokenShape() and the broken-shape set into vertexStylesTransform.ts so the import from storageAtoms is type-only into graphStyles.ts, breaking the runtime cycle that caused a ReferenceError during initialization. Change the coercion target from "round-rectangle" to "roundrectangle" (the value NODE_SHAPE uses for the picker) so the style dialog displays "Round Rectangle" instead of a blank field for coerced entries.
1 parent 8790caa commit e52fd8c

6 files changed

Lines changed: 39 additions & 38 deletions

File tree

packages/graph-explorer/src/core/StateProvider/graphStyles.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { DbState, renderHookWithState } from "@/utils/testing";
88
import {
99
appDefaultEdgeStyle,
1010
appDefaultVertexStyle,
11-
coerceBrokenShape,
1211
edgeStyleAtom,
1312
type EdgeStyleStorage,
1413
type ShapeStyle,
@@ -17,6 +16,7 @@ import {
1716
vertexStyleAtom,
1817
type VertexStyleStorage,
1918
} from "./graphStyles";
19+
import { coerceBrokenShape } from "./vertexStylesTransform";
2020

2121
function createExpectedVertex(existing: VertexStyleStorage) {
2222
return {
@@ -473,13 +473,14 @@ describe("coerceBrokenShape", () => {
473473
"round-tag",
474474
];
475475

476-
it.each(BROKEN)("coerces %s to round-rectangle", shape => {
477-
expect(coerceBrokenShape(shape)).toBe("round-rectangle");
476+
it.each(BROKEN)("coerces %s to roundrectangle", shape => {
477+
expect(coerceBrokenShape(shape)).toBe("roundrectangle");
478478
});
479479

480480
const SAFE: ShapeStyle[] = [
481481
"ellipse",
482482
"rectangle",
483+
"roundrectangle",
483484
"round-rectangle",
484485
"round-diamond",
485486
"star",

packages/graph-explorer/src/core/StateProvider/graphStyles.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,31 +45,6 @@ export const SHAPE_STYLES = [
4545
] as const;
4646
export type ShapeStyle = (typeof SHAPE_STYLES)[number];
4747

48-
/**
49-
* Shapes that cytoscape's round-polygon renderer draws incorrectly at small
50-
* node size (24px): their corner computation degenerates, rendering as a blob
51-
* and producing invalid edge endpoints that cause edges to disappear. These are
52-
* kept in {@link SHAPE_STYLES} so older files still parse, but are coerced to
53-
* `round-rectangle` at every read boundary.
54-
*/
55-
const BROKEN_ROUND_POLYGON_SHAPES: ReadonlySet<ShapeStyle> = new Set([
56-
"round-triangle",
57-
"round-pentagon",
58-
"round-hexagon",
59-
"round-heptagon",
60-
"round-octagon",
61-
"round-tag",
62-
]);
63-
64-
const BROKEN_SHAPE_REPLACEMENT: ShapeStyle = "round-rectangle";
65-
66-
/** Coerces a broken round-polygon shape to `round-rectangle`, passing all others through. */
67-
export function coerceBrokenShape(shape: ShapeStyle): ShapeStyle {
68-
return BROKEN_ROUND_POLYGON_SHAPES.has(shape)
69-
? BROKEN_SHAPE_REPLACEMENT
70-
: shape;
71-
}
72-
7348
export const LINE_STYLES = ["solid", "dashed", "dotted"] as const;
7449
export type LineStyle = (typeof LINE_STYLES)[number];
7550

packages/graph-explorer/src/core/StateProvider/vertexStylesTransform.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ describe("transformVertexStyles", () => {
3838
for (const shape of broken) {
3939
const styles = vertexMap([["X", { shape }]]);
4040
const result = transformVertexStyles(styles);
41-
expect(result.get(createVertexType("X"))!.shape).toBe("round-rectangle");
41+
expect(result.get(createVertexType("X"))!.shape).toBe("roundrectangle");
4242
}
4343
});
4444

45-
it("does not coerce round-rectangle or round-diamond", () => {
45+
it("does not coerce roundrectangle, round-rectangle, or round-diamond", () => {
4646
const styles = vertexMap([
47-
["A", { shape: "round-rectangle" }],
48-
["B", { shape: "round-diamond" }],
47+
["A", { shape: "roundrectangle" }],
48+
["B", { shape: "round-rectangle" }],
49+
["C", { shape: "round-diamond" }],
4950
]);
5051

5152
expect(transformVertexStyles(styles)).toBe(styles);
@@ -58,7 +59,7 @@ describe("transformVertexStyles", () => {
5859

5960
const result = transformVertexStyles(styles);
6061
const entry = result.get(createVertexType("A"))!;
61-
expect(entry.shape).toBe("round-rectangle");
62+
expect(entry.shape).toBe("roundrectangle");
6263
expect(entry.color).toBe("#ff0000");
6364
expect(entry.borderWidth).toBe(2);
6465
});

packages/graph-explorer/src/core/StateProvider/vertexStylesTransform.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
import type { VertexType } from "../entities";
2+
import type { ShapeStyle, VertexStyleStorage } from "./graphStyles";
23

3-
import { coerceBrokenShape, type VertexStyleStorage } from "./graphStyles";
4+
/**
5+
* Shapes that cytoscape's round-polygon renderer draws incorrectly at small
6+
* node size (24px): their corner computation degenerates, rendering as a blob
7+
* and producing invalid edge endpoints that cause edges to disappear. These are
8+
* kept in {@link SHAPE_STYLES} so older files still parse, but are coerced to
9+
* `round-rectangle` at every read boundary.
10+
*/
11+
const BROKEN_ROUND_POLYGON_SHAPES: ReadonlySet<ShapeStyle> = new Set([
12+
"round-triangle",
13+
"round-pentagon",
14+
"round-hexagon",
15+
"round-heptagon",
16+
"round-octagon",
17+
"round-tag",
18+
]);
19+
20+
const BROKEN_SHAPE_REPLACEMENT: ShapeStyle = "roundrectangle";
21+
22+
/** Coerces a broken round-polygon shape to `round-rectangle`, passing all others through. */
23+
export function coerceBrokenShape(shape: ShapeStyle): ShapeStyle {
24+
return BROKEN_ROUND_POLYGON_SHAPES.has(shape)
25+
? BROKEN_SHAPE_REPLACEMENT
26+
: shape;
27+
}
428

529
/**
630
* ReadTransform for vertex style maps: coerces broken round-polygon shapes to

packages/graph-explorer/src/core/styling/stylingParser.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,19 @@ describe("style enum validation", () => {
7878
vertices: { A: { shape } },
7979
edges: {},
8080
});
81-
const expected = BROKEN_SHAPES.has(shape) ? "round-rectangle" : shape;
81+
const expected = BROKEN_SHAPES.has(shape) ? "roundrectangle" : shape;
8282
expect(result.vertexStyles.get(createVertexType("A"))!.shape).toBe(
8383
expected,
8484
);
8585
});
8686

87-
test("coerces broken round-polygon shapes to round-rectangle on import", () => {
87+
test("coerces broken round-polygon shapes to roundrectangle on import", () => {
8888
const result = parseStylingPayload({
8989
vertices: { A: { shape: "round-tag" } },
9090
edges: {},
9191
});
9292
expect(result.vertexStyles.get(createVertexType("A"))!.shape).toBe(
93-
"round-rectangle",
93+
"roundrectangle",
9494
);
9595
});
9696

packages/graph-explorer/src/core/styling/stylingParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import { createEdgeType, createVertexType } from "@/core/entities";
88
import { FileEnvelopeError } from "@/core/fileEnvelope";
99
import {
1010
ARROW_STYLES,
11-
coerceBrokenShape,
1211
type EdgeStyleStorage,
1312
LINE_STYLES,
1413
SHAPE_STYLES,
1514
type VertexStyleStorage,
1615
} from "@/core/StateProvider/graphStyles";
16+
import { coerceBrokenShape } from "@/core/StateProvider/vertexStylesTransform";
1717
import { typedEntries } from "@/utils";
1818

1919
// --- Format identity ---

0 commit comments

Comments
 (0)