diff --git a/.eslintrc.json b/.eslintrc.json index 0864a267..d128d331 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,6 +9,7 @@ "plugin:react/recommended", "plugin:react-hooks/recommended", "plugin:@typescript-eslint/recommended", + "plugin:react/jsx-runtime", "prettier" ], "overrides": [ @@ -31,13 +32,7 @@ "version": "detect" } }, - "plugins": [ - "react", - "react-hooks", - "@typescript-eslint", - "patternfly-react", - "prettier" - ], + "plugins": ["react", "react-hooks", "@typescript-eslint", "patternfly-react", "prettier"], "rules": { "@typescript-eslint/adjacent-overload-signatures": "error", "@typescript-eslint/array-type": "error", diff --git a/README.md b/README.md index 3fae65c3..a2e9b129 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ To use Topology out of the box, follow these steps: ## Example ```ts -import * as React from 'react'; +import { memo, useState, useMemo } from 'react'; import { EdgeStyle, Model, @@ -172,10 +172,10 @@ const EDGES = [ } ]; -export const TopologyBaselineDemo = React.memo(() => { - const [selectedIds, setSelectedIds] = React.useState([]); +export const TopologyBaselineDemo = memo(() => { + const [selectedIds, setSelectedIds] = useState([]); - const controller = React.useMemo(() => { + const controller = useMemo(() => { const model: Model = { nodes: NODES, edges: EDGES, diff --git a/packages/demo-app-ts/src/App.test.tsx b/packages/demo-app-ts/src/App.test.tsx index a754b201..1c039be5 100755 --- a/packages/demo-app-ts/src/App.test.tsx +++ b/packages/demo-app-ts/src/App.test.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import App from './App'; it('renders without crashing', () => { const div = document.createElement('div'); - ReactDOM.render(, div); - ReactDOM.unmountComponentAtNode(div); + const root = createRoot(div); + root.render(); + root.unmount(); }); diff --git a/packages/demo-app-ts/src/App.tsx b/packages/demo-app-ts/src/App.tsx index 7e363842..933448ec 100755 --- a/packages/demo-app-ts/src/App.tsx +++ b/packages/demo-app-ts/src/App.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { createElement } from 'react'; import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom'; import { Page, @@ -81,7 +81,7 @@ class App extends React.Component<{}, AppState> { style={{ zIndex: 2 }} id={`/${demo.id}-nav-link/${subDemo.id}-nav-link`} > - {React.createElement(subDemo.componentType)} + {createElement(subDemo.componentType)} )} key={demo.id} @@ -94,7 +94,7 @@ class App extends React.Component<{}, AppState> { path={`/${demo.id}-nav-link`} render={() => ( - {React.createElement(demo.componentType)} + {createElement(demo.componentType)} )} key={demo.id} @@ -108,7 +108,7 @@ class App extends React.Component<{}, AppState> { path="/" render={() => ( - {React.createElement(defaultDemo.componentType)} + {createElement(defaultDemo.componentType)} )} key={defaultDemo.id} diff --git a/packages/demo-app-ts/src/components/CustomCircleNode.tsx b/packages/demo-app-ts/src/components/CustomCircleNode.tsx index 3aa438dc..f9e813f0 100644 --- a/packages/demo-app-ts/src/components/CustomCircleNode.tsx +++ b/packages/demo-app-ts/src/components/CustomCircleNode.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useEffect } from 'react'; import { observer } from 'mobx-react'; import { WithCreateConnectorProps, @@ -28,7 +28,7 @@ type CustomCircleNodeProps = { const CustomCircle: React.FunctionComponent = ({ element, className }) => { useAnchor(EllipseAnchor); - React.useEffect(() => { + useEffect(() => { // init height element.setDimensions(new Dimensions(40, 40)); }, [element]); diff --git a/packages/demo-app-ts/src/components/CustomPathNode.tsx b/packages/demo-app-ts/src/components/CustomPathNode.tsx index e69bd690..d36cb9bd 100644 --- a/packages/demo-app-ts/src/components/CustomPathNode.tsx +++ b/packages/demo-app-ts/src/components/CustomPathNode.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; import { WithCreateConnectorProps, diff --git a/packages/demo-app-ts/src/components/CustomPolygonNode.tsx b/packages/demo-app-ts/src/components/CustomPolygonNode.tsx index 17ad52e4..3a6e98b5 100644 --- a/packages/demo-app-ts/src/components/CustomPolygonNode.tsx +++ b/packages/demo-app-ts/src/components/CustomPolygonNode.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; import { WithCreateConnectorProps, diff --git a/packages/demo-app-ts/src/components/CustomRectNode.tsx b/packages/demo-app-ts/src/components/CustomRectNode.tsx index 6677b8b5..666ac7a1 100644 --- a/packages/demo-app-ts/src/components/CustomRectNode.tsx +++ b/packages/demo-app-ts/src/components/CustomRectNode.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; import { WithCreateConnectorProps, diff --git a/packages/demo-app-ts/src/components/DemoDefaultEdge.tsx b/packages/demo-app-ts/src/components/DemoDefaultEdge.tsx index 858396c1..ba28626a 100644 --- a/packages/demo-app-ts/src/components/DemoDefaultEdge.tsx +++ b/packages/demo-app-ts/src/components/DemoDefaultEdge.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useState } from 'react'; import { observer } from 'mobx-react'; import { Edge, @@ -25,7 +25,7 @@ interface BendpointProps { } const Bendpoint: React.FunctionComponent = observer(({ point }) => { - const [hover, setHover] = React.useState(false); + const [hover, setHover] = useState(false); const [, ref] = useBendpoint(point); return ( = ({ }) => { const nodeElement = element as Node; useAnchor(RectAnchor); - const boxRef = React.useRef(null); + const boxRef = useRef(null); const refs = useCombineRefs(dragNodeRef, dndDragRef, dndDropRef); if (!droppable || !boxRef.current) { diff --git a/packages/demo-app-ts/src/components/DemoDefaultNode.tsx b/packages/demo-app-ts/src/components/DemoDefaultNode.tsx index 046d069e..0265b50b 100644 --- a/packages/demo-app-ts/src/components/DemoDefaultNode.tsx +++ b/packages/demo-app-ts/src/components/DemoDefaultNode.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useEffect } from 'react'; import classNames from 'classnames'; import { observer } from 'mobx-react'; import { @@ -52,7 +52,7 @@ const DemoDefaultNode: React.FunctionComponent = ({ }); const ShapeComponent = (getCustomShape && getCustomShape(nodeElement)) || getShapeComponent(nodeElement); - React.useEffect(() => { + useEffect(() => { if (hover) { onShowCreateConnector && onShowCreateConnector(); } else { diff --git a/packages/demo-app-ts/src/components/GroupHull.tsx b/packages/demo-app-ts/src/components/GroupHull.tsx index 441f52c5..0b693d31 100644 --- a/packages/demo-app-ts/src/components/GroupHull.tsx +++ b/packages/demo-app-ts/src/components/GroupHull.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useRef } from 'react'; import { observer } from 'mobx-react'; import { polygonHull } from 'd3-polygon'; import { @@ -45,7 +45,7 @@ const GroupHull: React.FunctionComponent = ({ canDrop }) => { const nodeElement = element as Node; - const pathRef = React.useRef(null); + const pathRef = useRef(null); const refs = useCombineRefs(dragNodeRef, dndDragRef, dndDropRef); useAnchor(RectAnchor); diff --git a/packages/demo-app-ts/src/components/MultiEdge.tsx b/packages/demo-app-ts/src/components/MultiEdge.tsx index 824092d7..8ccda5b8 100644 --- a/packages/demo-app-ts/src/components/MultiEdge.tsx +++ b/packages/demo-app-ts/src/components/MultiEdge.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; import { Edge, vecSum, vecScale, unitNormal, GraphElement } from '@patternfly/react-topology'; diff --git a/packages/demo-app-ts/src/components/NodeRect.tsx b/packages/demo-app-ts/src/components/NodeRect.tsx index a1d1808a..3ccb1100 100644 --- a/packages/demo-app-ts/src/components/NodeRect.tsx +++ b/packages/demo-app-ts/src/components/NodeRect.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; import { Node, diff --git a/packages/demo-app-ts/src/components/actionsComponentFactory.tsx b/packages/demo-app-ts/src/components/actionsComponentFactory.tsx index 6b4d3625..e331446f 100644 --- a/packages/demo-app-ts/src/components/actionsComponentFactory.tsx +++ b/packages/demo-app-ts/src/components/actionsComponentFactory.tsx @@ -1,4 +1,3 @@ -import * as React from 'react'; import { GraphElement, ComponentFactory, diff --git a/packages/demo-app-ts/src/components/shapes/Path.tsx b/packages/demo-app-ts/src/components/shapes/Path.tsx index c44676b7..d91b5776 100644 --- a/packages/demo-app-ts/src/components/shapes/Path.tsx +++ b/packages/demo-app-ts/src/components/shapes/Path.tsx @@ -1,5 +1,4 @@ import { ShapeProps, useCombineRefs, useSvgAnchor } from '@patternfly/react-topology'; -import * as React from 'react'; const Path: React.FunctionComponent = ({ className, width, height, filter, dndDropRef }) => { const anchorRef = useSvgAnchor(); diff --git a/packages/demo-app-ts/src/components/shapes/Polygon.tsx b/packages/demo-app-ts/src/components/shapes/Polygon.tsx index 8c4e6804..428448ca 100644 --- a/packages/demo-app-ts/src/components/shapes/Polygon.tsx +++ b/packages/demo-app-ts/src/components/shapes/Polygon.tsx @@ -1,8 +1,8 @@ import { PointTuple, ShapeProps, usePolygonAnchor } from '@patternfly/react-topology'; -import * as React from 'react'; +import { useMemo } from 'react'; const Polygon: React.FunctionComponent = ({ className, width, height, filter, dndDropRef }) => { - const points: PointTuple[] = React.useMemo( + const points: PointTuple[] = useMemo( () => [ [width / 2, 0], [width - width / 8, height], diff --git a/packages/demo-app-ts/src/demos/Basics.tsx b/packages/demo-app-ts/src/demos/Basics.tsx index 55e2b47f..e2b31bf7 100644 --- a/packages/demo-app-ts/src/demos/Basics.tsx +++ b/packages/demo-app-ts/src/demos/Basics.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useMemo, useCallback, useState } from 'react'; import { DefaultNode, Model, @@ -17,7 +17,7 @@ import { Tab, Tabs, TabTitleText } from '@patternfly/react-core'; export const SingleNode = withTopologySetup(() => { useComponentFactory(defaultComponentFactory); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -43,7 +43,7 @@ export const SingleNode = withTopologySetup(() => { export const SingleEdge = withTopologySetup(() => { useComponentFactory(defaultComponentFactory); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -89,7 +89,7 @@ export const SingleEdge = withTopologySetup(() => { export const MultiEdge = withTopologySetup(() => { useComponentFactory(defaultComponentFactory); useComponentFactory( - React.useCallback((kind) => { + useCallback((kind) => { if (kind === ModelKind.node) { return withDragNode()(DefaultNode); } @@ -97,7 +97,7 @@ export const MultiEdge = withTopologySetup(() => { }, []) ); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -193,7 +193,7 @@ const groupStory = () => { useComponentFactory(defaultComponentFactory); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -247,7 +247,7 @@ export const GroupHull = withTopologySetup(groupStory('group-hull')); export const AutoSizeNode = withTopologySetup(() => { useComponentFactory(defaultComponentFactory); useComponentFactory( - React.useCallback((kind, type) => { + useCallback((kind, type) => { if (type === 'autoSize-circle') { return CustomCircleNode; } @@ -258,7 +258,7 @@ export const AutoSizeNode = withTopologySetup(() => { }, []) ); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -317,7 +317,7 @@ export const AutoSizeNode = withTopologySetup(() => { }); export const Basics: React.FunctionComponent = () => { - const [activeKey, setActiveKey] = React.useState(0); + const [activeKey, setActiveKey] = useState(0); const handleTabClick = (_event: React.MouseEvent, tabIndex: string | number) => { setActiveKey(tabIndex); diff --git a/packages/demo-app-ts/src/demos/CollapsibleGroups.tsx b/packages/demo-app-ts/src/demos/CollapsibleGroups.tsx index b92fcb65..437800a7 100644 --- a/packages/demo-app-ts/src/demos/CollapsibleGroups.tsx +++ b/packages/demo-app-ts/src/demos/CollapsibleGroups.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useState, useEffect } from 'react'; import { action } from 'mobx'; import { TopologyView, @@ -117,12 +117,12 @@ interface TopologyViewComponentProps { } const TopologyViewComponent: React.FunctionComponent = ({ vis }) => { - const [selectedIds, setSelectedIds] = React.useState(); - const [collapseBlue, setCollapseBlue] = React.useState(false); - const [collapseLightBlue, setCollapseLightBlue] = React.useState(false); - const [collapseCyan, setCollapseCyan] = React.useState(false); - const [collapseOrange, setCollapseOrange] = React.useState(false); - const [collapsePink, setCollapsePink] = React.useState(false); + const [selectedIds, setSelectedIds] = useState(); + const [collapseBlue, setCollapseBlue] = useState(false); + const [collapseLightBlue, setCollapseLightBlue] = useState(false); + const [collapseCyan, setCollapseCyan] = useState(false); + const [collapseOrange, setCollapseOrange] = useState(false); + const [collapsePink, setCollapsePink] = useState(false); useEventListener(SELECTION_EVENT, (ids) => { setSelectedIds(ids); @@ -183,7 +183,7 @@ const TopologyViewComponent: React.FunctionComponent ); - React.useEffect(() => { + useEffect(() => { action(() => { const collapsedTypes: string[] = []; if (collapseBlue) { diff --git a/packages/demo-app-ts/src/demos/Connectors.tsx b/packages/demo-app-ts/src/demos/Connectors.tsx index 72e0b384..53f08359 100644 --- a/packages/demo-app-ts/src/demos/Connectors.tsx +++ b/packages/demo-app-ts/src/demos/Connectors.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useCallback, useMemo, useState } from 'react'; import { Model, ModelKind, @@ -38,7 +38,7 @@ import { Tab, Tabs, TabTitleText } from '@patternfly/react-core'; export const Reconnect = withTopologySetup(() => { useComponentFactory(defaultComponentFactory); useComponentFactory( - React.useCallback((kind) => { + useCallback((kind) => { if (kind === ModelKind.graph) { return withPanZoom()(GraphComponent); } @@ -96,7 +96,7 @@ export const Reconnect = withTopologySetup(() => { }, []) ); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -158,7 +158,7 @@ type ColorChoice = ConnectorChoice & { }; export const CreateConnector = withTopologySetup(() => { - const model = React.useMemo( + const model = useMemo( (): Model => ({ graph: { id: 'g1', @@ -196,7 +196,7 @@ export const CreateConnector = withTopologySetup(() => { const controller = useVisualizationController(); useComponentFactory(defaultComponentFactory); useComponentFactory( - React.useCallback( + useCallback( (kind) => { if (kind === ModelKind.graph) { return withDndDrop({ @@ -295,7 +295,7 @@ const NodeWithPointAnchor: React.FunctionComponent<{ element: GraphElement } & W export const Anchors = withTopologySetup(() => { useComponentFactory(defaultComponentFactory); useComponentFactory( - React.useCallback((kind) => { + useCallback((kind) => { if (kind === ModelKind.node) { return withDragNode()(NodeWithPointAnchor); } @@ -303,7 +303,7 @@ export const Anchors = withTopologySetup(() => { }, []) ); useModel( - React.useMemo( + useMemo( (): Model => ({ graph: { id: 'g1', @@ -357,7 +357,7 @@ export const Anchors = withTopologySetup(() => { }); export const Connectors: React.FunctionComponent = () => { - const [activeKey, setActiveKey] = React.useState(0); + const [activeKey, setActiveKey] = useState(0); const handleTabClick = (_event: React.MouseEvent, tabIndex: string | number) => { setActiveKey(tabIndex); diff --git a/packages/demo-app-ts/src/demos/ContextMenus.tsx b/packages/demo-app-ts/src/demos/ContextMenus.tsx index 2eb87934..d703126d 100644 --- a/packages/demo-app-ts/src/demos/ContextMenus.tsx +++ b/packages/demo-app-ts/src/demos/ContextMenus.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { useState, useCallback, useMemo } from 'react'; import { ContextMenu, ContextMenuItem, @@ -42,7 +42,7 @@ export const UncontrolledContextMenu = () => ( ); export const ControlledContextMenu = () => { - const [open, setOpen] = React.useState(false); + const [open, setOpen] = useState(false); return ( <>