diff --git a/.changeset/nine-cougars-turn.md b/.changeset/nine-cougars-turn.md new file mode 100644 index 00000000..eb6f3776 --- /dev/null +++ b/.changeset/nine-cougars-turn.md @@ -0,0 +1,5 @@ +--- +'@reactflow/minimap': minor +--- + +add a new property "ariaLabel" to configure or remove the aria-label of the minimap component diff --git a/.changeset/silly-taxis-drop.md b/.changeset/silly-taxis-drop.md new file mode 100644 index 00000000..e26bd820 --- /dev/null +++ b/.changeset/silly-taxis-drop.md @@ -0,0 +1,5 @@ +--- +'@reactflow/core': patch +--- + +Core: Always elevate zIndex when node is selected diff --git a/.changeset/tender-pears-knock.md b/.changeset/tender-pears-knock.md new file mode 100644 index 00000000..697143ef --- /dev/null +++ b/.changeset/tender-pears-knock.md @@ -0,0 +1,5 @@ +--- +'@reactflow/core': patch +--- + +EdgeLabelRenderer: handle multiple instances on a page diff --git a/examples/vite-app/cypress/components/reactflow/multiple-instance.cy.tsx b/examples/vite-app/cypress/components/reactflow/multiple-instance.cy.tsx new file mode 100644 index 00000000..b1b354a0 --- /dev/null +++ b/examples/vite-app/cypress/components/reactflow/multiple-instance.cy.tsx @@ -0,0 +1,63 @@ +import ReactFlow, { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, ReactFlowProvider } from 'reactflow'; +import * as simpleflow from '../../fixtures/simpleflow'; + +function CustomEdge(props: EdgeProps) { + const [path, labelX, labelY] = getSmoothStepPath(props); + return ( + <> + + +
{props.id}
+
+ + ); +} + +const simpleflow1 = { ...simpleflow }; +simpleflow1.edges = [...simpleflow1.edges]; +simpleflow1.edges[0] = { ...simpleflow1.edges[0], id: 'edge1' }; + +const simpleflow2 = { ...simpleflow }; +simpleflow2.edges = [...simpleflow2.edges]; +simpleflow2.edges[0] = { ...simpleflow2.edges[0], id: 'edge2' }; + +describe(': Multiple Instances', () => { + describe('render EdgeLabelRenderer', () => { + beforeEach(() => { + cy.mount( + <> + + + + + + + + ); + }); + + it('Each ReactFlow instance has one edge label in EdgeLabelRenderer', () => { + cy.get('.react-flow__edgelabel-renderer').should('have.length', 2); + + cy.get('.react-flow__edgelabel-renderer') + .eq(0) + .within(() => { + cy.get('.label').should('have.length', 1).should('contain.text', 'edge1'); + }); + + cy.get('.react-flow__edgelabel-renderer') + .eq(1) + .within(() => { + cy.get('.label').should('have.length', 1).should('contain.text', 'edge2'); + }); + }); + }); +}); diff --git a/packages/core/src/components/EdgeLabelRenderer/index.tsx b/packages/core/src/components/EdgeLabelRenderer/index.tsx index 0647364a..07477493 100644 --- a/packages/core/src/components/EdgeLabelRenderer/index.tsx +++ b/packages/core/src/components/EdgeLabelRenderer/index.tsx @@ -1,15 +1,18 @@ -import { useRef } from 'react'; import type { ReactNode } from 'react'; import { createPortal } from 'react-dom'; +import { useStore } from '../../hooks/useStore'; +import { ReactFlowState } from '../../types'; + +const selector = (s: ReactFlowState) => s.domNode?.querySelector('.react-flow__edgelabel-renderer'); function EdgeLabelRenderer({ children }: { children: ReactNode }) { - const wrapperRef = useRef(document.getElementById('edgelabel-portal')); + const edgeLabelRenderer = useStore(selector); - if (!wrapperRef.current) { + if (!edgeLabelRenderer) { return null; } - return createPortal(children, wrapperRef.current); + return createPortal(children, edgeLabelRenderer); } export default EdgeLabelRenderer; diff --git a/packages/core/src/container/GraphView/index.tsx b/packages/core/src/container/GraphView/index.tsx index 4190bed0..3af02659 100644 --- a/packages/core/src/container/GraphView/index.tsx +++ b/packages/core/src/container/GraphView/index.tsx @@ -158,7 +158,7 @@ const GraphView = ({ disableKeyboardA11y={disableKeyboardA11y} rfId={rfId} /> -
+
{ - const z = isNumeric(node.zIndex) ? node.zIndex : node.selected ? 1000 : 0; + const z = (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? 1000 : 0); const currInternals = nodeInternals.get(node.id); const internals: Node = { diff --git a/packages/core/src/utils/graph.ts b/packages/core/src/utils/graph.ts index e3f6b9d7..0408603f 100644 --- a/packages/core/src/utils/graph.ts +++ b/packages/core/src/utils/graph.ts @@ -243,3 +243,4 @@ export const getTransformForBounds = ( export const getD3Transition = (selection: D3Selection, duration = 0) => { return selection.transition().duration(duration); }; + diff --git a/packages/minimap/src/MiniMap.tsx b/packages/minimap/src/MiniMap.tsx index c278ebd0..c02fa313 100644 --- a/packages/minimap/src/MiniMap.tsx +++ b/packages/minimap/src/MiniMap.tsx @@ -39,7 +39,6 @@ const selector = (s: ReactFlowState) => { const getAttrFunction = (func: any): GetMiniMapNodeAttribute => (func instanceof Function ? func : () => func); const ARIA_LABEL_KEY = 'react-flow__minimap-desc'; - function MiniMap({ style, className, @@ -54,6 +53,7 @@ function MiniMap({ onNodeClick, pannable = false, zoomable = false, + ariaLabel = 'React Flow mini map', }: MiniMapProps) { const store = useStoreApi(); const svg = useRef(null); @@ -156,7 +156,7 @@ function MiniMap({ ref={svg} onClick={onSvgClick} > - React Flow mini map + {ariaLabel && {ariaLabel}} {nodes.map((node) => ( = Omit, ' onNodeClick?: (event: MouseEvent, node: Node) => void; pannable?: boolean; zoomable?: boolean; + ariaLabel?: string | null; };