feat: create enablePanOnFocus prop, update onFocus func
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
getNodeDimensions,
|
||||
isInputDOMNode,
|
||||
nodeHasDimensions,
|
||||
getNodesInside,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { useStore, useStoreApi } from '../../hooks/useStore';
|
||||
@@ -29,6 +30,7 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
onContextMenu,
|
||||
onDoubleClick,
|
||||
nodesDraggable,
|
||||
enablePanOnFocus,
|
||||
elementsSelectable,
|
||||
nodesConnectable,
|
||||
nodesFocusable,
|
||||
@@ -163,28 +165,26 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
};
|
||||
|
||||
const onFocus = () => {
|
||||
if (disableKeyboardA11y) {
|
||||
if (disableKeyboardA11y || !enablePanOnFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return early if focus is not from keyboard navigation (i.e., was clicked)
|
||||
if (!nodeRef.current?.matches(':focus-visible')) {
|
||||
return;
|
||||
}
|
||||
const { x, y, zoom } = getViewport();
|
||||
|
||||
const isNodeVisible =
|
||||
node.position.x >= x &&
|
||||
node.position.x <= x + window.innerWidth &&
|
||||
node.position.y >= y &&
|
||||
node.position.y <= y + window.innerHeight;
|
||||
const { transform, width, height } = store.getState();
|
||||
const visibleNodes = getNodesInside(new Map([[id, node]]), { x: 0, y: 0, width, height }, transform, true);
|
||||
|
||||
const isNodeVisible = visibleNodes.length > 0;
|
||||
|
||||
if (!isNodeVisible) {
|
||||
const zoomLevel = transform[2];
|
||||
fitView({
|
||||
nodes: [{ id }],
|
||||
duration: 100,
|
||||
minZoom: zoom,
|
||||
maxZoom: zoom,
|
||||
minZoom: zoomLevel,
|
||||
maxZoom: zoomLevel,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ const reactFlowFieldsToTrack = [
|
||||
'onClickConnectStart',
|
||||
'onClickConnectEnd',
|
||||
'nodesDraggable',
|
||||
'enablePanOnFocus',
|
||||
'nodesConnectable',
|
||||
'nodesFocusable',
|
||||
'edgesFocusable',
|
||||
|
||||
@@ -29,6 +29,7 @@ export type NodeRendererProps<NodeType extends Node> = Pick<
|
||||
|
||||
const selector = (s: ReactFlowState) => ({
|
||||
nodesDraggable: s.nodesDraggable,
|
||||
enablePanOnFocus: s.enablePanOnFocus,
|
||||
nodesConnectable: s.nodesConnectable,
|
||||
nodesFocusable: s.nodesFocusable,
|
||||
elementsSelectable: s.elementsSelectable,
|
||||
@@ -36,7 +37,10 @@ const selector = (s: ReactFlowState) => ({
|
||||
});
|
||||
|
||||
function NodeRendererComponent<NodeType extends Node>(props: NodeRendererProps<NodeType>) {
|
||||
const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector, shallow);
|
||||
const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, enablePanOnFocus, onError } = useStore(
|
||||
selector,
|
||||
shallow
|
||||
);
|
||||
const nodeIds = useVisibleNodeIds(props.onlyRenderVisibleElements);
|
||||
const resizeObserver = useResizeObserver();
|
||||
|
||||
@@ -48,13 +52,13 @@ function NodeRendererComponent<NodeType extends Node>(props: NodeRendererProps<N
|
||||
* The split of responsibilities between NodeRenderer and
|
||||
* NodeComponentWrapper may appear weird. However, it’s designed to
|
||||
* minimize the cost of updates when individual nodes change.
|
||||
*
|
||||
*
|
||||
* For example, when you’re dragging a single node, that node gets
|
||||
* updated multiple times per second. If `NodeRenderer` were to update
|
||||
* every time, it would have to re-run the `nodes.map()` loop every
|
||||
* time. This gets pricey with hundreds of nodes, especially if every
|
||||
* loop cycle does more than just rendering a JSX element!
|
||||
*
|
||||
*
|
||||
* As a result of this choice, we took the following implementation
|
||||
* decisions:
|
||||
* - NodeRenderer subscribes *only* to node IDs – and therefore
|
||||
@@ -86,6 +90,7 @@ function NodeRendererComponent<NodeType extends Node>(props: NodeRendererProps<N
|
||||
disableKeyboardA11y={props.disableKeyboardA11y}
|
||||
resizeObserver={resizeObserver}
|
||||
nodesDraggable={nodesDraggable}
|
||||
enablePanOnFocus={enablePanOnFocus}
|
||||
nodesConnectable={nodesConnectable}
|
||||
nodesFocusable={nodesFocusable}
|
||||
elementsSelectable={elementsSelectable}
|
||||
|
||||
@@ -77,6 +77,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
onlyRenderVisibleElements = false,
|
||||
selectNodesOnDrag,
|
||||
nodesDraggable,
|
||||
enablePanOnFocus,
|
||||
nodesConnectable,
|
||||
nodesFocusable,
|
||||
nodeOrigin = defaultNodeOrigin,
|
||||
@@ -261,6 +262,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
onClickConnectStart={onClickConnectStart}
|
||||
onClickConnectEnd={onClickConnectEnd}
|
||||
nodesDraggable={nodesDraggable}
|
||||
enablePanOnFocus={enablePanOnFocus}
|
||||
nodesConnectable={nodesConnectable}
|
||||
nodesFocusable={nodesFocusable}
|
||||
edgesFocusable={edgesFocusable}
|
||||
|
||||
@@ -112,6 +112,7 @@ const getInitialState = ({
|
||||
snapToGrid: false,
|
||||
|
||||
nodesDraggable: true,
|
||||
enablePanOnFocus: false,
|
||||
nodesConnectable: true,
|
||||
nodesFocusable: true,
|
||||
edgesFocusable: true,
|
||||
|
||||
@@ -383,6 +383,11 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
|
||||
* @default true
|
||||
*/
|
||||
nodesDraggable?: boolean;
|
||||
/**
|
||||
* When `true`, the viewport will pan when a node is focused.
|
||||
* @default false
|
||||
*/
|
||||
enablePanOnFocus?: boolean;
|
||||
/**
|
||||
* Controls whether all nodes should be connectable or not. Individual nodes can override this
|
||||
* setting by setting their `connectable` prop.
|
||||
|
||||
@@ -48,6 +48,7 @@ export type NodeWrapperProps<NodeType extends Node> = {
|
||||
nodesConnectable: boolean;
|
||||
elementsSelectable: boolean;
|
||||
nodesDraggable: boolean;
|
||||
enablePanOnFocus: boolean;
|
||||
nodesFocusable: boolean;
|
||||
onClick?: NodeMouseHandler<NodeType>;
|
||||
onDoubleClick?: NodeMouseHandler<NodeType>;
|
||||
|
||||
@@ -88,6 +88,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
|
||||
snapGrid: SnapGrid;
|
||||
|
||||
nodesDraggable: boolean;
|
||||
enablePanOnFocus: boolean;
|
||||
nodesConnectable: boolean;
|
||||
nodesFocusable: boolean;
|
||||
edgesFocusable: boolean;
|
||||
|
||||
Reference in New Issue
Block a user