@@ -3,16 +3,20 @@ import {
33 ReactFlowInstance ,
44 ConnectionMode ,
55 ReactFlow ,
6- type Edge ,
76} from "@xyflow/react"
8- import { type MouseEvent as ReactMouseEvent , useCallback } from "react"
7+ import { useCallback } from "react"
98import {
109 CustomBackground ,
11- ReconnectConnectionLine ,
1210 AssessmentSelectionDebug ,
1311 ScrollOverlay ,
1412 AlignmentGuides ,
1513} from "@/components"
14+ // Imported DIRECTLY, not via the `@/components` barrel: this component pulls in the
15+ // edge-geometry solver to preview the committed auto route, and the barrel is
16+ // imported by `constants.ts`, so routing it through the barrel forms a
17+ // `constants → components → solver → edgeAnchoring` import cycle that leaves module
18+ // constants undefined at init. The direct path keeps the solver out of the barrel.
19+ import { ConnectionPreviewLine } from "@/components/ConnectionPreviewLine"
1620import { OverlayLayer } from "@/overlay/OverlayLayer"
1721import "@xyflow/react/dist/style.css"
1822// Shared, embed-safe @tumaet/ui primitives + --apollon-/--home- design tokens
@@ -26,6 +30,7 @@ import "@/styles/fonts.css"
2630import "@/styles/app.css"
2731import {
2832 useDiagramStore ,
33+ useEdgeGeometryStore ,
2934 useMetadataStore ,
3035 useOverlayStore ,
3136} from "./store/context"
@@ -36,7 +41,6 @@ import { diagramEdgeTypes } from "./edges"
3641import {
3742 useNodeDragStop ,
3843 useConnect ,
39- useReconnect ,
4044 useElementInteractions ,
4145 useDragOver ,
4246 useNodeDrag ,
@@ -50,37 +54,30 @@ import {
5054 useRemoteDraggingNodes ,
5155 applyDraggingOverlay ,
5256} from "./hooks/useRemoteDraggingNodes"
53- import {
54- getConnectionLineType ,
55- resolveReconnectPreviewBasePoints ,
56- } from "./utils/edgeUtils"
57- import { IPoint } from "./edges/Connection"
57+ import { getConnectionLineType } from "./utils/edgeUtils"
5858import {
5959 CollaborationLayer ,
6060 type CollaborationAwarenessApi ,
6161 type CollaborationLayerOptions ,
6262} from "@/components/collaboration/CollaborationLayer"
6363import { TooltipProvider } from "@/components/ui"
64+ import { EdgeGeometrySolver } from "@/components/EdgeGeometrySolver"
6465
6566interface AppProps {
6667 onReactFlowInit : ( instance : ReactFlowInstance ) => void
6768 collaboration : CollaborationLayerOptions
6869 awareness : CollaborationAwarenessApi
70+ /** Disabled by the off-screen export mount, which must materialize the whole
71+ * model regardless of its synthetic viewport. */
72+ onlyRenderVisibleElements ?: boolean
6973}
7074const proOptions = { hideAttribution : true }
71- const isPointArray = ( value : unknown ) : value is IPoint [ ] =>
72- Array . isArray ( value ) &&
73- value . every (
74- ( point ) =>
75- typeof point === "object" &&
76- point !== null &&
77- "x" in point &&
78- "y" in point &&
79- typeof point . x === "number" &&
80- typeof point . y === "number"
81- )
82-
83- function App ( { onReactFlowInit, collaboration, awareness } : AppProps ) {
75+ function App ( {
76+ onReactFlowInit,
77+ collaboration,
78+ awareness,
79+ onlyRenderVisibleElements = true ,
80+ } : AppProps ) {
8481 useKeyboardShortcuts ( )
8582
8683 const { nodes, onNodesChange, edges, onEdgesChange, diagramId, previewMode } =
@@ -102,8 +99,6 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
10299 scrollEnabled,
103100 keyboardShortcuts,
104101 connectionGuidanceActive,
105- startReconnectPreview,
106- stopReconnectPreview,
107102 } = useMetadataStore (
108103 useShallow ( ( state ) => ( {
109104 diagramType : state . diagramType ,
@@ -112,8 +107,6 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
112107 scrollEnabled : state . scrollEnabled ,
113108 keyboardShortcuts : state . keyboardShortcuts ,
114109 connectionGuidanceActive : state . connectionGuidanceActive ,
115- startReconnectPreview : state . startReconnectPreview ,
116- stopReconnectPreview : state . stopReconnectPreview ,
117110 } ) )
118111 )
119112
@@ -143,11 +136,11 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
143136 const onDragOver = useDragOver ( )
144137 const { onConnect, onConnectEnd, onConnectStart, onEdgesDelete } =
145138 useConnect ( )
146- const onReconnect = useReconnect ( )
147139 const { onBeforeDelete, onNodeDoubleClick, onEdgeDoubleClick } =
148140 useElementInteractions ( )
149141 const { onPaneClicked } = usePaneClicked ( )
150142 const multiSelectionMode = useMultiSelectionMode ( )
143+ const routingReady = useEdgeGeometryStore ( ( state ) => state . routingReady )
151144
152145 const handleReactFlowInit = useCallback (
153146 ( instance : ReactFlowInstance ) => {
@@ -156,25 +149,6 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
156149 [ onReactFlowInit ]
157150 )
158151
159- const handleReconnectStart = useCallback (
160- ( _event : ReactMouseEvent , edge : Edge , handleType : "source" | "target" ) => {
161- const storedPoints = isPointArray ( edge . data ?. points )
162- ? edge . data . points
163- : undefined
164-
165- startReconnectPreview (
166- edge . id ,
167- handleType ,
168- resolveReconnectPreviewBasePoints ( storedPoints , undefined , [ ] )
169- )
170- } ,
171- [ startReconnectPreview ]
172- )
173-
174- const handleReconnectEnd = useCallback ( ( ) => {
175- stopReconnectPreview ( )
176- } , [ stopReconnectPreview ] )
177-
178152 return (
179153 < TooltipProvider >
180154 < div
@@ -205,7 +179,20 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
205179 nodeTypes = { diagramNodeTypes }
206180 edgeTypes = { diagramEdgeTypes }
207181 nodes = { displayNodes }
208- edges = { edges }
182+ // The solver reads DiagramStore directly. Keep provisional React
183+ // Flow edges unmounted until this model's first exact generation;
184+ // nodes still mount below so their runtime handles can be measured.
185+ edges = { routingReady ? edges : [ ] }
186+ // React Flow's viewport culling keeps large off-screen diagrams out
187+ // of the DOM while the central solver still optimizes every edge.
188+ // This is purely a rendering boundary: export and exact geometry
189+ // continue to use the complete diagram.
190+ // Bootstrap one complete measurement pass before enabling viewport
191+ // culling. Otherwise off-screen nodes never mount their handles and
192+ // the holistic router cannot produce a stable first generation.
193+ onlyRenderVisibleElements = {
194+ routingReady ? onlyRenderVisibleElements : false
195+ }
209196 onDragOver = { onDragOver }
210197 onNodesChange = { onNodesChange }
211198 onEdgesChange = { onEdgesChange }
@@ -216,11 +203,8 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
216203 zoomOnDoubleClick = { false }
217204 onNodeDrag = { onNodeDrag }
218205 onNodeDragStop = { onNodeDragStop }
219- onReconnect = { onReconnect }
220- onReconnectStart = { handleReconnectStart }
221- onReconnectEnd = { handleReconnectEnd }
222206 connectionLineType = { connectionLineType }
223- connectionLineComponent = { ReconnectConnectionLine }
207+ connectionLineComponent = { ConnectionPreviewLine }
224208 connectionMode = { ConnectionMode . Loose }
225209 // Lift the selected edge (and its bend/endpoint handles) above other
226210 // edges so an overlapping edge's interaction ribbon can't steal the
@@ -244,7 +228,7 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
244228 onBeforeDelete = { onBeforeDelete }
245229 onPaneClick = { onPaneClicked }
246230 proOptions = { proOptions }
247- edgesReconnectable = { isDiagramModifiable }
231+ edgesReconnectable = { false }
248232 nodesConnectable = { isDiagramModifiable }
249233 nodesDraggable = { isDiagramModifiable }
250234 panOnScroll = { ! scrollLock || scrollEnabled }
@@ -278,6 +262,7 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
278262 < CustomBackground />
279263 < AlignmentGuides />
280264 < AssessmentSelectionDebug />
265+ < EdgeGeometrySolver />
281266 { /* Renders every registered control (built-in + host-injected) into
282267 its region: header, rails, corners, on-canvas. The chrome itself is
283268 registered at construction (imperative) or by the React wrapper. */ }
0 commit comments