Merge pull request #2464 from wbkd/refactor/a11y
Refactor: make keyboard a11y better configurable
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@reactflow/examples",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --port 3000 --open",
|
||||
|
||||
@@ -92,7 +92,7 @@ const BasicFlow = () => {
|
||||
defaultEdgeOptions={defaultEdgeOptions}
|
||||
selectNodesOnDrag={false}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Lines} />
|
||||
<Background variant={BackgroundVariant.Dots} />
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @reactflow/background
|
||||
|
||||
## 11.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab) Thanks [@moklick](https://github.com/moklick)! - default gap = 20
|
||||
|
||||
- Updated dependencies [[`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab), [`d00faa6b`](https://github.com/wbkd/react-flow/commit/d00faa6b3e77388bfd655d4c02e9a5375bc515e4)]:
|
||||
- @reactflow/core@11.1.0
|
||||
|
||||
## 11.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@reactflow/background",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "Background component with different variants for React Flow",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@@ -22,7 +22,7 @@ const selector = (s: ReactFlowState) => ({ transform: s.transform, rfId: s.rfId
|
||||
|
||||
function Background({
|
||||
variant = BackgroundVariant.Dots,
|
||||
gap = 25,
|
||||
gap = 20,
|
||||
// only used for dots and cross
|
||||
size,
|
||||
// only used for lines and cross
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @reactflow/controls
|
||||
|
||||
## 11.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab), [`d00faa6b`](https://github.com/wbkd/react-flow/commit/d00faa6b3e77388bfd655d4c02e9a5375bc515e4)]:
|
||||
- @reactflow/core@11.1.0
|
||||
|
||||
## 11.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@reactflow/controls",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "Component to control the viewport of a React Flow instance",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @reactflow/core
|
||||
|
||||
## 11.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab) Thanks [@moklick](https://github.com/moklick)! - New props: nodesFocusable and edgesFocusable
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`d00faa6b`](https://github.com/wbkd/react-flow/commit/d00faa6b3e77388bfd655d4c02e9a5375bc515e4) Thanks [@moklick](https://github.com/moklick)! - Make nopan class name overwritable with class name option
|
||||
|
||||
## 11.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@reactflow/core",
|
||||
"version": "11.0.0",
|
||||
"version": "11.1.0",
|
||||
"description": "Core components and util functions of React Flow.",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@@ -51,7 +51,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
||||
markerStart,
|
||||
rfId,
|
||||
ariaLabel,
|
||||
disableKeyboardA11y,
|
||||
isFocusable,
|
||||
pathOptions,
|
||||
interactionWidth,
|
||||
}: WrapEdgeProps): JSX.Element | null => {
|
||||
@@ -158,12 +158,12 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
||||
onMouseEnter={onEdgeMouseEnter}
|
||||
onMouseMove={onEdgeMouseMove}
|
||||
onMouseLeave={onEdgeMouseLeave}
|
||||
onKeyDown={disableKeyboardA11y ? undefined : onKeyDown}
|
||||
tabIndex={disableKeyboardA11y ? undefined : 0}
|
||||
role={disableKeyboardA11y ? undefined : 'button'}
|
||||
onKeyDown={isFocusable ? onKeyDown : undefined}
|
||||
tabIndex={isFocusable ? 0 : undefined}
|
||||
role={isFocusable ? 'button' : undefined}
|
||||
data-testid={`rf__edge-${id}`}
|
||||
aria-label={ariaLabel === null ? undefined : ariaLabel ? ariaLabel : `Edge from ${source} to ${target}`}
|
||||
aria-describedby={disableKeyboardA11y ? undefined : `${ARIA_EDGE_DESC_KEY}-${rfId}`}
|
||||
aria-describedby={isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined}
|
||||
ref={edgeRef}
|
||||
>
|
||||
{!updating && (
|
||||
|
||||
@@ -11,10 +11,10 @@ import { NodeProps, WrapNodeProps, XYPosition } from '../../types';
|
||||
import { elementSelectionKeys } from '../../utils';
|
||||
|
||||
export const arrowKeyDiffs: Record<string, XYPosition> = {
|
||||
ArrowUp: { x: 0, y: -10 },
|
||||
ArrowDown: { x: 0, y: 10 },
|
||||
ArrowLeft: { x: -10, y: 0 },
|
||||
ArrowRight: { x: 10, y: 0 },
|
||||
ArrowUp: { x: 0, y: -1 },
|
||||
ArrowDown: { x: 0, y: 1 },
|
||||
ArrowLeft: { x: -1, y: 0 },
|
||||
ArrowRight: { x: 1, y: 0 },
|
||||
};
|
||||
|
||||
export default (NodeComponent: ComponentType<NodeProps>) => {
|
||||
@@ -38,6 +38,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
||||
isDraggable,
|
||||
isSelectable,
|
||||
isConnectable,
|
||||
isFocusable,
|
||||
selectNodesOnDrag,
|
||||
sourcePosition,
|
||||
targetPosition,
|
||||
@@ -82,6 +83,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
||||
};
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
const { snapGrid, snapToGrid } = store.getState();
|
||||
if (elementSelectionKeys.includes(event.key) && isSelectable) {
|
||||
const unselect = event.key === 'Escape';
|
||||
if (unselect) {
|
||||
@@ -92,14 +94,28 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
||||
store,
|
||||
unselect,
|
||||
});
|
||||
} else if (selected && Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {
|
||||
} else if (
|
||||
!disableKeyboardA11y &&
|
||||
isDraggable &&
|
||||
selected &&
|
||||
Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)
|
||||
) {
|
||||
store.setState({
|
||||
ariaLiveMessage: `Moved selected node ten pixels ${event.key
|
||||
ariaLiveMessage: `Moved selected node ${event.key
|
||||
.replace('Arrow', '')
|
||||
.toLowerCase()}. New position, x: ${~~xPos}, y: ${~~yPos}`,
|
||||
});
|
||||
|
||||
updatePositions(arrowKeyDiffs[event.key]);
|
||||
// by default a node moves 5px on each key press, or 20px if shift is pressed
|
||||
// if snap grid is enabled, we use that for the velocity.
|
||||
const xVelo = snapToGrid ? snapGrid[0] : 5;
|
||||
const yVelo = snapToGrid ? snapGrid[1] : 5;
|
||||
const factor = event.shiftKey ? 4 : 1;
|
||||
|
||||
updatePositions({
|
||||
x: arrowKeyDiffs[event.key].x * xVelo * factor,
|
||||
y: arrowKeyDiffs[event.key].y * yVelo * factor,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -151,13 +167,16 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
||||
className={cc([
|
||||
'react-flow__node',
|
||||
`react-flow__node-${type}`,
|
||||
{
|
||||
// this is overwritable by passing `nopan` as a class name
|
||||
[noPanClassName]: isDraggable,
|
||||
},
|
||||
className,
|
||||
{
|
||||
selected,
|
||||
selectable: isSelectable,
|
||||
parent: isParent,
|
||||
dragging,
|
||||
[noPanClassName]: isDraggable,
|
||||
},
|
||||
])}
|
||||
ref={nodeRef}
|
||||
@@ -176,9 +195,9 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
|
||||
onContextMenu={onContextMenuHandler}
|
||||
onClick={onSelectNodeHandler}
|
||||
onDoubleClick={onDoubleClickHandler}
|
||||
onKeyDown={disableKeyboardA11y ? undefined : onKeyDown}
|
||||
tabIndex={disableKeyboardA11y ? undefined : 0}
|
||||
role={disableKeyboardA11y ? undefined : 'button'}
|
||||
onKeyDown={isFocusable ? onKeyDown : undefined}
|
||||
tabIndex={isFocusable ? 0 : undefined}
|
||||
role={isFocusable ? 'button' : undefined}
|
||||
aria-describedby={disableKeyboardA11y ? undefined : `${ARIA_NODE_DESC_KEY}-${rfId}`}
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
|
||||
@@ -18,6 +18,8 @@ type StoreUpdaterProps = Pick<
|
||||
| 'onClickConnectEnd'
|
||||
| 'nodesDraggable'
|
||||
| 'nodesConnectable'
|
||||
| 'nodesFocusable'
|
||||
| 'edgesFocusable'
|
||||
| 'minZoom'
|
||||
| 'maxZoom'
|
||||
| 'nodeExtent'
|
||||
@@ -89,6 +91,8 @@ const StoreUpdater = ({
|
||||
onClickConnectEnd,
|
||||
nodesDraggable,
|
||||
nodesConnectable,
|
||||
nodesFocusable,
|
||||
edgesFocusable,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
nodeExtent,
|
||||
@@ -145,6 +149,8 @@ const StoreUpdater = ({
|
||||
useDirectStoreUpdater('onClickConnectEnd', onClickConnectEnd, store.setState);
|
||||
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
|
||||
useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);
|
||||
useDirectStoreUpdater('nodesFocusable', nodesFocusable, store.setState);
|
||||
useDirectStoreUpdater('edgesFocusable', edgesFocusable, store.setState);
|
||||
useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);
|
||||
useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);
|
||||
useDirectStoreUpdater('snapGrid', snapGrid, store.setState);
|
||||
|
||||
@@ -46,6 +46,7 @@ const selector = (s: ReactFlowState) => ({
|
||||
connectionNodeId: s.connectionNodeId,
|
||||
connectionHandleType: s.connectionHandleType,
|
||||
nodesConnectable: s.nodesConnectable,
|
||||
edgesFocusable: s.edgesFocusable,
|
||||
elementsSelectable: s.elementsSelectable,
|
||||
width: s.width,
|
||||
height: s.height,
|
||||
@@ -58,6 +59,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
||||
connectionNodeId,
|
||||
connectionHandleType,
|
||||
nodesConnectable,
|
||||
edgesFocusable,
|
||||
elementsSelectable,
|
||||
width,
|
||||
height,
|
||||
@@ -119,6 +121,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
||||
const targetHandle = getHandle(targetNodeHandles!, edge.targetHandle || null);
|
||||
const sourcePosition = sourceHandle?.position || Position.Bottom;
|
||||
const targetPosition = targetHandle?.position || Position.Top;
|
||||
const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined'));
|
||||
|
||||
if (!sourceHandle || !targetHandle) {
|
||||
devWarn(
|
||||
@@ -181,7 +184,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
|
||||
onEdgeUpdateEnd={props.onEdgeUpdateEnd}
|
||||
rfId={props.rfId}
|
||||
ariaLabel={edge.ariaLabel}
|
||||
disableKeyboardA11y={props.disableKeyboardA11y}
|
||||
isFocusable={isFocusable}
|
||||
pathOptions={'pathOptions' in edge ? edge.pathOptions : undefined}
|
||||
interactionWidth={edge.interactionWidth}
|
||||
/>
|
||||
|
||||
@@ -31,12 +31,16 @@ type NodeRendererProps = Pick<
|
||||
const selector = (s: ReactFlowState) => ({
|
||||
nodesDraggable: s.nodesDraggable,
|
||||
nodesConnectable: s.nodesConnectable,
|
||||
nodesFocusable: s.nodesFocusable,
|
||||
elementsSelectable: s.elementsSelectable,
|
||||
updateNodeDimensions: s.updateNodeDimensions,
|
||||
});
|
||||
|
||||
const NodeRenderer = (props: NodeRendererProps) => {
|
||||
const { nodesDraggable, nodesConnectable, elementsSelectable, updateNodeDimensions } = useStore(selector, shallow);
|
||||
const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, updateNodeDimensions } = useStore(
|
||||
selector,
|
||||
shallow
|
||||
);
|
||||
const nodes = useVisibleNodes(props.onlyRenderVisibleElements);
|
||||
const resizeObserverRef = useRef<ResizeObserver>();
|
||||
|
||||
@@ -82,6 +86,8 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
||||
const isDraggable = !!(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'));
|
||||
const isSelectable = !!(node.selectable || (elementsSelectable && typeof node.selectable === 'undefined'));
|
||||
const isConnectable = !!(node.connectable || (nodesConnectable && typeof node.connectable === 'undefined'));
|
||||
const isFocusable = !!(node.focusable || (nodesFocusable && typeof node.focusable === 'undefined'));
|
||||
|
||||
const clampedPosition = props.nodeExtent
|
||||
? clampPosition(node.positionAbsolute, props.nodeExtent)
|
||||
: node.positionAbsolute;
|
||||
@@ -122,6 +128,7 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
||||
isDraggable={isDraggable}
|
||||
isSelectable={isSelectable}
|
||||
isConnectable={isConnectable}
|
||||
isFocusable={isFocusable}
|
||||
resizeObserver={resizeObserver}
|
||||
dragHandle={node.dragHandle}
|
||||
zIndex={node[internalsSymbol]?.z ?? 0}
|
||||
|
||||
@@ -108,7 +108,9 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
selectNodesOnDrag = true,
|
||||
nodesDraggable,
|
||||
nodesConnectable,
|
||||
nodesFocusable,
|
||||
nodeOrigin = initNodeOrigin,
|
||||
edgesFocusable,
|
||||
elementsSelectable,
|
||||
defaultViewport = initDefaultViewport,
|
||||
minZoom = 0.5,
|
||||
@@ -245,6 +247,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
onClickConnectEnd={onClickConnectEnd}
|
||||
nodesDraggable={nodesDraggable}
|
||||
nodesConnectable={nodesConnectable}
|
||||
nodesFocusable={nodesFocusable}
|
||||
edgesFocusable={edgesFocusable}
|
||||
elementsSelectable={elementsSelectable}
|
||||
minZoom={minZoom}
|
||||
maxZoom={maxZoom}
|
||||
|
||||
@@ -9,17 +9,19 @@ function useUpdateNodePositions() {
|
||||
const store = useStoreApi();
|
||||
|
||||
const updatePositions = useCallback((positionDiff: XYPosition) => {
|
||||
const { nodeInternals, nodeExtent, updateNodePositions } = store.getState();
|
||||
const { nodeInternals, nodeExtent, updateNodePositions, snapToGrid, snapGrid } = store.getState();
|
||||
const selectedNodes = Array.from(nodeInternals.values()).filter((n) => n.selected);
|
||||
|
||||
const nodeUpdates = selectedNodes.map((n) => {
|
||||
if (n.positionAbsolute) {
|
||||
const updatedPos = calcNextPosition(
|
||||
n,
|
||||
{ x: n.positionAbsolute.x + positionDiff.x, y: n.positionAbsolute.y + positionDiff.y },
|
||||
nodeInternals,
|
||||
nodeExtent
|
||||
);
|
||||
const nextPosition = { x: n.positionAbsolute.x + positionDiff.x, y: n.positionAbsolute.y + positionDiff.y };
|
||||
|
||||
if (snapToGrid) {
|
||||
nextPosition.x = snapGrid[0] * Math.round(nextPosition.x / snapGrid[0]);
|
||||
nextPosition.y = snapGrid[1] * Math.round(nextPosition.y / snapGrid[1]);
|
||||
}
|
||||
|
||||
const updatedPos = calcNextPosition(n, nextPosition, nodeInternals, nodeExtent);
|
||||
|
||||
n.position = updatedPos.position;
|
||||
n.positionAbsolute = updatedPos.positionAbsolute;
|
||||
|
||||
@@ -40,6 +40,8 @@ const initialState: ReactFlowStore = {
|
||||
|
||||
nodesDraggable: true,
|
||||
nodesConnectable: true,
|
||||
nodesFocusable: true,
|
||||
edgesFocusable: true,
|
||||
elementsSelectable: true,
|
||||
fitViewOnInit: false,
|
||||
fitViewOnInitDone: false,
|
||||
|
||||
@@ -92,7 +92,9 @@ export interface ReactFlowProps extends HTMLAttributes<HTMLDivElement> {
|
||||
onlyRenderVisibleElements?: boolean;
|
||||
nodesDraggable?: boolean;
|
||||
nodesConnectable?: boolean;
|
||||
nodesFocusable?: boolean;
|
||||
nodeOrigin?: NodeOrigin;
|
||||
edgesFocusable?: boolean;
|
||||
initNodeOrigin?: NodeOrigin;
|
||||
elementsSelectable?: boolean;
|
||||
selectNodesOnDrag?: boolean;
|
||||
|
||||
@@ -33,6 +33,7 @@ type DefaultEdge<T = any> = {
|
||||
zIndex?: number;
|
||||
ariaLabel?: string;
|
||||
interactionWidth?: number;
|
||||
focusable?: boolean;
|
||||
};
|
||||
|
||||
export type SmoothStepPathOptions = {
|
||||
@@ -132,7 +133,7 @@ export type WrapEdgeProps<T = any> = Omit<Edge<T>, 'sourceHandle' | 'targetHandl
|
||||
onEdgeUpdateStart?: (event: React.MouseEvent, edge: Edge, handleType: HandleType) => void;
|
||||
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge, handleType: HandleType) => void;
|
||||
rfId?: string;
|
||||
disableKeyboardA11y: boolean;
|
||||
isFocusable: boolean;
|
||||
pathOptions?: BezierPathOptions | SmoothStepPathOptions;
|
||||
};
|
||||
|
||||
|
||||
@@ -167,6 +167,8 @@ export type ReactFlowStore = {
|
||||
|
||||
nodesDraggable: boolean;
|
||||
nodesConnectable: boolean;
|
||||
nodesFocusable: boolean;
|
||||
edgesFocusable: boolean;
|
||||
elementsSelectable: boolean;
|
||||
|
||||
multiSelectionActive: boolean;
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface Node<T = any> {
|
||||
expandParent?: boolean;
|
||||
positionAbsolute?: XYPosition;
|
||||
ariaLabel?: string;
|
||||
focusable?: boolean;
|
||||
|
||||
// only used internally
|
||||
[internalsSymbol]?: {
|
||||
@@ -73,6 +74,7 @@ export interface WrapNodeProps<T = any> {
|
||||
initialized: boolean;
|
||||
isSelectable: boolean;
|
||||
isDraggable: boolean;
|
||||
isFocusable: boolean;
|
||||
selectNodesOnDrag: boolean;
|
||||
onClick?: NodeMouseHandler;
|
||||
onDoubleClick?: NodeMouseHandler;
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @reactflow/minimap
|
||||
|
||||
## 11.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab), [`d00faa6b`](https://github.com/wbkd/react-flow/commit/d00faa6b3e77388bfd655d4c02e9a5375bc515e4)]:
|
||||
- @reactflow/core@11.1.0
|
||||
|
||||
## 11.0.0
|
||||
|
||||
### Major Changes
|
||||
@@ -29,7 +36,6 @@
|
||||
- @reactflow/controls
|
||||
- @reactflow/minimap
|
||||
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@reactflow/minimap",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "Minimap component for React Flow.",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
# reactflow
|
||||
|
||||
## 11.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab) Thanks [@moklick](https://github.com/moklick)! - New props: nodesFocusable and edgesFocusable
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`d00faa6b`](https://github.com/wbkd/react-flow/commit/d00faa6b3e77388bfd655d4c02e9a5375bc515e4) Thanks [@moklick](https://github.com/moklick)! - Make nopan class name overwritable with class name option
|
||||
|
||||
- Updated dependencies [[`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab), [`def11008`](https://github.com/wbkd/react-flow/commit/def11008d88749fec40e6fcba8bc41eea2511bab), [`d00faa6b`](https://github.com/wbkd/react-flow/commit/d00faa6b3e77388bfd655d4c02e9a5375bc515e4)]:
|
||||
- @reactflow/background@11.0.1
|
||||
- @reactflow/core@11.1.0
|
||||
- @reactflow/controls@11.0.1
|
||||
- @reactflow/minimap@11.0.1
|
||||
|
||||
## 11.0.0
|
||||
|
||||
Finally it's here! A new version that comes with lots of improvements and the new package name `reactflow`.
|
||||
From now on you can install it via `npm install reactflow`.
|
||||
From now on you can install it via `npm install reactflow`.
|
||||
|
||||
## Major Changes
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "reactflow",
|
||||
"version": "11.0.0",
|
||||
"version": "11.1.0",
|
||||
"description": "A highly customizable React library for building node-based editors and interactive flow charts",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
Reference in New Issue
Block a user