Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2846899097 | |||
| 2ddd30e7bb | |||
| 866bc1de18 | |||
| 23d631c4f0 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1237,6 +1237,22 @@ ${linksYaml}`;
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getRotatableNodeHandleDirection = (node, handleId) => {
|
||||||
|
if (!node || !handleId) return null;
|
||||||
|
if (node.type !== 'rotatableNode' && !(!node.data?.elementType && node.data?.componentName)) return null;
|
||||||
|
const ports = node.data && node.data.ports;
|
||||||
|
if (!ports || !ports[handleId]) return null;
|
||||||
|
const boxSize = normalizeBoxSize({ box_size: node.data && node.data.boxSize }, DEFAULT_COMPONENT_BOX_SIZE);
|
||||||
|
const handles = buildPortHandles(ports, {
|
||||||
|
rotation: Number((node.data && node.data.rotation) || 0),
|
||||||
|
flip: Boolean(node.data && node.data.flip),
|
||||||
|
flop: Boolean(node.data && node.data.flop),
|
||||||
|
boxSize
|
||||||
|
});
|
||||||
|
const found = handles.find(handle => handle.name === handleId);
|
||||||
|
return found ? found.position : null;
|
||||||
|
};
|
||||||
|
|
||||||
// Backward-compatible alias for same-type route crossing validation.
|
// Backward-compatible alias for same-type route crossing validation.
|
||||||
const findSameFamilyRouteCrossing = findSameTypeRouteCrossing;
|
const findSameFamilyRouteCrossing = findSameTypeRouteCrossing;
|
||||||
|
|
||||||
@@ -1276,6 +1292,7 @@ ${linksYaml}`;
|
|||||||
createComponentSymbolMetrics,
|
createComponentSymbolMetrics,
|
||||||
transformPortInfo,
|
transformPortInfo,
|
||||||
getNodePortCanvasPoint,
|
getNodePortCanvasPoint,
|
||||||
|
getRotatableNodeHandleDirection,
|
||||||
buildPortHandles,
|
buildPortHandles,
|
||||||
buildElementPorts,
|
buildElementPorts,
|
||||||
buildElementPinEntries,
|
buildElementPinEntries,
|
||||||
|
|||||||
+150
-64
@@ -1566,6 +1566,7 @@ Organization : OptiHK Limited
|
|||||||
calculateLayoutBounds,
|
calculateLayoutBounds,
|
||||||
calculateCompositeBoxSize,
|
calculateCompositeBoxSize,
|
||||||
buildPortHandles,
|
buildPortHandles,
|
||||||
|
getRotatableNodeHandleDirection,
|
||||||
buildElementPorts,
|
buildElementPorts,
|
||||||
getElementPinName,
|
getElementPinName,
|
||||||
buildElementBoxSize,
|
buildElementBoxSize,
|
||||||
@@ -1622,7 +1623,7 @@ Organization : OptiHK Limited
|
|||||||
|
|
||||||
|
|
||||||
// Displays a category icon with cached loading and graceful failure behavior.
|
// Displays a category icon with cached loading and graceful failure behavior.
|
||||||
const IconImg = memo(({ category, containerStyle }) => {
|
const IconImg = memo(({ category, containerStyle, objectFit: imgObjectFit }) => {
|
||||||
const [src, setSrc] = useState(() => {
|
const [src, setSrc] = useState(() => {
|
||||||
if (!category) return undefined;
|
if (!category) return undefined;
|
||||||
const cache = fetchIcon(category);
|
const cache = fetchIcon(category);
|
||||||
@@ -1671,7 +1672,7 @@ Organization : OptiHK Limited
|
|||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
objectFit: 'fill',
|
objectFit: imgObjectFit || 'fill',
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
}}
|
}}
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
@@ -1698,8 +1699,10 @@ Organization : OptiHK Limited
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const transformKey = `${data.rotation || 0}:${data.flip ? 1 : 0}:${data.flop ? 1 : 0}`;
|
const transformKey = `${data.rotation || 0}:${data.flip ? 1 : 0}:${data.flop ? 1 : 0}`;
|
||||||
if (prevTransformRef.current !== transformKey) {
|
if (prevTransformRef.current !== transformKey) {
|
||||||
updateNodeInternalsRef.current(id);
|
|
||||||
prevTransformRef.current = transformKey;
|
prevTransformRef.current = transformKey;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
updateNodeInternalsRef.current(id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [data.rotation, data.flip, data.flop, id]);
|
}, [data.rotation, data.flip, data.flop, id]);
|
||||||
|
|
||||||
@@ -1719,9 +1722,51 @@ Organization : OptiHK Limited
|
|||||||
top: Position.Top,
|
top: Position.Top,
|
||||||
bottom: Position.Bottom
|
bottom: Position.Bottom
|
||||||
};
|
};
|
||||||
|
const rotateHandleDirection = (dir, rot) => {
|
||||||
|
const norm = ((rot % 360) + 360) % 360;
|
||||||
|
const map = {
|
||||||
|
0: { right: 'right', left: 'left', top: 'top', bottom: 'bottom' },
|
||||||
|
90: { right: 'bottom', left: 'top', top: 'left', bottom: 'right' },
|
||||||
|
180: { right: 'left', left: 'right', top: 'bottom', bottom: 'top' },
|
||||||
|
270: { right: 'top', left: 'bottom', top: 'right', bottom: 'left' }
|
||||||
|
};
|
||||||
|
return (map[norm] || map[0])[dir] || dir;
|
||||||
|
};
|
||||||
const componentSize = normalizeBoxSize({ box_size: data.boxSize }, DEFAULT_COMPONENT_BOX_SIZE);
|
const componentSize = normalizeBoxSize({ box_size: data.boxSize }, DEFAULT_COMPONENT_BOX_SIZE);
|
||||||
|
const flippedPorts = useMemo(
|
||||||
|
() => {
|
||||||
|
const result = {};
|
||||||
|
const ports = Object.entries(data.ports || {}).filter(([name]) => name !== 'a0' && name !== 'b0');
|
||||||
|
if (ports.length === 0) return result;
|
||||||
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
||||||
|
ports.forEach(([, info]) => {
|
||||||
|
const x = Number(info.x || 0);
|
||||||
|
const y = Number(info.y || 0);
|
||||||
|
if (x < minX) minX = x;
|
||||||
|
if (x > maxX) maxX = x;
|
||||||
|
if (y < minY) minY = y;
|
||||||
|
if (y > maxY) maxY = y;
|
||||||
|
});
|
||||||
|
ports.forEach(([name, info]) => {
|
||||||
|
let x = Number(info.x || 0);
|
||||||
|
let y = Number(info.y || 0);
|
||||||
|
let a = Number(info.a || 0);
|
||||||
|
if (data.flip) {
|
||||||
|
y = minY + maxY - y;
|
||||||
|
a = -a;
|
||||||
|
}
|
||||||
|
if (data.flop) {
|
||||||
|
x = minX + maxX - x;
|
||||||
|
a = normalizeAngle(180 - a);
|
||||||
|
}
|
||||||
|
result[name] = { ...info, x, y, a: normalizeAngle(a) };
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
[data.ports, data.flip, data.flop]
|
||||||
|
);
|
||||||
const portHandles = useMemo(
|
const portHandles = useMemo(
|
||||||
() => buildPortHandles(data.ports, { rotation: 0, flip: Boolean(data.flip), flop: Boolean(data.flop), boxSize: componentSize }),
|
() => buildPortHandles(flippedPorts, { rotation: 0, boxSize: componentSize }),
|
||||||
[data.ports, data.rotation, data.flip, data.flop, componentSize]
|
[data.ports, data.rotation, data.flip, data.flop, componentSize]
|
||||||
);
|
);
|
||||||
const portDirectionMap = useMemo(
|
const portDirectionMap = useMemo(
|
||||||
@@ -1731,21 +1776,22 @@ Organization : OptiHK Limited
|
|||||||
const isAnchorElement = data.elementType === 'anchor';
|
const isAnchorElement = data.elementType === 'anchor';
|
||||||
const isBasicCompactComponent = isBasicComponent(data.componentName) && ['waveguide', 'taper', '90 bend'].includes(data.componentName);
|
const isBasicCompactComponent = isBasicComponent(data.componentName) && ['waveguide', 'taper', '90 bend'].includes(data.componentName);
|
||||||
const visualSize = isAnchorElement ? { width: PORT_NODE_SIZE, height: PORT_NODE_SIZE } : componentSize;
|
const visualSize = isAnchorElement ? { width: PORT_NODE_SIZE, height: PORT_NODE_SIZE } : componentSize;
|
||||||
const componentVisualTransform = `rotate(${data.rotation || 0}deg) scaleX(${data.flop ? -1 : 1}) scaleY(${data.flip ? -1 : 1})`;
|
const componentVisualTransform = `rotate(${data.rotation || 0}deg)`;
|
||||||
|
const componentBodyTransform = `rotate(${data.rotation || 0}deg) scaleX(${data.flop ? -1 : 1}) scaleY(${data.flip ? -1 : 1})`;
|
||||||
const iconSize = createComponentSymbolMetrics(componentSize);
|
const iconSize = createComponentSymbolMetrics(componentSize);
|
||||||
const portLabelStyle = (portHandle) => {
|
const portLabelStyle = (portHandle) => {
|
||||||
const base = { ...portHandle.style };
|
const base = { ...portHandle.style };
|
||||||
const unrotate = `rotate(${-(data.rotation || 0)}deg) scaleX(${data.flop ? -1 : 1}) scaleY(${data.flip ? -1 : 1})`;
|
const unrotate = `rotate(${-(data.rotation || 0)}deg)`;
|
||||||
if (portHandle.position === 'left') {
|
if (portHandle.position === 'left') {
|
||||||
return { ...base, left: 'auto', right: 'calc(100% + 8px)', transform: `translateY(-50%) ${unrotate}`, textAlign: 'right' };
|
return { ...base, left: 'auto', right: 'calc(100% + 8px)', transform: `${unrotate} translateY(-50%)`, textAlign: 'right' };
|
||||||
}
|
}
|
||||||
if (portHandle.position === 'right') {
|
if (portHandle.position === 'right') {
|
||||||
return { ...base, left: 'calc(100% + 8px)', right: 'auto', transform: `translateY(-50%) ${unrotate}`, textAlign: 'left' };
|
return { ...base, left: 'calc(100% + 8px)', right: 'auto', transform: `${unrotate} translateY(-50%)`, textAlign: 'left' };
|
||||||
}
|
}
|
||||||
if (portHandle.position === 'top') {
|
if (portHandle.position === 'top') {
|
||||||
return { ...base, top: 'auto', bottom: 'calc(100% + 8px)', transform: `translateX(-50%) ${unrotate}`, textAlign: 'center' };
|
return { ...base, top: 'auto', bottom: 'calc(100% + 8px)', transform: `${unrotate} translateX(-50%)`, textAlign: 'center' };
|
||||||
}
|
}
|
||||||
return { ...base, top: 'calc(100% + 8px)', bottom: 'auto', transform: `translateX(-50%) ${unrotate}`, textAlign: 'center' };
|
return { ...base, top: 'calc(100% + 8px)', bottom: 'auto', transform: `${unrotate} translateX(-50%)`, textAlign: 'center' };
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -1759,19 +1805,18 @@ Organization : OptiHK Limited
|
|||||||
<span title={data.componentName}>{data.componentName}</span>
|
<span title={data.componentName}>{data.componentName}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div
|
||||||
position: 'relative',
|
className="component-visual-body"
|
||||||
width: componentSize.width,
|
style={{
|
||||||
transform: componentVisualTransform,
|
width: componentSize.width,
|
||||||
transformOrigin: 'center center',
|
height: visualSize.height,
|
||||||
}}>
|
minHeight: visualSize.height,
|
||||||
<div
|
overflow: 'hidden',
|
||||||
className="component-visual-body"
|
...(visualSize.height < 50 && !isAnchorElement ? { padding: '2px 4px' } : {}),
|
||||||
style={{
|
border: selected ? '2px solid var(--accent)' : '1px solid var(--border)',
|
||||||
width: componentSize.width,
|
boxShadow: selected ? '0 0 15px rgba(56, 189, 248, 0.2)' : '0 4px 6px rgba(0,0,0,0.3)',
|
||||||
height: visualSize.height,
|
transform: componentBodyTransform,
|
||||||
border: selected ? '2px solid var(--accent)' : '1px solid var(--border)',
|
transformOrigin: 'center center',
|
||||||
boxShadow: selected ? '0 0 15px rgba(56, 189, 248, 0.2)' : '0 4px 6px rgba(0,0,0,0.3)',
|
|
||||||
...(isBasicCompactComponent ? {
|
...(isBasicCompactComponent ? {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -1794,8 +1839,8 @@ Organization : OptiHK Limited
|
|||||||
) : (
|
) : (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '8px', minHeight: '100%' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '8px', minHeight: '100%' }}>
|
||||||
{!data.hideIcon && data.category && (
|
{!data.hideIcon && data.category && (
|
||||||
<div style={{ width: iconSize.width, height: iconSize.height }}>
|
<div style={{ maxWidth: iconSize.width, maxHeight: iconSize.height, width: '100%', aspectRatio: `${iconSize.width}/${iconSize.height}`, overflow: 'hidden' }}>
|
||||||
<IconImg category={data.category} />
|
<IconImg category={data.category} objectFit="contain" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!data.category && <div style={{ width: iconSize.width, height: iconSize.height, borderRadius: 4, border: '1px solid var(--border-strong)', background: 'rgba(148, 163, 184, 0.08)' }} />}
|
{!data.category && <div style={{ width: iconSize.width, height: iconSize.height, borderRadius: 4, border: '1px solid var(--border-strong)', background: 'rgba(148, 163, 184, 0.08)' }} />}
|
||||||
@@ -1803,39 +1848,41 @@ Organization : OptiHK Limited
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{
|
<div style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0, left: 0,
|
top: 0, left: 0,
|
||||||
width: '100%',
|
width: componentSize.width,
|
||||||
height: '100%',
|
height: visualSize.height,
|
||||||
pointerEvents: 'none'
|
transform: componentVisualTransform,
|
||||||
}}>
|
transformOrigin: 'center center',
|
||||||
{portHandles.map((portHandle) => (
|
pointerEvents: 'none'
|
||||||
<React.Fragment key={portHandle.name}>
|
}}>
|
||||||
<Handle
|
{portHandles.map((portHandle) => {
|
||||||
type="source"
|
const originalDir = portDirectionMap.get(portHandle.name) || portHandle.position;
|
||||||
position={handlePositionMap[portDirectionMap.get(portHandle.name) || portHandle.position]}
|
const effectiveDir = rotateHandleDirection(originalDir, data.rotation || 0);
|
||||||
id={portHandle.name}
|
return (
|
||||||
title={portHandle.name}
|
<React.Fragment key={portHandle.name}>
|
||||||
style={{ ...baseHandleStyle, ...portHandle.style, zIndex: 10, pointerEvents: 'all' }}
|
<Handle
|
||||||
/>
|
type="source"
|
||||||
<Handle
|
position={handlePositionMap[effectiveDir]}
|
||||||
type="target"
|
id={portHandle.name}
|
||||||
position={handlePositionMap[portDirectionMap.get(portHandle.name) || portHandle.position]}
|
title={portHandle.name}
|
||||||
id={portHandle.name}
|
style={{ ...baseHandleStyle, ...portHandle.style, zIndex: 10, pointerEvents: 'all' }}
|
||||||
title={portHandle.name}
|
/>
|
||||||
style={{ ...baseHandleStyle, ...portHandle.style, zIndex: 5, pointerEvents: 'all' }}
|
<Handle
|
||||||
/>
|
type="target"
|
||||||
</React.Fragment>
|
position={handlePositionMap[effectiveDir]}
|
||||||
))}
|
id={portHandle.name}
|
||||||
</div>
|
title={portHandle.name}
|
||||||
|
style={{ ...baseHandleStyle, ...portHandle.style, zIndex: 5, pointerEvents: 'all' }}
|
||||||
{portHandles.map((portHandle) => (
|
/>
|
||||||
<React.Fragment key={`label-${portHandle.name}`}>
|
|
||||||
<span className="port-name-label" style={portLabelStyle(portHandle)} title={portHandle.name}>
|
|
||||||
{portHandle.name}
|
|
||||||
</span>
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{portHandles.map((portHandle) => (
|
||||||
|
<span key={`label-${portHandle.name}`} className="port-name-label" style={portLabelStyle(portHandle)} title={portHandle.name}>
|
||||||
|
{portHandle.name}
|
||||||
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -3977,8 +4024,10 @@ Organization : OptiHK Limited
|
|||||||
const targetEndpoint = `${edge.target}:${edge.targetHandle || ''}`;
|
const targetEndpoint = `${edge.target}:${edge.targetHandle || ''}`;
|
||||||
const key = [sourceEndpoint, targetEndpoint].sort().join('<>');
|
const key = [sourceEndpoint, targetEndpoint].sort().join('<>');
|
||||||
const group = groups.get(key) || [];
|
const group = groups.get(key) || [];
|
||||||
const sourceDirection = getAnchorHandleRouteDirection(nodeMap[edge.source], edge.sourceHandle);
|
const sourceDirection = getAnchorHandleRouteDirection(nodeMap[edge.source], edge.sourceHandle)
|
||||||
const targetDirection = getAnchorHandleRouteDirection(nodeMap[edge.target], edge.targetHandle);
|
|| getRotatableNodeHandleDirection(nodeMap[edge.source], edge.sourceHandle);
|
||||||
|
const targetDirection = getAnchorHandleRouteDirection(nodeMap[edge.target], edge.targetHandle)
|
||||||
|
|| getRotatableNodeHandleDirection(nodeMap[edge.target], edge.targetHandle);
|
||||||
const usesAnchorDirection = Boolean(sourceDirection || targetDirection);
|
const usesAnchorDirection = Boolean(sourceDirection || targetDirection);
|
||||||
const hasRoutePoints = edge.data && Array.isArray(edge.data.points) && edge.data.points.length >= 2;
|
const hasRoutePoints = edge.data && Array.isArray(edge.data.points) && edge.data.points.length >= 2;
|
||||||
const directionalEdge = usesAnchorDirection
|
const directionalEdge = usesAnchorDirection
|
||||||
@@ -4001,7 +4050,7 @@ Organization : OptiHK Limited
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
return [...separatedEdges, ...rulerEdges];
|
return [...separatedEdges, ...rulerEdges];
|
||||||
}, [currentEdges, currentNodes, getAnchorHandleRouteDirection, rulerEdges]);
|
}, [currentEdges, currentNodes, getAnchorHandleRouteDirection, getRotatableNodeHandleDirection, rulerEdges]);
|
||||||
|
|
||||||
const [projectCompositeMap, setProjectCompositeMap] = useState({});
|
const [projectCompositeMap, setProjectCompositeMap] = useState({});
|
||||||
const [standaloneComposites, setStandaloneComposites] = useState([]);
|
const [standaloneComposites, setStandaloneComposites] = useState([]);
|
||||||
@@ -5065,6 +5114,35 @@ Organization : OptiHK Limited
|
|||||||
return boxSize ? { ...node, data: { ...node.data, boxSize } } : node;
|
return boxSize ? { ...node, data: { ...node.data, boxSize } } : node;
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Pre-fetch PDK component metadata so nodes render with correct boxSize immediately.
|
||||||
|
const allNodes = cellPages.flatMap(page => page.nodes);
|
||||||
|
const pdkNames = [...new Set(allNodes
|
||||||
|
.filter(n => n.data?.componentName && !n.data?.elementType
|
||||||
|
&& !isForgeComponent(n.data.componentName)
|
||||||
|
&& !isBasicComponent(n.data.componentName))
|
||||||
|
.map(n => n.data.componentName))];
|
||||||
|
if (pdkNames.length > 0) {
|
||||||
|
const metaResults = await Promise.all(
|
||||||
|
pdkNames.map(name => loadComponentMetadata(name).catch(() => null))
|
||||||
|
);
|
||||||
|
const metaMap = new Map(
|
||||||
|
pdkNames.filter((_, i) => metaResults[i]).map((name, i) => [name, metaResults[i]])
|
||||||
|
);
|
||||||
|
for (const page of cellPages) {
|
||||||
|
page.nodes = page.nodes.map(node => {
|
||||||
|
const metadata = metaMap.get(node.data?.componentName);
|
||||||
|
if (!metadata) return node;
|
||||||
|
const sz = normalizeBoxSize(metadata);
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
position: clampPositionToCanvas(node.position, page.canvasSize || DEFAULT_CANVAS_SIZE, sz),
|
||||||
|
data: { ...node.data, boxSize: sz, ports: metadata.pins || metadata.ports || {}, foundry: metadata.foundry || '', process: metadata.process || '' }
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const loadedProjectPage = cellPages.find(page => page.type === 'project' && page.name === currentProjectName);
|
const loadedProjectPage = cellPages.find(page => page.type === 'project' && page.name === currentProjectName);
|
||||||
const nonProjectPages = cellPages.filter(page => page !== loadedProjectPage);
|
const nonProjectPages = cellPages.filter(page => page !== loadedProjectPage);
|
||||||
const resolvedProjectPage = loadedProjectPage || projectPage;
|
const resolvedProjectPage = loadedProjectPage || projectPage;
|
||||||
@@ -5189,12 +5267,20 @@ Organization : OptiHK Limited
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
// Force React Flow to re-measure nodes whose boxSize / ports have changed.
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
const updatedIds = results.filter(r => r.metadata).map(r => r.nodeId);
|
||||||
|
if (updatedIds.length > 0 && reactFlowInstance.updateNodeInternals) {
|
||||||
|
reactFlowInstance.updateNodeInternals(updatedIds);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
};
|
};
|
||||||
}, [pages, loadComponentMetadata]);
|
}, [pages, loadComponentMetadata, reactFlowInstance]);
|
||||||
|
|
||||||
const openTabs = useMemo(() => pages.filter(page => !page.isClosed), [pages]);
|
const openTabs = useMemo(() => pages.filter(page => !page.isClosed), [pages]);
|
||||||
|
|
||||||
@@ -5951,6 +6037,7 @@ Organization : OptiHK Limited
|
|||||||
const route = currentLinkRoute;
|
const route = currentLinkRoute;
|
||||||
const view = routeStyleForSettings(route, false);
|
const view = routeStyleForSettings(route, false);
|
||||||
const edgeId = `edge-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}-${Date.now()}`;
|
const edgeId = `edge-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}-${Date.now()}`;
|
||||||
|
const nodeMap = Object.fromEntries(activePage.nodes.map(node => [node.id, node]));
|
||||||
const candidate = {
|
const candidate = {
|
||||||
id: edgeId,
|
id: edgeId,
|
||||||
source: connection.source,
|
source: connection.source,
|
||||||
@@ -5960,9 +6047,8 @@ Organization : OptiHK Limited
|
|||||||
type: view.type,
|
type: view.type,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
style: view.style,
|
style: view.style,
|
||||||
data: { route }
|
data: { route },
|
||||||
};
|
};
|
||||||
const nodeMap = Object.fromEntries(activePage.nodes.map(node => [node.id, node]));
|
|
||||||
const conflict = findSameTypeRouteCrossing(candidate, activePage.edges, nodeMap, technologyManifest);
|
const conflict = findSameTypeRouteCrossing(candidate, activePage.edges, nodeMap, technologyManifest);
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
const source = nodeMap[conflict.conflictEdge.source]?.data?.componentDisplayName || conflict.conflictEdge.source;
|
const source = nodeMap[conflict.conflictEdge.source]?.data?.componentDisplayName || conflict.conflictEdge.source;
|
||||||
@@ -5976,7 +6062,7 @@ Organization : OptiHK Limited
|
|||||||
: p
|
: p
|
||||||
)));
|
)));
|
||||||
addLog(`Connected ${connection.sourceHandle} to ${connection.targetHandle}.`);
|
addLog(`Connected ${connection.sourceHandle} to ${connection.targetHandle}.`);
|
||||||
}, [activePageId, activePage, rulerMode, currentLinkRoute, technologyManifest, addLog]);
|
}, [activePageId, activePage, rulerMode, currentLinkRoute, technologyManifest, addLog, getAnchorHandleRouteDirection]);
|
||||||
|
|
||||||
// Select custom route edges from their SVG hit target.
|
// Select custom route edges from their SVG hit target.
|
||||||
const handleRouteEdgeMouseDown = useCallback((event) => {
|
const handleRouteEdgeMouseDown = useCallback((event) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user