From 587341d605a91652d584bd57fc5737b4ffc3f2b5 Mon Sep 17 00:00:00 2001 From: Jeff Phillips Date: Thu, 6 Apr 2023 12:45:13 -0400 Subject: [PATCH] chore(Topology): Remove topology package (#8927) Topology moved to https://github.com/patternfly/react-topology --- README.md | 1 - packages/react-docs/package.json | 1 - .../patternfly-docs/patternfly-docs.config.js | 1 - .../patternfly-docs/patternfly-docs.css.js | 5 - .../patternfly-docs/patternfly-docs.source.js | 5 - .../demo-app-ts/src/Demos.ts | 10 - .../components/demos/TopologyDemo/Basics.tsx | 314 - .../demos/TopologyDemo/CollapsibleGroups.tsx | 249 - .../demos/TopologyDemo/Connectors.tsx | 358 - .../demos/TopologyDemo/ContextMenus.tsx | 92 - .../demos/TopologyDemo/DragDrop.tsx | 252 - .../components/demos/TopologyDemo/Groups.tsx | 147 - .../components/demos/TopologyDemo/Layouts.tsx | 63 - .../components/demos/TopologyDemo/PanZoom.tsx | 78 - .../demos/TopologyDemo/PipelineLayout.tsx | 128 - .../demos/TopologyDemo/PipelineTasks.tsx | 62 - .../demos/TopologyDemo/Selection.tsx | 161 - .../components/demos/TopologyDemo/Shapes.tsx | 153 - .../components/demos/TopologyDemo/Styles.tsx | 850 -- .../demos/TopologyDemo/TopologyDemo.css | 62 - .../demos/TopologyDemo/TopologyDemo.tsx | 287 - .../demos/TopologyDemo/TopologyPackage.tsx | 192 - .../TopologyDemo/TopologyPipelineDemo.tsx | 31 - .../components/CustomCircleNode.tsx | 55 - .../components/CustomPathNode.tsx | 30 - .../components/CustomPolygonNode.tsx | 30 - .../components/CustomRectNode.tsx | 37 - .../TopologyDemo/components/DefaultEdge.tsx | 77 - .../TopologyDemo/components/DefaultGroup.tsx | 94 - .../components/DemoDefaultNode.tsx | 68 - .../components/DemoFinallyNode.tsx | 34 - .../components/DemoTaskGroupEdge.tsx | 15 - .../TopologyDemo/components/DemoTaskNode.tsx | 83 - .../TopologyDemo/components/GroupHull.tsx | 128 - .../TopologyDemo/components/MultiEdge.tsx | 44 - .../TopologyDemo/components/NodeRect.tsx | 62 - .../TopologyDemo/components/StyleEdge.tsx | 34 - .../TopologyDemo/components/StyleGroup.tsx | 93 - .../TopologyDemo/components/StyleNode.tsx | 186 - .../components/actionsComponentFactory.tsx | 79 - .../components/defaultComponentFactory.ts | 33 - .../components/pipelineComponentFactory.tsx | 70 - .../TopologyDemo/components/shapes/Path.tsx | 19 - .../components/shapes/Polygon.tsx | 26 - .../components/shapesComponentFactory.ts | 23 - .../components/stylesComponentFactory.tsx | 143 - .../demos/TopologyDemo/data/generator.ts | 211 - .../demos/TopologyDemo/data/group-types.ts | 35 - .../demos/TopologyDemo/data/miserables.ts | 337 - .../demos/TopologyDemo/data/reasonable.ts | 23 - .../layouts/defaultLayoutFactory.ts | 37 - .../TopologyDemo/useDemoPipelineNodes.tsx | 213 - .../demos/TopologyDemo/usePipelineOptions.tsx | 44 - .../demos/TopologyDemo/useTopologyOptions.tsx | 450 - .../demos/TopologyDemo/utils/logos.ts | 11 - .../demos/TopologyDemo/utils/styleUtils.ts | 538 - .../TopologyDemo/utils/withTopologySetup.tsx | 11 - .../demo-app-ts/src/components/demos/index.ts | 2 - .../demo-app-ts/tsconfig.dev.json | 3 +- .../demo-app-ts/webpack.config.js | 3 +- .../Topology/topology-components.css | 832 -- .../Topology/topology-controlbar.css | 22 - .../Topology/topology-pipelines.css | 554 - .../components/Topology/topology-side-bar.css | 73 - .../css/components/Topology/topology-view.css | 13 - packages/react-topology/.npmignore | 2 - packages/react-topology/CHANGELOG.md | 12300 ---------------- packages/react-topology/README.md | 184 - packages/react-topology/package.json | 58 - packages/react-topology/src/Visualization.ts | 358 - .../src/__tests__/Visualization.spec.ts | 34 - .../src/anchors/AbstractAnchor.ts | 25 - .../src/anchors/CenterAnchor.ts | 14 - .../src/anchors/EllipseAnchor.ts | 15 - .../src/anchors/PolygonAnchor.ts | 70 - .../react-topology/src/anchors/RectAnchor.ts | 16 - .../react-topology/src/anchors/SVGAnchor.ts | 114 - .../anchors/__tests__/AbstractAnchor.spec.ts | 36 - .../anchors/__tests__/CenterAnchor.spec.ts | 25 - .../anchors/__tests__/EllipseAnchor.spec.ts | 38 - .../src/anchors/__tests__/RectAnchor.spec.ts | 29 - packages/react-topology/src/anchors/index.ts | 6 - .../react-topology/src/behavior/dnd-types.ts | 180 - packages/react-topology/src/behavior/index.ts | 15 - .../src/behavior/useAddBendpoint.tsx.bak | 58 - .../react-topology/src/behavior/useAnchor.tsx | 41 - .../src/behavior/useBendpoint.tsx | 102 - .../src/behavior/useDndDrag.tsx | 324 - .../src/behavior/useDndDrop.tsx | 195 - .../src/behavior/useDndManager.tsx | 358 - .../src/behavior/useDragNode.tsx | 178 - .../src/behavior/usePanZoom.tsx | 119 - .../src/behavior/usePolygonAnchor.tsx | 40 - .../src/behavior/useReconnect.tsx | 52 - .../src/behavior/useSelection.tsx | 92 - .../src/behavior/useSvgAnchor.tsx | 45 - .../src/behavior/withContextMenu.tsx | 55 - .../src/behavior/withCreateConnector.tsx | 278 - .../src/behavior/withRemoveConnector.tsx | 48 - .../components/ComputeElementDimensions.tsx | 32 - .../src/components/DefaultCreateConnector.tsx | 89 - .../src/components/DefaultRemoveConnector.tsx | 51 - .../src/components/ElementWrapper.tsx | 126 - .../src/components/GraphComponent.tsx | 69 - .../src/components/SVGArrowMarker.tsx | 34 - .../TopologyControlBar/TopologyControlBar.tsx | 304 - .../__tests__/TopologyControlBar.test.tsx | 50 - .../TopologyControlBar.test.tsx.snap | 314 - .../components/TopologyControlBar/index.ts | 1 - .../TopologySideBar/TopologySideBar.tsx | 71 - .../__tests__/TopologySideBar.test.tsx | 40 - .../src/components/TopologySideBar/index.ts | 1 - .../components/TopologyView/TopologyView.tsx | 132 - .../__tests__/TopologyView.test.tsx | 110 - .../__snapshots__/TopologyView.test.tsx.snap | 115 - .../TopologyView/examples/TopologyAnchors.md | 52 - .../examples/TopologyAnchorsDemo.tsx | 179 - .../examples/TopologyContextMenu.md | 45 - .../examples/TopologyContextMenuDemo.tsx | 195 - .../examples/TopologyControlBar.md | 56 - .../examples/TopologyControlBarDemo.tsx | 202 - .../examples/TopologyCustomEdges.md | 48 - .../examples/TopologyCustomEdgesDemo.tsx | 240 - .../examples/TopologyCustomNodes.md | 42 - .../examples/TopologyCustomNodesDemo.tsx | 237 - .../examples/TopologyDragDropDemo.md | 104 - .../examples/TopologyDragDropDemo.tsx | 282 - .../examples/TopologyGettingStarted.md | 55 - .../examples/TopologyGettingStartedDemo.tsx | 160 - .../TopologyView/examples/TopologyLayouts.md | 76 - .../examples/TopologyLayoutsDemo.tsx | 349 - .../TopologyView/examples/TopologyPanZoom.md | 42 - .../examples/TopologyPanZoomDemo.tsx | 238 - .../TopologyPipelinesGettingStarted.md | 113 - .../TopologyPipelinesGettingStartedDemo.tsx | 170 - .../examples/TopologySelectable.md | 48 - .../examples/TopologySelectableDemo.tsx | 241 - .../TopologyView/examples/TopologySidebar.md | 42 - .../examples/TopologySidebarDemo.tsx | 249 - .../TopologyView/examples/TopologyToolbar.md | 52 - .../examples/TopologyToolbarDemo.tsx | 306 - .../examples/topology-example.css | 49 - .../examples/topology-pipelines-example.css | 6 - .../src/components/TopologyView/index.ts | 1 - .../src/components/VisualizationProvider.tsx | 27 - .../src/components/VisualizationSurface.tsx | 76 - .../ComputeElementDimensions.test.tsx | 19 - .../components/contextmenu/ContextMenu.tsx | 59 - .../contextmenu/ContextSubMenuItem.tsx | 95 - .../src/components/contextmenu/index.ts | 5 - .../src/components/decorators/Decorator.tsx | 83 - .../src/components/decorators/index.ts | 1 - .../src/components/defs/Defs.tsx | 22 - .../src/components/defs/SVGDefs.tsx | 31 - .../src/components/defs/SVGDefsContext.ts | 10 - .../src/components/defs/SVGDefsProvider.tsx | 70 - .../src/components/defs/SVGDefsSetter.tsx | 23 - .../src/components/defs/__mocks__/SVGDefs.tsx | 9 - .../components/defs/__tests__/Defs.test.tsx | 14 - .../defs/__tests__/SVGDefs.spec.tsx | 57 - .../src/components/defs/index.ts | 2 - .../components/edges/DefaultConnectorTag.tsx | 74 - .../src/components/edges/DefaultEdge.tsx | 186 - .../src/components/edges/index.ts | 3 - .../edges/terminals/ConnectorArrow.tsx | 66 - .../edges/terminals/ConnectorArrowAlt.tsx | 35 - .../edges/terminals/ConnectorCircle.tsx | 49 - .../edges/terminals/ConnectorCross.tsx | 61 - .../edges/terminals/ConnectorSquare.tsx | 50 - .../terminals/DefaultConnectorTerminal.tsx | 65 - .../src/components/edges/terminals/index.ts | 7 - .../edges/terminals/terminalUtils.ts | 30 - .../factories/RegisterComponentFactory.tsx | 14 - .../factories/RegisterElementFactory.tsx | 14 - .../factories/RegisterLayoutFactory.tsx | 14 - .../factories/components/componentUtils.ts | 289 - .../components/factories/components/index.ts | 1 - .../src/components/factories/index.ts | 4 - .../components/groups/CollapsedGroupAnchor.ts | 25 - .../src/components/groups/DefaultGroup.tsx | 56 - .../groups/DefaultGroupCollapsed.tsx | 185 - .../groups/DefaultGroupExpanded.tsx | 216 - .../src/components/groups/index.ts | 2 - .../src/components/groups/types.ts | 12 - .../react-topology/src/components/index.ts | 18 - .../src/components/layers/Layer.tsx | 88 - .../src/components/layers/LayerContainer.tsx | 37 - .../src/components/layers/LayersContext.ts | 7 - .../src/components/layers/LayersProvider.tsx | 57 - .../src/components/layers/index.ts | 2 - .../src/components/nodes/DefaultNode.tsx | 367 - .../src/components/nodes/NodeShadows.tsx | 23 - .../src/components/nodes/index.ts | 4 - .../nodes/labels/LabelActionIcon.tsx | 59 - .../components/nodes/labels/LabelBadge.tsx | 71 - .../nodes/labels/LabelContextMenu.tsx | 32 - .../src/components/nodes/labels/LabelIcon.tsx | 47 - .../src/components/nodes/labels/NodeLabel.tsx | 299 - .../src/components/nodes/labels/index.ts | 5 - .../src/components/nodes/shapes/Ellipse.tsx | 31 - .../src/components/nodes/shapes/Hexagon.tsx | 13 - .../src/components/nodes/shapes/Octagon.tsx | 13 - .../src/components/nodes/shapes/Rectangle.tsx | 36 - .../src/components/nodes/shapes/Rhombus.tsx | 45 - .../components/nodes/shapes/SidedShape.tsx | 40 - .../src/components/nodes/shapes/Stadium.tsx | 30 - .../src/components/nodes/shapes/Trapezoid.tsx | 54 - .../src/components/nodes/shapes/index.ts | 9 - .../src/components/nodes/shapes/shapeUtils.ts | 162 - .../src/components/popper/Popper.tsx | 233 - .../src/components/popper/Portal.tsx | 25 - .../src/components/popper/index.ts | 1 - .../components/svg/SvgDropShadowFilter.tsx | 64 - packages/react-topology/src/const.ts | 10 - packages/react-topology/src/declarations.d.ts | 3 - .../react-topology/src/elements/BaseEdge.ts | 202 - .../src/elements/BaseElement.ts | 306 - .../react-topology/src/elements/BaseGraph.ts | 370 - .../react-topology/src/elements/BaseNode.ts | 401 - .../src/elements/__tests__/BaseGraph.spec.ts | 334 - .../src/elements/__tests__/BaseNode.spec.ts | 47 - .../__tests__/defaultElementFactory.spec.ts | 13 - .../src/elements/defaultElementFactory.ts | 19 - packages/react-topology/src/elements/index.ts | 5 - .../react-topology/src/geom/Dimensions.ts | 63 - packages/react-topology/src/geom/Point.ts | 58 - packages/react-topology/src/geom/Rect.ts | 151 - .../src/geom/__tests__/Dimensions.spec.ts | 75 - .../src/geom/__tests__/Point.spec.ts | 68 - .../src/geom/__tests__/Rect.spec.ts | 135 - packages/react-topology/src/geom/index.ts | 4 - packages/react-topology/src/geom/types.ts | 28 - packages/react-topology/src/hooks/index.ts | 9 - .../src/hooks/useComponentFactory.tsx | 13 - .../src/hooks/useDetailsLevel.tsx | 12 - .../src/hooks/useElementFactory.tsx | 13 - .../src/hooks/useEventListener.tsx | 15 - .../src/hooks/useLayoutFactory.tsx | 13 - .../react-topology/src/hooks/useModel.tsx | 13 - .../react-topology/src/hooks/useScaleNode.tsx | 50 - .../src/hooks/useVisualizationController.tsx | 7 - .../src/hooks/useVisualizationState.tsx | 40 - packages/react-topology/src/index.ts | 13 - .../react-topology/src/layouts/BaseLayout.ts | 484 - .../src/layouts/BreadthFirstGroup.ts | 3 - .../src/layouts/BreadthFirstLayout.ts | 123 - .../src/layouts/BreadthFirstLink.ts | 3 - .../src/layouts/BreadthFirstNode.ts | 8 - .../react-topology/src/layouts/ColaGroup.ts | 3 - .../src/layouts/ColaGroupsLayout.ts | 252 - .../src/layouts/ColaGroupsNode.ts | 58 - .../react-topology/src/layouts/ColaLayout.ts | 199 - .../react-topology/src/layouts/ColaLink.ts | 10 - .../react-topology/src/layouts/ColaNode.ts | 21 - .../src/layouts/ConcentricGroup.ts | 2 - .../src/layouts/ConcentricLayout.ts | 107 - .../src/layouts/ConcentricLink.ts | 3 - .../src/layouts/ConcentricNode.ts | 8 - .../react-topology/src/layouts/DagreGroup.ts | 2 - .../react-topology/src/layouts/DagreLayout.ts | 93 - .../react-topology/src/layouts/DagreLink.ts | 10 - .../react-topology/src/layouts/DagreNode.ts | 19 - .../react-topology/src/layouts/ForceLayout.ts | 46 - .../src/layouts/ForceSimulation.ts | 112 - .../react-topology/src/layouts/GridGroup.ts | 2 - .../react-topology/src/layouts/GridLayout.ts | 71 - .../react-topology/src/layouts/GridLink.ts | 3 - .../react-topology/src/layouts/GridNode.ts | 8 - .../react-topology/src/layouts/LayoutGroup.ts | 21 - .../react-topology/src/layouts/LayoutLink.ts | 26 - .../react-topology/src/layouts/LayoutNode.ts | 93 - .../src/layouts/LayoutOptions.ts | 11 - packages/react-topology/src/layouts/index.ts | 12 - packages/react-topology/src/mobx-exports.ts | 5 - .../anchors/TaskNodeSourceAnchor.ts | 27 - .../anchors/TaskNodeSourceAnchorSave.ts | 22 - .../anchors/TaskNodeTargetAnchor.ts | 21 - .../src/pipelines/components/anchors/index.ts | 2 - .../pipelines/components/edges/TaskEdge.tsx | 34 - .../pipelines/components/edges/WhenEdge.tsx | 9 - .../src/pipelines/components/edges/index.ts | 2 - .../components/groups/DefaultTaskGroup.tsx | 182 - .../src/pipelines/components/groups/index.ts | 1 - .../src/pipelines/components/index.ts | 4 - .../components/nodes/FinallyNode.tsx | 8 - .../pipelines/components/nodes/SpacerNode.tsx | 7 - .../pipelines/components/nodes/TaskBadge.tsx | 75 - .../pipelines/components/nodes/TaskNode.tsx | 493 - .../src/pipelines/components/nodes/index.ts | 5 - .../react-topology/src/pipelines/const.ts | 12 - .../pipelines/decorators/WhenDecorator.tsx | 94 - .../src/pipelines/decorators/index.ts | 1 - .../react-topology/src/pipelines/index.ts | 6 - .../pipelines/layouts/PipelineDagreLayout.ts | 32 - .../src/pipelines/layouts/index.ts | 1 - .../react-topology/src/pipelines/types.ts | 24 - .../src/pipelines/utils/StatusIcon.tsx | 52 - .../src/pipelines/utils/draw-utils.ts | 93 - .../src/pipelines/utils/index.ts | 3 - .../src/pipelines/utils/utils.ts | 203 - packages/react-topology/src/types.ts | 353 - .../src/utils/ControllerContext.ts | 6 - .../src/utils/ElementContext.ts | 6 - packages/react-topology/src/utils/Stateful.ts | 18 - .../src/utils/__tests__/svg-utils.spec.ts | 30 - .../react-topology/src/utils/anchor-utils.ts | 179 - .../src/utils/createAggregateEdges.ts | 94 - .../react-topology/src/utils/element-utils.ts | 122 - .../react-topology/src/utils/geom-utils.ts | 11 - .../src/utils/getNodeScaleTranslation.ts | 16 - packages/react-topology/src/utils/index.ts | 13 - .../react-topology/src/utils/style-utils.ts | 46 - .../react-topology/src/utils/svg-utils.ts | 142 - .../src/utils/truncate-middle.ts | 49 - .../src/utils/useCallbackRef.ts | 22 - .../src/utils/useCombineRefs.tsx | 18 - packages/react-topology/src/utils/useHover.ts | 80 - packages/react-topology/src/utils/useSize.ts | 26 - packages/react-topology/tsconfig.cjs.json | 8 - packages/react-topology/tsconfig.json | 20 - packages/tsconfig.cjs.json | 3 - packages/tsconfig.json | 3 - yarn.lock | 495 +- 323 files changed, 9 insertions(+), 40704 deletions(-) delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Basics.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/CollapsibleGroups.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Connectors.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/ContextMenus.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/DragDrop.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Groups.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Layouts.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PanZoom.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineLayout.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineTasks.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Selection.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Shapes.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Styles.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.css delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPackage.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPipelineDemo.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomCircleNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPathNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPolygonNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomRectNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultEdge.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultGroup.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoDefaultNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoFinallyNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskGroupEdge.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/GroupHull.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/MultiEdge.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/NodeRect.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleEdge.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleGroup.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleNode.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/actionsComponentFactory.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/defaultComponentFactory.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/pipelineComponentFactory.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Path.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Polygon.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapesComponentFactory.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/stylesComponentFactory.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/generator.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/group-types.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/miserables.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/reasonable.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/layouts/defaultLayoutFactory.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useDemoPipelineNodes.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/usePipelineOptions.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useTopologyOptions.tsx delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/utils/logos.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/utils/styleUtils.ts delete mode 100644 packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/utils/withTopologySetup.tsx delete mode 100644 packages/react-styles/src/css/components/Topology/topology-components.css delete mode 100644 packages/react-styles/src/css/components/Topology/topology-controlbar.css delete mode 100644 packages/react-styles/src/css/components/Topology/topology-pipelines.css delete mode 100644 packages/react-styles/src/css/components/Topology/topology-side-bar.css delete mode 100644 packages/react-styles/src/css/components/Topology/topology-view.css delete mode 100644 packages/react-topology/.npmignore delete mode 100644 packages/react-topology/CHANGELOG.md delete mode 100644 packages/react-topology/README.md delete mode 100644 packages/react-topology/package.json delete mode 100644 packages/react-topology/src/Visualization.ts delete mode 100644 packages/react-topology/src/__tests__/Visualization.spec.ts delete mode 100644 packages/react-topology/src/anchors/AbstractAnchor.ts delete mode 100644 packages/react-topology/src/anchors/CenterAnchor.ts delete mode 100644 packages/react-topology/src/anchors/EllipseAnchor.ts delete mode 100644 packages/react-topology/src/anchors/PolygonAnchor.ts delete mode 100644 packages/react-topology/src/anchors/RectAnchor.ts delete mode 100644 packages/react-topology/src/anchors/SVGAnchor.ts delete mode 100644 packages/react-topology/src/anchors/__tests__/AbstractAnchor.spec.ts delete mode 100644 packages/react-topology/src/anchors/__tests__/CenterAnchor.spec.ts delete mode 100644 packages/react-topology/src/anchors/__tests__/EllipseAnchor.spec.ts delete mode 100644 packages/react-topology/src/anchors/__tests__/RectAnchor.spec.ts delete mode 100644 packages/react-topology/src/anchors/index.ts delete mode 100644 packages/react-topology/src/behavior/dnd-types.ts delete mode 100644 packages/react-topology/src/behavior/index.ts delete mode 100644 packages/react-topology/src/behavior/useAddBendpoint.tsx.bak delete mode 100644 packages/react-topology/src/behavior/useAnchor.tsx delete mode 100644 packages/react-topology/src/behavior/useBendpoint.tsx delete mode 100644 packages/react-topology/src/behavior/useDndDrag.tsx delete mode 100644 packages/react-topology/src/behavior/useDndDrop.tsx delete mode 100644 packages/react-topology/src/behavior/useDndManager.tsx delete mode 100644 packages/react-topology/src/behavior/useDragNode.tsx delete mode 100644 packages/react-topology/src/behavior/usePanZoom.tsx delete mode 100644 packages/react-topology/src/behavior/usePolygonAnchor.tsx delete mode 100644 packages/react-topology/src/behavior/useReconnect.tsx delete mode 100644 packages/react-topology/src/behavior/useSelection.tsx delete mode 100644 packages/react-topology/src/behavior/useSvgAnchor.tsx delete mode 100644 packages/react-topology/src/behavior/withContextMenu.tsx delete mode 100644 packages/react-topology/src/behavior/withCreateConnector.tsx delete mode 100644 packages/react-topology/src/behavior/withRemoveConnector.tsx delete mode 100644 packages/react-topology/src/components/ComputeElementDimensions.tsx delete mode 100644 packages/react-topology/src/components/DefaultCreateConnector.tsx delete mode 100644 packages/react-topology/src/components/DefaultRemoveConnector.tsx delete mode 100644 packages/react-topology/src/components/ElementWrapper.tsx delete mode 100644 packages/react-topology/src/components/GraphComponent.tsx delete mode 100644 packages/react-topology/src/components/SVGArrowMarker.tsx delete mode 100644 packages/react-topology/src/components/TopologyControlBar/TopologyControlBar.tsx delete mode 100644 packages/react-topology/src/components/TopologyControlBar/__tests__/TopologyControlBar.test.tsx delete mode 100644 packages/react-topology/src/components/TopologyControlBar/__tests__/__snapshots__/TopologyControlBar.test.tsx.snap delete mode 100644 packages/react-topology/src/components/TopologyControlBar/index.ts delete mode 100644 packages/react-topology/src/components/TopologySideBar/TopologySideBar.tsx delete mode 100644 packages/react-topology/src/components/TopologySideBar/__tests__/TopologySideBar.test.tsx delete mode 100644 packages/react-topology/src/components/TopologySideBar/index.ts delete mode 100644 packages/react-topology/src/components/TopologyView/TopologyView.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/__tests__/TopologyView.test.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/__tests__/__snapshots__/TopologyView.test.tsx.snap delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyAnchors.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyAnchorsDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyContextMenu.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyContextMenuDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyControlBar.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyControlBarDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyCustomEdges.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyCustomEdgesDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyCustomNodes.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyCustomNodesDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyDragDropDemo.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyDragDropDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyGettingStarted.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyGettingStartedDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyLayouts.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyLayoutsDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyPanZoom.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyPanZoomDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyPipelinesGettingStarted.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyPipelinesGettingStartedDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologySelectable.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologySelectableDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologySidebar.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologySidebarDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyToolbar.md delete mode 100644 packages/react-topology/src/components/TopologyView/examples/TopologyToolbarDemo.tsx delete mode 100644 packages/react-topology/src/components/TopologyView/examples/topology-example.css delete mode 100644 packages/react-topology/src/components/TopologyView/examples/topology-pipelines-example.css delete mode 100644 packages/react-topology/src/components/TopologyView/index.ts delete mode 100644 packages/react-topology/src/components/VisualizationProvider.tsx delete mode 100644 packages/react-topology/src/components/VisualizationSurface.tsx delete mode 100644 packages/react-topology/src/components/__tests__/ComputeElementDimensions.test.tsx delete mode 100644 packages/react-topology/src/components/contextmenu/ContextMenu.tsx delete mode 100644 packages/react-topology/src/components/contextmenu/ContextSubMenuItem.tsx delete mode 100644 packages/react-topology/src/components/contextmenu/index.ts delete mode 100644 packages/react-topology/src/components/decorators/Decorator.tsx delete mode 100644 packages/react-topology/src/components/decorators/index.ts delete mode 100644 packages/react-topology/src/components/defs/Defs.tsx delete mode 100644 packages/react-topology/src/components/defs/SVGDefs.tsx delete mode 100644 packages/react-topology/src/components/defs/SVGDefsContext.ts delete mode 100644 packages/react-topology/src/components/defs/SVGDefsProvider.tsx delete mode 100644 packages/react-topology/src/components/defs/SVGDefsSetter.tsx delete mode 100644 packages/react-topology/src/components/defs/__mocks__/SVGDefs.tsx delete mode 100644 packages/react-topology/src/components/defs/__tests__/Defs.test.tsx delete mode 100644 packages/react-topology/src/components/defs/__tests__/SVGDefs.spec.tsx delete mode 100644 packages/react-topology/src/components/defs/index.ts delete mode 100644 packages/react-topology/src/components/edges/DefaultConnectorTag.tsx delete mode 100644 packages/react-topology/src/components/edges/DefaultEdge.tsx delete mode 100644 packages/react-topology/src/components/edges/index.ts delete mode 100644 packages/react-topology/src/components/edges/terminals/ConnectorArrow.tsx delete mode 100644 packages/react-topology/src/components/edges/terminals/ConnectorArrowAlt.tsx delete mode 100644 packages/react-topology/src/components/edges/terminals/ConnectorCircle.tsx delete mode 100644 packages/react-topology/src/components/edges/terminals/ConnectorCross.tsx delete mode 100644 packages/react-topology/src/components/edges/terminals/ConnectorSquare.tsx delete mode 100644 packages/react-topology/src/components/edges/terminals/DefaultConnectorTerminal.tsx delete mode 100644 packages/react-topology/src/components/edges/terminals/index.ts delete mode 100644 packages/react-topology/src/components/edges/terminals/terminalUtils.ts delete mode 100644 packages/react-topology/src/components/factories/RegisterComponentFactory.tsx delete mode 100644 packages/react-topology/src/components/factories/RegisterElementFactory.tsx delete mode 100644 packages/react-topology/src/components/factories/RegisterLayoutFactory.tsx delete mode 100644 packages/react-topology/src/components/factories/components/componentUtils.ts delete mode 100644 packages/react-topology/src/components/factories/components/index.ts delete mode 100644 packages/react-topology/src/components/factories/index.ts delete mode 100644 packages/react-topology/src/components/groups/CollapsedGroupAnchor.ts delete mode 100644 packages/react-topology/src/components/groups/DefaultGroup.tsx delete mode 100644 packages/react-topology/src/components/groups/DefaultGroupCollapsed.tsx delete mode 100644 packages/react-topology/src/components/groups/DefaultGroupExpanded.tsx delete mode 100644 packages/react-topology/src/components/groups/index.ts delete mode 100644 packages/react-topology/src/components/groups/types.ts delete mode 100644 packages/react-topology/src/components/index.ts delete mode 100644 packages/react-topology/src/components/layers/Layer.tsx delete mode 100644 packages/react-topology/src/components/layers/LayerContainer.tsx delete mode 100644 packages/react-topology/src/components/layers/LayersContext.ts delete mode 100644 packages/react-topology/src/components/layers/LayersProvider.tsx delete mode 100644 packages/react-topology/src/components/layers/index.ts delete mode 100644 packages/react-topology/src/components/nodes/DefaultNode.tsx delete mode 100644 packages/react-topology/src/components/nodes/NodeShadows.tsx delete mode 100644 packages/react-topology/src/components/nodes/index.ts delete mode 100644 packages/react-topology/src/components/nodes/labels/LabelActionIcon.tsx delete mode 100644 packages/react-topology/src/components/nodes/labels/LabelBadge.tsx delete mode 100644 packages/react-topology/src/components/nodes/labels/LabelContextMenu.tsx delete mode 100644 packages/react-topology/src/components/nodes/labels/LabelIcon.tsx delete mode 100644 packages/react-topology/src/components/nodes/labels/NodeLabel.tsx delete mode 100644 packages/react-topology/src/components/nodes/labels/index.ts delete mode 100644 packages/react-topology/src/components/nodes/shapes/Ellipse.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/Hexagon.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/Octagon.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/Rectangle.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/Rhombus.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/SidedShape.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/Stadium.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/Trapezoid.tsx delete mode 100644 packages/react-topology/src/components/nodes/shapes/index.ts delete mode 100644 packages/react-topology/src/components/nodes/shapes/shapeUtils.ts delete mode 100644 packages/react-topology/src/components/popper/Popper.tsx delete mode 100644 packages/react-topology/src/components/popper/Portal.tsx delete mode 100644 packages/react-topology/src/components/popper/index.ts delete mode 100644 packages/react-topology/src/components/svg/SvgDropShadowFilter.tsx delete mode 100644 packages/react-topology/src/const.ts delete mode 100644 packages/react-topology/src/declarations.d.ts delete mode 100644 packages/react-topology/src/elements/BaseEdge.ts delete mode 100644 packages/react-topology/src/elements/BaseElement.ts delete mode 100644 packages/react-topology/src/elements/BaseGraph.ts delete mode 100644 packages/react-topology/src/elements/BaseNode.ts delete mode 100644 packages/react-topology/src/elements/__tests__/BaseGraph.spec.ts delete mode 100644 packages/react-topology/src/elements/__tests__/BaseNode.spec.ts delete mode 100644 packages/react-topology/src/elements/__tests__/defaultElementFactory.spec.ts delete mode 100644 packages/react-topology/src/elements/defaultElementFactory.ts delete mode 100644 packages/react-topology/src/elements/index.ts delete mode 100644 packages/react-topology/src/geom/Dimensions.ts delete mode 100644 packages/react-topology/src/geom/Point.ts delete mode 100644 packages/react-topology/src/geom/Rect.ts delete mode 100644 packages/react-topology/src/geom/__tests__/Dimensions.spec.ts delete mode 100644 packages/react-topology/src/geom/__tests__/Point.spec.ts delete mode 100644 packages/react-topology/src/geom/__tests__/Rect.spec.ts delete mode 100644 packages/react-topology/src/geom/index.ts delete mode 100644 packages/react-topology/src/geom/types.ts delete mode 100644 packages/react-topology/src/hooks/index.ts delete mode 100644 packages/react-topology/src/hooks/useComponentFactory.tsx delete mode 100644 packages/react-topology/src/hooks/useDetailsLevel.tsx delete mode 100644 packages/react-topology/src/hooks/useElementFactory.tsx delete mode 100644 packages/react-topology/src/hooks/useEventListener.tsx delete mode 100644 packages/react-topology/src/hooks/useLayoutFactory.tsx delete mode 100644 packages/react-topology/src/hooks/useModel.tsx delete mode 100644 packages/react-topology/src/hooks/useScaleNode.tsx delete mode 100644 packages/react-topology/src/hooks/useVisualizationController.tsx delete mode 100644 packages/react-topology/src/hooks/useVisualizationState.tsx delete mode 100644 packages/react-topology/src/index.ts delete mode 100644 packages/react-topology/src/layouts/BaseLayout.ts delete mode 100644 packages/react-topology/src/layouts/BreadthFirstGroup.ts delete mode 100644 packages/react-topology/src/layouts/BreadthFirstLayout.ts delete mode 100644 packages/react-topology/src/layouts/BreadthFirstLink.ts delete mode 100644 packages/react-topology/src/layouts/BreadthFirstNode.ts delete mode 100644 packages/react-topology/src/layouts/ColaGroup.ts delete mode 100644 packages/react-topology/src/layouts/ColaGroupsLayout.ts delete mode 100644 packages/react-topology/src/layouts/ColaGroupsNode.ts delete mode 100644 packages/react-topology/src/layouts/ColaLayout.ts delete mode 100644 packages/react-topology/src/layouts/ColaLink.ts delete mode 100644 packages/react-topology/src/layouts/ColaNode.ts delete mode 100644 packages/react-topology/src/layouts/ConcentricGroup.ts delete mode 100644 packages/react-topology/src/layouts/ConcentricLayout.ts delete mode 100644 packages/react-topology/src/layouts/ConcentricLink.ts delete mode 100644 packages/react-topology/src/layouts/ConcentricNode.ts delete mode 100644 packages/react-topology/src/layouts/DagreGroup.ts delete mode 100644 packages/react-topology/src/layouts/DagreLayout.ts delete mode 100644 packages/react-topology/src/layouts/DagreLink.ts delete mode 100644 packages/react-topology/src/layouts/DagreNode.ts delete mode 100644 packages/react-topology/src/layouts/ForceLayout.ts delete mode 100644 packages/react-topology/src/layouts/ForceSimulation.ts delete mode 100644 packages/react-topology/src/layouts/GridGroup.ts delete mode 100644 packages/react-topology/src/layouts/GridLayout.ts delete mode 100644 packages/react-topology/src/layouts/GridLink.ts delete mode 100644 packages/react-topology/src/layouts/GridNode.ts delete mode 100644 packages/react-topology/src/layouts/LayoutGroup.ts delete mode 100644 packages/react-topology/src/layouts/LayoutLink.ts delete mode 100644 packages/react-topology/src/layouts/LayoutNode.ts delete mode 100644 packages/react-topology/src/layouts/LayoutOptions.ts delete mode 100644 packages/react-topology/src/layouts/index.ts delete mode 100644 packages/react-topology/src/mobx-exports.ts delete mode 100644 packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchor.ts delete mode 100644 packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchorSave.ts delete mode 100644 packages/react-topology/src/pipelines/components/anchors/TaskNodeTargetAnchor.ts delete mode 100644 packages/react-topology/src/pipelines/components/anchors/index.ts delete mode 100644 packages/react-topology/src/pipelines/components/edges/TaskEdge.tsx delete mode 100644 packages/react-topology/src/pipelines/components/edges/WhenEdge.tsx delete mode 100644 packages/react-topology/src/pipelines/components/edges/index.ts delete mode 100644 packages/react-topology/src/pipelines/components/groups/DefaultTaskGroup.tsx delete mode 100644 packages/react-topology/src/pipelines/components/groups/index.ts delete mode 100644 packages/react-topology/src/pipelines/components/index.ts delete mode 100644 packages/react-topology/src/pipelines/components/nodes/FinallyNode.tsx delete mode 100644 packages/react-topology/src/pipelines/components/nodes/SpacerNode.tsx delete mode 100644 packages/react-topology/src/pipelines/components/nodes/TaskBadge.tsx delete mode 100644 packages/react-topology/src/pipelines/components/nodes/TaskNode.tsx delete mode 100644 packages/react-topology/src/pipelines/components/nodes/index.ts delete mode 100644 packages/react-topology/src/pipelines/const.ts delete mode 100644 packages/react-topology/src/pipelines/decorators/WhenDecorator.tsx delete mode 100644 packages/react-topology/src/pipelines/decorators/index.ts delete mode 100644 packages/react-topology/src/pipelines/index.ts delete mode 100644 packages/react-topology/src/pipelines/layouts/PipelineDagreLayout.ts delete mode 100644 packages/react-topology/src/pipelines/layouts/index.ts delete mode 100644 packages/react-topology/src/pipelines/types.ts delete mode 100644 packages/react-topology/src/pipelines/utils/StatusIcon.tsx delete mode 100644 packages/react-topology/src/pipelines/utils/draw-utils.ts delete mode 100644 packages/react-topology/src/pipelines/utils/index.ts delete mode 100644 packages/react-topology/src/pipelines/utils/utils.ts delete mode 100644 packages/react-topology/src/types.ts delete mode 100644 packages/react-topology/src/utils/ControllerContext.ts delete mode 100644 packages/react-topology/src/utils/ElementContext.ts delete mode 100644 packages/react-topology/src/utils/Stateful.ts delete mode 100644 packages/react-topology/src/utils/__tests__/svg-utils.spec.ts delete mode 100644 packages/react-topology/src/utils/anchor-utils.ts delete mode 100644 packages/react-topology/src/utils/createAggregateEdges.ts delete mode 100644 packages/react-topology/src/utils/element-utils.ts delete mode 100644 packages/react-topology/src/utils/geom-utils.ts delete mode 100644 packages/react-topology/src/utils/getNodeScaleTranslation.ts delete mode 100644 packages/react-topology/src/utils/index.ts delete mode 100644 packages/react-topology/src/utils/style-utils.ts delete mode 100644 packages/react-topology/src/utils/svg-utils.ts delete mode 100644 packages/react-topology/src/utils/truncate-middle.ts delete mode 100644 packages/react-topology/src/utils/useCallbackRef.ts delete mode 100644 packages/react-topology/src/utils/useCombineRefs.tsx delete mode 100644 packages/react-topology/src/utils/useHover.ts delete mode 100644 packages/react-topology/src/utils/useSize.ts delete mode 100644 packages/react-topology/tsconfig.cjs.json delete mode 100644 packages/react-topology/tsconfig.json diff --git a/README.md b/README.md index 8093bd8d2fd..ebcd955715f 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ Using PatternFly 3? Take a look at the [PatternFly 3 React component informatio | **:family: Extension packages** *community supported* | |   [@patternfly/react-catalog-view-extension](./packages/react-catalog-view-extension/README.md) | Catalog view extension | |   [@patternfly/react-virtualized-extension](./packages/react-virtualized-extension/README.md) | Table and list row virtualization extension | -|   [@patternfly/react-topology](./packages/react-topology/README.md) | Topology components | | **:x: Deprecated packages** | |   [@patternfly/react-inline-edit-extension](./packages/react-inline-edit-extension/README.md) | Table inline edit extension | diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index f31fbf384f9..ce88d32b8ae 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -31,7 +31,6 @@ "@patternfly/react-styles": "^4.92.6", "@patternfly/react-table": "^4.113.0", "@patternfly/react-tokens": "^4.94.6", - "@patternfly/react-topology": "^4.91.40", "@patternfly/react-virtualized-extension": "^4.88.115" }, "devDependencies": { diff --git a/packages/react-docs/patternfly-docs/patternfly-docs.config.js b/packages/react-docs/patternfly-docs/patternfly-docs.config.js index a28df4af87b..e870285e3a1 100644 --- a/packages/react-docs/patternfly-docs/patternfly-docs.config.js +++ b/packages/react-docs/patternfly-docs/patternfly-docs.config.js @@ -12,7 +12,6 @@ module.exports = { { section: 'components' }, { section: 'demos' }, { section: 'extensions' }, - { section: 'topology' }, { section: 'layouts' } ], topNavItems: [{ text: 'Icons', path: '/icons' }], diff --git a/packages/react-docs/patternfly-docs/patternfly-docs.css.js b/packages/react-docs/patternfly-docs/patternfly-docs.css.js index cc9a28b5ff7..642562cc07e 100644 --- a/packages/react-docs/patternfly-docs/patternfly-docs.css.js +++ b/packages/react-docs/patternfly-docs/patternfly-docs.css.js @@ -1,10 +1,5 @@ // React-specific CSS import '@patternfly/react-styles/src/css/components/Table/inline-edit.css'; // inline-edit extension styles -import '@patternfly/react-styles/src/css/components/Topology/topology-controlbar.css'; -import '@patternfly/react-styles/src/css/components/Topology/topology-side-bar.css'; -import '@patternfly/react-styles/src/css/components/Topology/topology-view.css'; -import '@patternfly/react-styles/src/css/components/Topology/topology-components.css'; -import '@patternfly/react-styles/src/css/components/Topology/topology-pipelines.css'; import '@patternfly/react-styles/src/css/layouts/Toolbar/toolbar.css'; import '@patternfly/react-styles/src/css/components/Popper/Popper.css'; diff --git a/packages/react-docs/patternfly-docs/patternfly-docs.source.js b/packages/react-docs/patternfly-docs/patternfly-docs.source.js index 7fb5a7ee806..fe3ffd23aba 100644 --- a/packages/react-docs/patternfly-docs/patternfly-docs.source.js +++ b/packages/react-docs/patternfly-docs/patternfly-docs.source.js @@ -19,7 +19,6 @@ module.exports = (baseSourceMD, sourceProps) => { const reactVirtualizedPath = require .resolve('@patternfly/react-virtualized-extension/package.json') .replace('package.json', 'src'); - const reactTopologyPath = require.resolve('@patternfly/react-topology/package.json').replace('package.json', 'src'); const reactPropsIgnore = '**/*.test.tsx'; sourceProps(path.join(reactCorePath, '/**/*.tsx'), reactPropsIgnore); @@ -27,7 +26,6 @@ module.exports = (baseSourceMD, sourceProps) => { sourceProps(path.join(reactChartsPath, '/**/*.tsx'), reactPropsIgnore); sourceProps(path.join(reactCodeEditorPath, '/**/*.tsx'), reactPropsIgnore); sourceProps(path.join(reactVirtualizedPath, '/**/*.tsx'), reactPropsIgnore); - sourceProps(path.join(reactTopologyPath, '/**/*.tsx'), reactPropsIgnore); // React MD sourceMD(path.join(reactCorePath, '/components/**/examples/*.md'), 'react'); @@ -52,9 +50,6 @@ module.exports = (baseSourceMD, sourceProps) => { // Code Editor MD sourceMD(path.join(reactCodeEditorPath, '/**/examples/*.md'), 'react'); - // Topology MD - sourceMD(path.join(reactTopologyPath, '/**/examples/*.md'), 'react'); - // Release notes sourceMD(require.resolve('@patternfly/react-docs/RELEASE-NOTES.md'), 'react'); diff --git a/packages/react-integration/demo-app-ts/src/Demos.ts b/packages/react-integration/demo-app-ts/src/Demos.ts index dc9f4d1c8a3..fcac5290bee 100644 --- a/packages/react-integration/demo-app-ts/src/Demos.ts +++ b/packages/react-integration/demo-app-ts/src/Demos.ts @@ -507,16 +507,6 @@ export const Demos: DemoInterface[] = [ name: 'Tooltip Demo', componentType: Examples.TooltipDemo }, - { - id: 'topology-demo', - name: 'Topology Demo', - componentType: Examples.TopologyDemo - }, - { - id: 'topology-pipelines-demo', - name: 'Topology Pipelines Demo', - componentType: Examples.TopologyPipelineDemo - }, { id: 'treeview-demo', name: 'Tree View Demo', diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Basics.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Basics.tsx deleted file mode 100644 index e78bb33a624..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Basics.tsx +++ /dev/null @@ -1,314 +0,0 @@ -import * as React from 'react'; -import { - DefaultNode, - Model, - ModelKind, - withDragNode, - useComponentFactory, - useModel, - ComponentFactory -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import withTopologySetup from './utils/withTopologySetup'; -import CustomCircleNode from './components/CustomCircleNode'; -import CustomRectNode from './components/CustomRectNode'; - -export const SingleNode = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 50, - y: 50, - width: 20, - height: 20 - } - ] - }), - [] - ) - ); - return null; -}); - -export const SingleEdge = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 20, - y: 20, - width: 20, - height: 20 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 50, - width: 100, - height: 30 - } - ], - edges: [ - { - id: 'e1', - type: 'edge', - source: 'n1', - target: 'n2', - bendpoints: [ - [80, 30], - [110, 10] - ] - } - ] - }), - [] - ) - ); - return null; -}); - -export const MultiEdge = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback(kind => { - if (kind === ModelKind.node) { - return withDragNode()(DefaultNode); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 50, - y: 50, - width: 100, - height: 100 - }, - { - id: 'n2', - type: 'node', - x: 400, - y: 50, - width: 100, - height: 100 - }, - { - id: 'n3', - type: 'node', - x: 50, - y: 200, - width: 100, - height: 100 - }, - { - id: 'n4', - type: 'node', - x: 400, - y: 200, - width: 100, - height: 100 - } - ], - edges: [ - { - id: 'e1', - type: 'multi-edge', - source: 'n1', - target: 'n2' - }, - { - id: 'e2', - type: 'multi-edge', - source: 'n1', - target: 'n2' - }, - { - id: 'e3', - type: 'multi-edge', - source: 'n3', - target: 'n4' - }, - { - id: 'e4', - type: 'multi-edge', - source: 'n3', - target: 'n4' - }, - { - id: 'e5', - type: 'multi-edge', - source: 'n3', - target: 'n4' - }, - { - id: 'e6', - type: 'multi-edge', - source: 'n3', - target: 'n4' - }, - { - id: 'e7', - type: 'multi-edge', - source: 'n3', - target: 'n4' - } - ] - }), - [] - ) - ); - return null; -}); - -const groupStory = (groupType: string): React.FunctionComponent => () => { - useComponentFactory(defaultComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'gr1', - type: groupType, - group: true, - children: ['n1', 'n2', 'n3'], - style: { - padding: 10 - } - }, - { - id: 'n1', - type: 'node', - x: 50, - y: 50, - width: 30, - height: 30 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 20, - width: 10, - height: 10 - }, - { - id: 'n3', - type: 'node', - x: 150, - y: 100, - width: 20, - height: 20 - } - ] - }), - [] - ) - ); - return null; -}; - -export const Group = withTopologySetup(groupStory('group')); -export const GroupHull = withTopologySetup(groupStory('group-hull')); - -export const AutoSizeNode = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback((kind, type) => { - if (type === 'autoSize-circle') { - return CustomCircleNode; - } - if (type === 'autoSize-rect') { - return CustomRectNode; - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'autoSize-rect', - x: 50, - y: 50 - }, - - { - id: 'n2', - type: 'autoSize-circle', - x: 250, - y: 200 - }, - - { - id: 'n3', - type: 'autoSize-rect', - x: 300, - y: 70 - }, - { - id: 'gr1', - type: 'group', - group: true, - children: ['n1', 'n3'], - style: { - padding: 10 - } - } - ], - edges: [ - { - id: 'e1', - type: 'edge', - source: 'n1', - target: 'n2' - }, - { - id: 'e2', - type: 'edge', - source: 'gr1', - target: 'n2' - } - ] - }), - [] - ) - ); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/CollapsibleGroups.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/CollapsibleGroups.tsx deleted file mode 100644 index efc989cd3ff..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/CollapsibleGroups.tsx +++ /dev/null @@ -1,249 +0,0 @@ -import * as React from 'react'; -import { action } from 'mobx'; -import { - TopologyView, - TopologyControlBar, - createTopologyControlButtons, - defaultControlButtonsOptions, - EdgeModel, - Model, - ModelKind, - NodeModel, - Visualization, - withPanZoom, - GraphComponent, - withDragNode, - VisualizationSurface, - SELECTION_EVENT, - SelectionEventListener, - withSelection, - createAggregateEdges, - VisualizationProvider, - useEventListener -} from '@patternfly/react-topology'; -import { ToolbarGroup, ToolbarItem, Checkbox } from '@patternfly/react-core'; -import defaultLayoutFactory from './layouts/defaultLayoutFactory'; -import data from './data/group-types'; -import GroupHull from './components/GroupHull'; -import Group from './components/DefaultGroup'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import defaultComponentFactory from './components/defaultComponentFactory'; - -const getModel = (collapseTypes: string[] = []): Model => { - // create nodes from data - const nodes: NodeModel[] = data.nodes.map(d => { - if (d.type) { - return { - type: d.type, - id: d.id, - group: true, - children: data.nodes.filter((n: any) => n.group === d.id).map(n => n.id), - label: d.id, - width: d.width, - height: d.height, - collapsed: collapseTypes.includes(d.type), - style: { - padding: 10 - }, - data: { - background: d.color - } - }; - } - // randomize size somewhat - const width = 50 + d.id.length; - const height = 50 + d.id.length; - return { - id: d.id, - type: 'node', - width, - height, - data: d, - groupId: d.group - }; - }); - - // create links from data - const edges = data.links.map( - (d): EdgeModel => ({ - data: d, - source: d.source, - target: d.target, - id: `${d.source}_${d.target}`, - type: 'edge' - }) - ); - - // create topology model - return { - nodes, - edges: createAggregateEdges('aggregate-edge', edges, nodes) - }; -}; - -const getVisualization = (model: Model): Visualization => { - const vis = new Visualization(); - model.graph = { - id: 'graph1', - type: 'graph', - layout: 'Cola' - }; - - vis.registerLayoutFactory(defaultLayoutFactory); - vis.registerComponentFactory(defaultComponentFactory); - - // support pan zoom, drag, and selection - vis.registerComponentFactory((kind, type) => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (type === 'lightblue' || type === 'cyan') { - return withDragNode({ canCancel: false })(GroupHull); - } - if (type === 'blue' || type === 'orange' || type === 'pink') { - return withDragNode({ canCancel: false })(Group); - } - if (kind === ModelKind.node) { - return withDragNode({ canCancel: false })(withSelection()(DemoDefaultNode)); - } - return undefined; - }); - - vis.fromModel(model); - - return vis; -}; - -interface TopologyViewComponentProps { - vis: Visualization; -} - -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); - - useEventListener(SELECTION_EVENT, ids => { - setSelectedIds(ids); - }); - - const viewToolbar = ( - <> - - - setCollapseBlue(checked)} - /> - - - - - setCollapseLightBlue(checked)} - /> - - - - - setCollapseCyan(checked)} - /> - - - - - setCollapseOrange(checked)} - /> - - - - - setCollapsePink(checked)} - /> - - - - ); - - React.useEffect(() => { - action(() => { - const collapsedTypes: string[] = []; - if (collapseBlue) { - collapsedTypes.push('blue'); - } - if (collapseLightBlue) { - collapsedTypes.push('lightblue'); - } - if (collapseCyan) { - collapsedTypes.push('cyan'); - } - if (collapseOrange) { - collapsedTypes.push('orange'); - } - if (collapsePink) { - collapsedTypes.push('pink'); - } - const modelUpdate = getModel(collapsedTypes); - vis.fromModel(modelUpdate); - })(); - }, [vis, collapseBlue, collapseLightBlue, collapseCyan, collapseOrange, collapsePink]); - - return ( - { - vis.getGraph().scaleBy(4 / 3); - }), - zoomOutCallback: action(() => { - vis.getGraph().scaleBy(0.75); - }), - fitToScreenCallback: action(() => { - vis.getGraph().fit(80); - }), - resetViewCallback: action(() => { - vis.getGraph().reset(); - vis.getGraph().layout(); - }), - legend: false - })} - /> - } - viewToolbar={viewToolbar} - > - - - ); -}; - -export const CollapsibleGroups = () => { - const vis: Visualization = getVisualization(getModel()); - - return ( - - - - ); -}; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Connectors.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Connectors.tsx deleted file mode 100644 index 66b729e02f4..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Connectors.tsx +++ /dev/null @@ -1,358 +0,0 @@ -import * as React from 'react'; -import { - Model, - ModelKind, - Edge, - Node, - AnchorEnd, - withTargetDrag, - withSourceDrag, - DragEvent, - DragObjectWithType, - withDndDrop, - withPanZoom, - GraphComponent, - withCreateConnector, - CREATE_CONNECTOR_DROP_TYPE, - ConnectorChoice, - useSvgAnchor, - withDragNode, - WithDragNodeProps, - Layer, - Graph, - isGraph, - useModel, - useComponentFactory, - ComponentFactory, - useVisualizationController -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import DefaultEdge from './components/DefaultEdge'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import withTopologySetup from './utils/withTopologySetup'; -import NodeRect from './components/NodeRect'; - -interface NodeProps { - element: Node; -} - -interface EdgeProps { - element: Edge; -} - -export const Reconnect = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback(kind => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (kind === ModelKind.node) { - return withDndDrop({ - accept: 'test', - canDrop: (item, monitor, props) => - !props || (item.getSource() !== props.element && item.getTarget() !== props.element), - collect: monitor => ({ - droppable: monitor.isDragging(), - hover: monitor.isOver(), - canDrop: monitor.canDrop() - }) - })(DemoDefaultNode); - } - if (kind === ModelKind.edge) { - return withSourceDrag({ - item: { type: 'test' }, - begin: (monitor, props) => { - props.element.raise(); - return props.element; - }, - drag: (event, monitor, props) => { - props.element.setStartPoint(event.x, event.y); - }, - end: (dropResult, monitor, props) => { - if (monitor.didDrop() && dropResult && props) { - props.element.setSource(dropResult); - } - props.element.setStartPoint(); - } - })( - withTargetDrag({ - item: { type: 'test' }, - begin: (monitor, props) => { - props.element.raise(); - return props.element; - }, - drag: (event, monitor, props) => { - props.element.setEndPoint(event.x, event.y); - }, - end: (dropResult, monitor, props) => { - if (monitor.didDrop() && dropResult && props) { - props.element.setTarget(dropResult); - } - props.element.setEndPoint(); - }, - collect: monitor => ({ - dragging: monitor.isDragging() - }) - })(DefaultEdge) - ); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 20, - y: 150, - width: 20, - height: 20 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 50, - width: 100, - height: 30 - }, - { - id: 'n3', - type: 'node', - x: 200, - y: 300, - width: 30, - height: 30 - } - ], - edges: [ - { - id: 'e1', - type: 'edge', - source: 'n1', - target: 'n2', - bendpoints: [ - [50, 30], - [110, 10] - ] - }, - { - id: 'e2', - type: 'edge', - source: 'n1', - target: 'n3' - } - ] - }), - [] - ) - ); - return null; -}); - -type ColorChoice = ConnectorChoice & { - color: string; -}; - -export const CreateConnector = withTopologySetup(() => { - const model = React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 20, - y: 150, - width: 104, - height: 104 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 50, - width: 100, - height: 30 - }, - { - id: 'n3', - type: 'node', - x: 200, - y: 300, - width: 30, - height: 30 - } - ] - }), - [] - ); - const controller = useVisualizationController(); - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback( - kind => { - if (kind === ModelKind.graph) { - return withDndDrop({ - accept: CREATE_CONNECTOR_DROP_TYPE, - dropHint: 'create' - })(withPanZoom()(GraphComponent)); - } - if (kind === ModelKind.node) { - return withCreateConnector( - ( - source: Node, - target: Node | Graph, - event: DragEvent, - dropHints: string[], - choice: ColorChoice | undefined - ): ColorChoice[] | void => { - if (!choice) { - return [ - { label: 'Create Annotation', color: 'red' }, - { label: 'Create Binding', color: 'green' } - ]; - } - - let targetId; - if (isGraph(target)) { - if (!model.nodes) { - model.nodes = []; - } - targetId = `n${controller.getGraph().getNodes().length + 1}`; - model.nodes.push({ - id: targetId, - type: 'node', - x: event.x - 15, - y: event.y - 15, - height: 30, - width: 30 - }); - } else { - targetId = target.getId(); - } - const id = `e${controller.getGraph().getEdges().length + 1}`; - if (!model.edges) { - model.edges = []; - } - model.edges.push({ - id, - type: 'edge', - source: source.getId(), - target: targetId, - data: { - color: choice.color - } - }); - controller.fromModel(model); - } - )( - withDndDrop({ - accept: CREATE_CONNECTOR_DROP_TYPE, - canDrop: (item, monitor, props) => !props || item !== props.element, - collect: monitor => ({ - droppable: monitor.isDragging(), - hover: monitor.isOver(), - canDrop: monitor.canDrop() - }) - })(DemoDefaultNode) - ); - } - return undefined; - }, - [model, controller] - ) - ); - useModel(model); - return null; -}); - -const NodeWithPointAnchor: React.FunctionComponent<{ element: Node } & WithDragNodeProps> = props => { - const nodeRef = useSvgAnchor(); - const targetRef = useSvgAnchor(AnchorEnd.target, 'edge-point'); - const { width, height } = props.element.getDimensions(); - return ( - <> - - - - - - - ); -}; - -export const Anchors = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback(kind => { - if (kind === ModelKind.node) { - return withDragNode()(NodeWithPointAnchor); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 150, - y: 10, - width: 100, - height: 100 - }, - { - id: 'n2', - type: 'node', - x: 25, - y: 250, - width: 50, - height: 50 - }, - { - id: 'n3', - type: 'node', - x: 225, - y: 250, - width: 50, - height: 50 - } - ], - edges: [ - { - id: 'e1', - type: 'edge-point', - source: 'n1', - target: 'n3' - }, - { - id: 'e2', - type: 'edge-point', - source: 'n2', - target: 'n1' - } - ] - }), - [] - ) - ); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/ContextMenus.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/ContextMenus.tsx deleted file mode 100644 index fd7a49aac66..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/ContextMenus.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from 'react'; -import { - ContextMenu, - ContextMenuItem, - ContextMenuSeparator, - Model, - ModelKind, - withDragNode, - withPanZoom, - GraphComponent, - withContextMenu, - useModel, - useComponentFactory, - ComponentFactory -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import withTopologySetup from './utils/withTopologySetup'; - -const contextMenuItem = (label: string, i: number): React.ReactElement => { - if (label === '-') { - return ; - } - return ( - // eslint-disable-next-line no-alert - alert(`Selected: ${label}`)}> - {label} - - ); -}; - -const createContextMenuItems = (...labels: string[]): React.ReactElement[] => labels.map(contextMenuItem); - -const defaultMenu = createContextMenuItems('First', 'Second', 'Third', '-', 'Fourth'); - -export const UncontrolledContextMenu = () => ( - <> -

Dismiss the context menu by pressing `ESC` or clicking away.

- {defaultMenu} - -); - -export const ControlledContextMenu = () => { - const [open, setOpen] = React.useState(false); - return ( - <> - - setOpen(false)}> - {defaultMenu} - - - ); -}; - -export const ContextMenuOnNode = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback(kind => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (kind === ModelKind.node) { - return withDragNode()(withContextMenu(() => defaultMenu)(DemoDefaultNode)); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'n1', - type: 'node', - x: 50, - y: 50, - width: 20, - height: 20 - } - ] - }), - [] - ) - ); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/DragDrop.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/DragDrop.tsx deleted file mode 100644 index 4574a6ff839..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/DragDrop.tsx +++ /dev/null @@ -1,252 +0,0 @@ -import * as React from 'react'; -import { - Model, - Node, - ModelKind, - withDndDrag, - Modifiers, - withDndDrop, - GraphComponent, - withPanZoom, - DragObjectWithType, - withDragNode, - useModel, - useComponentFactory, - ComponentFactory -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import GroupHull from './components/GroupHull'; -import withTopologySetup from './utils/withTopologySetup'; - -interface ElementProps { - element: Node; -} - -export const Dnd = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - // support pan zoom and drag - useComponentFactory( - React.useCallback((kind, type) => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (type === 'group-drop') { - return withDndDrop({ - accept: 'test', - canDrop: (item, monitor, props) => !!props && item.getParent() !== props.element, - collect: monitor => ({ - droppable: monitor.isDragging(), - hover: monitor.isOver(), - canDrop: monitor.canDrop() - }) - })(GroupHull); - } - if (type === 'node-drag') { - return withDndDrag({ - item: { type: 'test' }, - begin: (monitor, props) => { - props.element.raise(); - return props.element; - }, - drag: (event, monitor, props) => { - props.element.setPosition( - props.element - .getPosition() - .clone() - .translate(event.dx, event.dy) - ); - }, - end: (dropResult, monitor, props) => { - if (monitor.didDrop() && dropResult && props) { - dropResult.appendChild(props.element); - } - } - })(DemoDefaultNode); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'gr1', - type: 'group-drop', - group: true, - children: ['n2', 'n3'], - style: { - padding: 10 - } - }, - { - id: 'gr2', - type: 'group-drop', - group: true, - children: ['n4', 'n5'], - style: { - padding: 10 - } - }, - { - id: 'n1', - type: 'node-drag', - x: 50, - y: 50, - width: 30, - height: 30 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 20, - width: 10, - height: 10 - }, - { - id: 'n3', - type: 'node', - x: 150, - y: 100, - width: 20, - height: 20 - }, - { - id: 'n4', - type: 'node', - x: 300, - y: 250, - width: 30, - height: 30 - }, - { - id: 'n5', - type: 'node', - x: 350, - y: 370, - width: 15, - height: 15 - } - ] - }), - [] - ) - ); - return null; -}); - -export const DndShiftRegroup = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - // support pan zoom and drag - useComponentFactory( - React.useCallback((kind, type) => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (type === 'group-drop') { - return withDndDrop({ - accept: 'test', - canDrop: (item, monitor, props) => - item && monitor.getOperation().type === 'regroup' && !!props && item.getParent() !== props.element, - collect: monitor => ({ - droppable: monitor.isDragging() && monitor.getOperation().type === 'regroup', - hover: monitor.isOver(), - canDrop: monitor.canDrop() - }) - })(GroupHull); - } - if (type === 'node-drag') { - return withDragNode({ - item: { type: 'test' }, - operation: () => ({ - [Modifiers.SHIFT]: { type: 'regroup' } - }), - end: (dropResult, monitor, props) => { - if (monitor.didDrop() && dropResult && props) { - dropResult.appendChild(props.element); - } - } - })(DemoDefaultNode); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'gr1', - type: 'group-drop', - group: true, - children: ['n2', 'n3'], - style: { - padding: 10 - } - }, - { - id: 'gr2', - type: 'group-drop', - group: true, - children: ['n4', 'n5'], - style: { - padding: 10 - } - }, - { - id: 'n1', - type: 'node-drag', - x: 50, - y: 50, - width: 30, - height: 30 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 20, - width: 10, - height: 10 - }, - { - id: 'n3', - type: 'node', - x: 150, - y: 100, - width: 20, - height: 20 - }, - { - id: 'n4', - type: 'node', - x: 300, - y: 250, - width: 30, - height: 30 - }, - { - id: 'n5', - type: 'node', - x: 350, - y: 370, - width: 15, - height: 15 - } - ] - }), - [] - ) - ); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Groups.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Groups.tsx deleted file mode 100644 index 3ca53a6c89f..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Groups.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - Model, - Node, - AnchorEnd, - NodeShape, - useSvgAnchor, - withDragNode, - WithDragNodeProps, - useModel, - useLayoutFactory, - useComponentFactory, - ComponentFactory -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import DefaultGroup from './components/DefaultGroup'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import defaultLayoutFactory from './layouts/defaultLayoutFactory'; -import withTopologySetup from './utils/withTopologySetup'; - -const GroupWithDecorator: React.FunctionComponent<{ element: Node } & WithDragNodeProps> = observer(props => { - const trafficSourceRef = useSvgAnchor(AnchorEnd.source, 'traffic'); - const b = props.element.getBounds(); - return ( - - - - ); -}); - -export const ComplexGroup = withTopologySetup(() => { - useLayoutFactory(defaultLayoutFactory); - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback((kind, type) => { - if (type === 'service') { - return withDragNode()(GroupWithDecorator); - } - if (type === 'node') { - return withDragNode()(DemoDefaultNode); - } - return undefined; - }, []) - ); - - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph', - layout: 'Force' - }, - nodes: [ - { - id: 'gr1', - type: 'group-hull', - group: true, - children: ['n1', 'n2', 's1'], - style: { - padding: 50 - } - }, - - { - id: 's1', - type: 'service', - group: true, - children: ['r1', 'r2'], - shape: NodeShape.rect, - style: { - padding: 25 - } - }, - { - id: 's2', - type: 'service', - group: true, - shape: NodeShape.rect, - width: 100, - height: 100, - style: { - padding: 25 - } - }, - { - id: 'n1', - type: 'node', - x: 100, - y: 150, - width: 100, - height: 100 - }, - { - id: 'n2', - type: 'node', - x: 450, - y: 100, - width: 100, - height: 100 - }, - { - id: 'r1', - type: 'node', - x: 250, - y: 300, - width: 100, - height: 100 - }, - { - id: 'r2', - type: 'node', - x: 370, - y: 320, - width: 100, - height: 100 - } - ], - edges: [ - { - id: 't1', - type: 'traffic', - source: 's1', - target: 'r1' - }, - { - id: 't2', - type: 'traffic', - source: 's1', - target: 'r2' - } - ] - }), - [] - ) - ); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Layouts.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Layouts.tsx deleted file mode 100644 index 85b7da39573..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Layouts.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import * as React from 'react'; -import { - Model, - ModelKind, - withPanZoom, - GraphComponent, - withDragNode, - useComponentFactory, - useLayoutFactory, - useModel, - ComponentFactory -} from '@patternfly/react-topology'; -import defaultLayoutFactory from './layouts/defaultLayoutFactory'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import GroupHull from './components/GroupHull'; -import Group from './components/DefaultGroup'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import withTopologySetup from './utils/withTopologySetup'; -import { generateDataModel } from './data/generator'; -import stylesComponentFactory from './components/stylesComponentFactory'; - -const getModel = (layout: string): Model => { - // create nodes from data - const model = generateDataModel(200, 5, 20); - model.graph = { - id: 'g1', - type: 'graph', - layout - }; - - return model; -}; - -const layoutStory = (model: Model): React.FunctionComponent => () => { - useLayoutFactory(defaultLayoutFactory); - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - - // support pan zoom and drag - useComponentFactory( - React.useCallback((kind: string, type: string) => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (type === 'group-hull') { - return withDragNode()(GroupHull); - } - if (type === 'group') { - return withDragNode()(Group); - } - if (kind === ModelKind.node) { - return withDragNode()(DemoDefaultNode); - } - return undefined; - }, []) - ); - useModel(model); - return null; -}; - -export const Force = withTopologySetup(layoutStory(getModel('Force'))); -export const Dagre = withTopologySetup(layoutStory(getModel('Dagre'))); -export const Cola = withTopologySetup(layoutStory(getModel('Cola'))); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PanZoom.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PanZoom.tsx deleted file mode 100644 index f6f16af64cb..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PanZoom.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import { reaction } from 'mobx'; -import { - Model, - ModelKind, - withPanZoom, - GraphComponent, - useComponentFactory, - useVisualizationController, - useModel, - ComponentFactory -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import withTopologySetup from './utils/withTopologySetup'; - -const model: Model = { - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'gr1', - type: 'group-hull', - group: true, - children: ['n1', 'n2'], - style: { - padding: 10 - } - }, - { - id: 'n1', - type: 'node', - x: 200, - y: 200, - width: 50, - height: 50 - }, - { - id: 'n2', - type: 'node', - x: 300, - y: 300, - width: 100, - height: 100 - } - ] -}; - -export const PanZoom: React.FunctionComponent = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory( - React.useCallback(kind => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - return undefined; - }, []) - ); - const controller = useVisualizationController(); - - React.useEffect(() => { - reaction( - () => ({ - x: controller.getGraph().getBounds().x, - y: controller.getGraph().getBounds().y, - k: controller.getGraph().getScale() - }), - transform => { - // eslint-disable-next-line no-console - console.log(`Pan zoom event`, transform); - } - ); - }, [controller]); - useModel(model); - return null; -}); -PanZoom.displayName = 'PanZoom'; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineLayout.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineLayout.tsx deleted file mode 100644 index f22aa32e9d4..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineLayout.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import React from 'react'; -import { - Graph, - Layout, - PipelineDagreLayout, - Visualization, - VisualizationProvider, - useEventListener, - SelectionEventListener, - SELECTION_EVENT, - TopologyView, - VisualizationSurface, - useVisualizationController, - NODE_SEPARATION_HORIZONTAL, - GRAPH_LAYOUT_END_EVENT, - getSpacerNodes, - getEdgesFromNodes, - DEFAULT_EDGE_TYPE, - DEFAULT_SPACER_NODE_TYPE, - DEFAULT_FINALLY_NODE_TYPE -} from '@patternfly/react-topology'; -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; -import pipelineComponentFactory, { GROUPED_EDGE_TYPE } from './components/pipelineComponentFactory'; -import { usePipelineOptions } from './usePipelineOptions'; -import { useDemoPipelineNodes } from './useDemoPipelineNodes'; -import { GROUPED_PIPELINE_NODE_SEPARATION_HORIZONTAL } from './components/DemoTaskGroupEdge'; - -export const PIPELINE_NODE_SEPARATION_VERTICAL = 65; - -export const LAYOUT_TITLE = 'Layout'; - -const PIPELINE_LAYOUT = 'PipelineLayout'; -const GROUPED_PIPELINE_LAYOUT = 'GroupedPipelineLayout'; - -const TopologyPipelineLayout: React.FC = () => { - const [selectedIds, setSelectedIds] = React.useState(); - - const controller = useVisualizationController(); - const { contextToolbar, showContextMenu, showBadges, showIcons, showGroups, badgeTooltips } = usePipelineOptions( - true - ); - const pipelineNodes = useDemoPipelineNodes( - showContextMenu, - showBadges, - showIcons, - badgeTooltips, - 'PipelineDagreLayout', - showGroups - ); - - React.useEffect(() => { - const spacerNodes = getSpacerNodes(pipelineNodes); - const nodes = [...pipelineNodes, ...spacerNodes]; - const edgeType = showGroups ? GROUPED_EDGE_TYPE : DEFAULT_EDGE_TYPE; - const edges = getEdgesFromNodes( - nodes.filter(n => !n.group), - DEFAULT_SPACER_NODE_TYPE, - edgeType, - edgeType, - [DEFAULT_FINALLY_NODE_TYPE], - edgeType - ); - - controller.fromModel( - { - graph: { - id: 'g1', - type: 'graph', - x: 25, - y: 25, - layout: showGroups ? GROUPED_PIPELINE_LAYOUT : PIPELINE_LAYOUT - }, - nodes, - edges - }, - true - ); - controller.getGraph().layout(); - }, [controller, pipelineNodes, showGroups]); - - useEventListener(SELECTION_EVENT, ids => { - setSelectedIds(ids); - }); - - return ( - - - - ); -}; - -TopologyPipelineLayout.displayName = 'TopologyPipelineLayout'; - -export const PipelineLayout = React.memo(() => { - const controller = new Visualization(); - controller.setFitToScreenOnLayout(true); - controller.registerComponentFactory(pipelineComponentFactory); - controller.registerLayoutFactory( - (type: string, graph: Graph): Layout | undefined => - new PipelineDagreLayout(graph, { - nodesep: PIPELINE_NODE_SEPARATION_VERTICAL, - ranksep: - type === GROUPED_PIPELINE_LAYOUT ? GROUPED_PIPELINE_NODE_SEPARATION_HORIZONTAL : NODE_SEPARATION_HORIZONTAL, - ignoreGroups: true - }) - ); - controller.fromModel( - { - graph: { - id: 'g1', - type: 'graph', - x: 25, - y: 25, - layout: PIPELINE_LAYOUT - } - }, - false - ); - controller.addEventListener(GRAPH_LAYOUT_END_EVENT, () => { - controller.getGraph().fit(75); - }); - - return ( - - - - ); -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineTasks.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineTasks.tsx deleted file mode 100644 index 451ed49833e..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/PipelineTasks.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import { - TopologyView, - Visualization, - VisualizationProvider, - VisualizationSurface, - useEventListener, - SelectionEventListener, - SELECTION_EVENT, - useVisualizationController -} from '@patternfly/react-topology'; -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; -import pipelineComponentFactory from './components/pipelineComponentFactory'; -import { usePipelineOptions } from './usePipelineOptions'; -import { useDemoPipelineNodes } from './useDemoPipelineNodes'; - -export const TASKS_TITLE = 'Tasks'; - -export const PipelineTasks: React.FC = () => { - const [selectedIds, setSelectedIds] = React.useState(); - - const controller = useVisualizationController(); - const { contextToolbar, showContextMenu, showBadges, showIcons, badgeTooltips } = usePipelineOptions(); - const pipelineNodes = useDemoPipelineNodes(showContextMenu, showBadges, showIcons, badgeTooltips); - - React.useEffect(() => { - controller.fromModel( - { - graph: { - id: 'g1', - type: 'graph', - x: 25, - y: 25 - }, - nodes: pipelineNodes - }, - false - ); - }, [controller, pipelineNodes]); - - useEventListener(SELECTION_EVENT, ids => { - setSelectedIds(ids); - }); - - return ( - - - - ); -}; - -PipelineTasks.displayName = 'PipelineTasks'; - -export const TopologyPipelineTasks = React.memo(() => { - const controller = new Visualization(); - controller.registerComponentFactory(pipelineComponentFactory); - return ( - - - - ); -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Selection.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Selection.tsx deleted file mode 100644 index 01e1bab80b4..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Selection.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import * as React from 'react'; -import { - Model, - ModelKind, - NodeModel, - withSelection, - SELECTION_EVENT, - SelectionEventListener, - useComponentFactory, - ComponentFactory, - useModel, - useEventListener, - useVisualizationState, - SELECTION_STATE -} from '@patternfly/react-topology'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import withTopologySetup from './utils/withTopologySetup'; - -const twoNodeModel: Model = { - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - { - id: 'gr1', - type: 'group', - group: true, - children: ['n1', 'n2'], - style: { - padding: 10 - } - }, - { - id: 'n1', - type: 'node', - x: 30, - y: 30, - width: 20, - height: 20 - }, - { - id: 'n2', - type: 'node', - x: 100, - y: 30, - width: 20, - height: 20 - } - ] -}; - -export const UncontrolledSelection: React.FunctionComponent = withTopologySetup(() => { - useComponentFactory( - React.useCallback((kind, type) => { - const widget = defaultComponentFactory(kind, type); - if (kind === ModelKind.node || kind === ModelKind.graph) { - // TODO fix any type - return withSelection({ multiSelect: false, controlled: false })(widget as any); - } - return widget; - }, []) - ); - useEventListener( - SELECTION_EVENT, - React.useCallback(([id]) => { - // eslint-disable-next-line no-console - console.log(`Selection event`, id); - }, []) - ); - useModel(twoNodeModel); - return null; -}); -UncontrolledSelection.displayName = 'UncontrolledSelection'; - -export const ControlledSelection = withTopologySetup(() => { - const [, setSelectedIds] = useVisualizationState(SELECTION_STATE); - useComponentFactory( - React.useCallback((kind, type) => { - const widget = defaultComponentFactory(kind, type); - if (kind === ModelKind.node || kind === ModelKind.graph) { - // TODO fix any type - return withSelection({ multiSelect: false, controlled: true })(widget as any); - } - return widget; - }, []) - ); - useEventListener( - SELECTION_EVENT, - React.useCallback( - ids => { - // eslint-disable-next-line no-console - console.log(`Selection event`, ids); - setSelectedIds(ids); - }, - [setSelectedIds] - ) - ); - useModel(twoNodeModel); - return null; -}); - -export const MultiSelect: React.FunctionComponent = withTopologySetup(() => { - useModel(twoNodeModel); - useComponentFactory( - React.useCallback((kind, type) => { - const widget = defaultComponentFactory(kind, type); - if (kind === ModelKind.node || kind === ModelKind.graph) { - // TODO fix any type - return withSelection({ multiSelect: true, controlled: false })(widget as any); - } - return widget; - }, []) - ); - useEventListener( - SELECTION_EVENT, - React.useCallback(ids => { - // eslint-disable-next-line no-console - console.log(`Selection event`, ids); - }, []) - ); - return null; -}); -MultiSelect.displayName = 'MultiSelect'; - -const perfModel: Model = { - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [] -}; -for (let i = 1; i <= 100; i++) { - for (let j = 1; j <= 100; j++) { - const node: NodeModel = { - id: `${i}-${j}`, - type: 'node', - x: j * 20, - y: i * 20, - width: 10, - height: 10 - }; - perfModel.nodes.push(node); - } -} - -export const Performance: React.FunctionComponent = withTopologySetup(() => { - useModel(perfModel); - useComponentFactory( - React.useCallback((kind, type) => { - const widget = defaultComponentFactory(kind, type); - if (kind === ModelKind.node || kind === ModelKind.graph) { - // TODO fix any type - return withSelection({ multiSelect: true, controlled: false, raiseOnSelect: false })(widget as any); - } - return widget; - }, []) - ); - return null; -}); -Performance.displayName = 'Performance'; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Shapes.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Shapes.tsx deleted file mode 100644 index 39442fbd79c..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Shapes.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import React from 'react'; -import { - Model, - ModelKind, - withPanZoom, - GraphComponent, - withDragNode, - useComponentFactory, - useModel, - ComponentFactory, - NodeShape -} from '@patternfly/react-topology'; -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import shapesComponentFactory from './components/shapesComponentFactory'; -import DemoDefaultNode from './components/DemoDefaultNode'; -import withTopologySetup from './utils/withTopologySetup'; - -export const SHAPE_TITLE = 'Shapes'; - -export const Shapes = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(shapesComponentFactory); - // support pan zoom and drag - useComponentFactory( - React.useCallback((kind, type) => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (type === 'node-drag') { - return withDragNode()(DemoDefaultNode); - } - return undefined; - }, []) - ); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph', - x: 25, - y: 25 - }, - nodes: [ - { - id: 'gr1', - type: 'group-hull', - group: true, - children: ['n2', 'n3'], - style: { - padding: 10 - } - }, - { - id: 'gr2', - type: 'group-hull', - group: true, - children: ['n4', 'n5'], - style: { - padding: 10 - } - }, - { - id: 'n1', - type: 'node-drag', - x: 50, - y: 50, - width: 30, - height: 30 - }, - { - id: 'n2', - type: 'node', - x: 200, - y: 20, - shape: NodeShape.rect, - width: 30, - height: 50 - }, - { - id: 'n3', - type: 'node', - shape: NodeShape.ellipse, - x: 150, - y: 100, - width: 50, - height: 30 - }, - { - id: 'n4', - type: 'node-path', - x: 300, - y: 250, - width: 30, - height: 30 - }, - { - id: 'n5', - type: 'node-polygon', - x: 350, - y: 370, - width: 65, - height: 65 - }, - { - id: 'n6', - type: 'node', - shape: NodeShape.rect, - x: 300, - y: 200, - width: 60, - height: 20 - } - ], - edges: [ - { - id: 'e1', - type: 'edge', - source: 'n1', - target: 'n2' - }, - { - id: 'e2', - type: 'edge', - source: 'n1', - target: 'n3' - }, - { - id: 'e3', - type: 'edge', - source: 'n1', - target: 'n4' - }, - { - id: 'e4', - type: 'edge', - source: 'n1', - target: 'n5' - }, - { - id: 'e5', - type: 'edge', - source: 'n1', - target: 'n6' - } - ] - }), - [] - ) - ); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Styles.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Styles.tsx deleted file mode 100644 index 1eb8031bb6e..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/Styles.tsx +++ /dev/null @@ -1,850 +0,0 @@ -import * as React from 'react'; -import { - BadgeLocation, - EdgeModel, - EdgeStyle, - EdgeTerminalType, - LabelPosition, - Model, - NodeModel, - NodeShape, - NodeStatus, - useComponentFactory, - useModel -} from '@patternfly/react-topology'; -import withTopologySetup from './utils/withTopologySetup'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import stylesComponentFactory from './components/stylesComponentFactory'; -import { logos } from './utils/logos'; -import { - AlternateTerminalTypes, - createBadgeNodes, - createGroupedGroupNodes, - createGroupNodes, - createNode, - createStatusNodeShapes, - createUnGroupedGroupNodes, - EDGE_ANIMATION_SPEED_COUNT, - EDGE_ANIMATION_SPEEDS, - EDGE_STYLE_COUNT, - EDGE_STYLES, - EDGE_TERMINAL_TYPES, - EDGE_TERMINAL_TYPES_COUNT, - RIGHT_LABEL_COLUMN_WIDTH, - STATUS_VALUES -} from './utils/styleUtils'; -import { DataTypes } from './components/StyleNode'; - -export const NodeStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes() - }), - [] - ) - ); - return null; -}); - -export const NodeHoverStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, '', undefined, true) - }), - [] - ) - ); - return null; -}); - -export const NodeSelectedStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, '', true) - }), - [] - ) - ); - return null; -}); - -export const NodeStatusDecoratorStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, '', undefined, undefined, LabelPosition.bottom, true, 'Tooltip Text') - }), - [] - ) - ); - return null; -}); - -export const NodeDecoratorStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes(); - const nodes2: NodeModel[] = createGroupNodes('2', 600); - - nodes.forEach(n => (n.data.showDecorators = true)); - nodes.forEach(n => (n.data.labelPosition = LabelPosition.bottom)); - nodes2.forEach(n => (n.data.showDecorators = true)); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [...nodes, ...nodes2] - }), - [nodes, nodes2] - ) - ); - return null; -}); - -export const NodeLabelStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, 'Node Title') - }), - [] - ) - ); - return null; -}); - -export const NodeLabelHoverStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, 'Node Title', undefined, true) - }), - [] - ) - ); - return null; -}); - -export const NodeLabelSelectedStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, 'Node Title', true) - }), - [] - ) - ); - return null; -}); - -export const NodeHorizontalLabelStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: createStatusNodeShapes(1, 'Node Title', undefined, undefined, LabelPosition.right) - }), - [] - ) - ); - return null; -}); - -export const NodeBadgedLabelStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - ...createBadgeNodes({ row: 1, badge: 'C' }), - ...createBadgeNodes({ row: 2, badge: 'CS', hover: true }), - ...createBadgeNodes({ row: 3, badge: 'CSN', selected: true }), - ...createBadgeNodes({ row: 4, badge: 'CSNY', badgeLocation: BadgeLocation.below }) - ] - }), - [] - ) - ); - return null; -}); - -export const NodeContextMenuLabelStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - ...createBadgeNodes({ row: 1, badge: 'C', showContextMenu: true }), - ...createBadgeNodes({ row: 2, badge: 'CS', hover: true, showContextMenu: true }), - ...createBadgeNodes({ row: 3, badge: 'CSN', selected: true, showContextMenu: true }) - ] - }), - [] - ) - ); - return null; -}); - -export const NodeIconLabelStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - useModel( - React.useMemo( - (): Model => ({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - ...createBadgeNodes({ - row: 1, - badge: 'C', - showContextMenu: true, - showIconClass: true, - marginX: 100 - }), - ...createBadgeNodes({ - row: 2, - badge: 'CS', - hover: true, - showContextMenu: true, - showIconClass: true, - marginX: 100 - }), - ...createBadgeNodes({ - row: 3, - badge: 'CSN', - selected: true, - showContextMenu: true, - showIconClass: true, - marginX: 100 - }) - ] - }), - [] - ) - ); - return null; -}); - -export const NodeSecondaryLabelStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes = Object.values(NodeShape).reduce((nodes: NodeModel[], shape: string | NodeShape, index) => { - nodes.push( - createNode({ - id: `${shape}-secondary`, - shape: shape as NodeShape, - label: 'Primary Label', - secondaryLabel: 'Secondary Label', - labelPosition: LabelPosition.bottom, - row: 1, - column: index + 1, - x: index * RIGHT_LABEL_COLUMN_WIDTH, - truncateLength: 13 - }) - ); - nodes.push( - createNode({ - id: `${shape}-secondary-long`, - shape: shape as NodeShape, - label: 'Primary Label', - secondaryLabel: 'Very Long Secondary Label', - labelPosition: LabelPosition.bottom, - row: 2, - column: index + 1, - x: index * RIGHT_LABEL_COLUMN_WIDTH, - y: 165, - truncateLength: 13 - }) - ); - nodes.push( - createNode({ - id: `${shape}-secondary-long-badged`, - label: 'Label Bottom', - secondaryLabel: 'Very Long Secondary Label', - shape: shape as NodeShape, - row: 3, - column: index + 1, - x: index * (RIGHT_LABEL_COLUMN_WIDTH + 45), - y: 330, - labelIconClass: logos.get('icon-java'), - truncateLength: 13, - badge: 'CS', - hover: true, - showContextMenu: true, - badgeColor: '#ace12e', - badgeTextColor: '#486b00', - badgeBorderColor: '#486b00', - marginX: 100 - }) - ); - return nodes; - }, []); - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes - }); - return null; -}); - -export const GroupStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes(); - - const groupNode = { - id: 'Group 1', - type: 'group', - label: 'Node Group Title', - children: nodes.map(n => n.id), - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - labelIconClass: logos.get('icon-java'), - collapsedWidth: 75, - collapsedHeight: 75, - showContextMenu: true - } - }; - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [...nodes, groupNode] - }); - return null; -}); - -export const GroupHoverStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes(); - - const groupNode = { - id: 'Group 1', - type: 'group', - label: 'Node Group Title', - children: nodes.map(n => n.id), - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - labelIconClass: logos.get('icon-java'), - collapsedWidth: 75, - collapsedHeight: 75, - hover: true - } - }; - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [...nodes, groupNode] - }); - return null; -}); - -export const GroupSelectedStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes(); - - const groupNode = { - id: 'Group 1', - type: 'group', - label: 'Node Group Title', - children: nodes.map(n => n.id), - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - labelIconClass: logos.get('icon-java'), - collapsedWidth: 75, - collapsedHeight: 75, - selected: true - } - }; - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [...nodes, groupNode] - }); - return null; -}); - -export const GroupDropTargetStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes(); - - const groupNode = { - id: 'Group 1', - type: 'group', - label: 'Node Group Title', - children: nodes.map(n => n.id), - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - labelIconClass: logos.get('icon-java'), - collapsedWidth: 75, - collapsedHeight: 75, - canDrop: true, - dropTarget: true - } - }; - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [...nodes, groupNode] - }); - return null; -}); - -export const GroupedGroupsStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const groupedGroupNodes: NodeModel[] = createGroupedGroupNodes('GroupedGroup'); - const ungroupedGroupNodes: NodeModel[] = createUnGroupedGroupNodes('Group 1'); - - const groupNode = { - id: 'Group 1', - type: 'group', - label: 'Node Group Title', - children: ['GroupedGroup', ...ungroupedGroupNodes.map(n => n.id)], - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - collapsedWidth: 75, - collapsedHeight: 75, - showContextMenu: true, - labelIconClass: logos.get('icon-java') - } - }; - - const groupedGroupNodes2: NodeModel[] = createGroupedGroupNodes('GroupedGroup2', 500); - const ungroupedGroupNodes2: NodeModel[] = createUnGroupedGroupNodes('Group 2', 500); - - const groupNode2 = { - id: 'Group 2', - type: 'group', - label: 'Node Group Title', - children: ['GroupedGroup2', ...ungroupedGroupNodes2.map(n => n.id)], - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - collapsedWidth: 75, - collapsedHeight: 75, - selected: true, - showContextMenu: true, - labelIconClass: logos.get('icon-jenkins') - } - }; - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [ - ...groupedGroupNodes, - ...ungroupedGroupNodes, - groupNode, - ...groupedGroupNodes2, - ...ungroupedGroupNodes2, - groupNode2 - ] - }); - return null; -}); - -export const CollapsibleGroupStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes('Group 1'); - const nodes2: NodeModel[] = createGroupNodes('Group 2', 600); - - const groupNode = { - id: 'Group 1', - type: 'group', - label: 'Node Group Title', - children: nodes.map(n => n.id), - group: true, - style: { padding: 17 }, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - labelIconClass: logos.get('icon-jenkins'), - collapsedWidth: 75, - collapsedHeight: 75, - showContextMenu: true, - collapsible: true - } - }; - - const groupNode2: NodeModel = { - id: 'Group 2', - type: 'group', - label: 'Node Group Title', - children: nodes2.map(n => n.id), - group: true, - style: { padding: 17 }, - collapsed: true, - data: { - badge: 'Label', - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - labelIconClass: logos.get('icon-java'), - collapsedWidth: 75, - collapsedHeight: 75, - showContextMenu: true, - collapsible: true - } - }; - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes: [...nodes, groupNode, ...nodes2, groupNode2] - }); - return null; -}); - -export const EdgeStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes('edges-group'); - const edges: EdgeModel[] = []; - - const middleNodeIndex = nodes.length - 1; - nodes.forEach((item, index) => { - if (index === middleNodeIndex) { - return; - } - const endIndex = index < nodes.length - 2 ? index + 1 : 0; - edges.push({ - id: `edge-${index}-${endIndex}`, - type: 'edge', - source: nodes[index].id, - target: nodes[endIndex].id, - edgeStyle: EDGE_STYLES[index % EDGE_STYLE_COUNT] - }); - edges.push({ - id: `edge-${middleNodeIndex}-${index}`, - type: 'edge', - source: nodes[middleNodeIndex].id, - target: nodes[index].id, - edgeStyle: EdgeStyle.default - }); - }); - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes, - edges - }); - return null; -}); - -export const EdgeAnimationStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes('animation-edges-group'); - const edges: EdgeModel[] = []; - - const middleNodeIndex = nodes.length - 1; - nodes.forEach((item, index) => { - if (index === middleNodeIndex) { - return; - } - const endIndex = index < nodes.length - 2 ? index + 1 : 0; - edges.push({ - id: `animation-edge-${index}-${endIndex}`, - type: 'edge', - source: nodes[index].id, - target: nodes[endIndex].id, - edgeStyle: EdgeStyle.dashedMd, - animationSpeed: EDGE_ANIMATION_SPEEDS[index % EDGE_ANIMATION_SPEED_COUNT] - }); - edges.push({ - id: `animation-edge-${middleNodeIndex}-${index}`, - type: 'edge', - source: nodes[middleNodeIndex].id, - target: nodes[index].id, - edgeStyle: EdgeStyle.default - }); - }); - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes, - edges - }); - return null; -}); - -export const EdgeTerminalStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = createGroupNodes('animation-edges-group'); - const edges: EdgeModel[] = []; - - const middleNodeIndex = nodes.length - 1; - nodes.forEach((item, index) => { - if (index === middleNodeIndex) { - return; - } - const endIndex = index < nodes.length - 2 ? index + 1 : 0; - const endTerminalType = EDGE_TERMINAL_TYPES[(index + 1) % EDGE_TERMINAL_TYPES_COUNT]; - const startTerminalType = AlternateTerminalTypes.includes(endTerminalType) - ? endTerminalType - : EdgeTerminalType.none; - edges.push({ - id: `animation-edge-${index}-${endIndex}`, - type: 'edge', - source: nodes[index].id, - target: nodes[endIndex].id, - edgeStyle: EdgeStyle.dashedMd, - animationSpeed: EDGE_ANIMATION_SPEEDS[index % EDGE_ANIMATION_SPEED_COUNT], - data: { startTerminalType, endTerminalType } - }); - edges.push({ - id: `animation-edge-${middleNodeIndex}-${index}`, - type: 'edge', - source: nodes[middleNodeIndex].id, - target: nodes[index].id, - edgeStyle: EdgeStyle.default, - data: { - startTerminalType: endTerminalType, - endTerminalType: EdgeTerminalType.directional - } - }); - }); - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes, - edges - }); - return null; -}); - -export const EdgeTerminalStatusStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = []; - const edges: EdgeModel[] = []; - - STATUS_VALUES.forEach((status, statusIndex) => { - if (status === NodeStatus.default) { - return; - } - EDGE_TERMINAL_TYPES.forEach((terminalType, typeIndex) => { - if (terminalType === EdgeTerminalType.none) { - return; - } - const n1 = createNode({ - id: `${terminalType}--${status}-1`, - shape: NodeShape.ellipse, - label: 'Node 1', - row: typeIndex, - column: statusIndex * 3 - 2 - }); - const n2 = createNode({ - id: `${terminalType}-${status}-1`, - shape: NodeShape.ellipse, - dataType: DataTypes.Alternate, - label: 'Node 1', - row: typeIndex, - column: statusIndex * 3 - }); - nodes.push(n1); - nodes.push(n2); - edges.push({ - id: `edge-${n1.id}-${n2.id}`, - type: 'edge', - source: n1.id, - target: n2.id, - edgeStyle: EdgeStyle.default, - data: { - startTerminalType: terminalType, - startTerminalStatus: STATUS_VALUES[statusIndex], - endTerminalType: terminalType, - endTerminalStatus: STATUS_VALUES[statusIndex] - } - }); - }); - }); - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes, - edges - }); - return null; -}); - -export const EdgeTerminalTagStyles = withTopologySetup(() => { - useComponentFactory(defaultComponentFactory); - useComponentFactory(stylesComponentFactory); - const nodes: NodeModel[] = []; - const edges: EdgeModel[] = []; - - STATUS_VALUES.forEach((status, statusIndex) => { - const n1 = createNode({ - id: `${status}-1`, - shape: NodeShape.ellipse, - label: 'Node 1', - row: statusIndex + 1, - column: 1 - }); - const n2 = createNode({ - id: `${status}-2`, - shape: NodeShape.ellipse, - dataType: DataTypes.Alternate, - label: 'Node 1', - row: statusIndex + 1, - column: 4 - }); - nodes.push(n1); - nodes.push(n2); - edges.push({ - id: `edge-${n1.id}-${n2.id}`, - type: 'edge', - source: n1.id, - target: n2.id, - edgeStyle: EdgeStyle.default, - data: { - endTerminalType: EdgeTerminalType.directional, - tag: '250 kbs', - tagStatus: status - } - }); - }); - - useModel({ - graph: { - id: 'g1', - type: 'graph' - }, - nodes, - edges - }); - return null; -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.css b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.css deleted file mode 100644 index 65d342ce014..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.css +++ /dev/null @@ -1,62 +0,0 @@ -.pf-ri__topology-demo { - height: 100%; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.pf-ri__topology-demo .pf-c-tab-content { - display: flex; - flex-direction: column; - flex-grow: 1; -} - -.pf-ri__topology-demo .pf-c-tab-content:focus { - outline: none; -} - -.pf-ri__topology-demo .pf-c-toolbar { - --pf-c-toolbar__expandable-content--lg--PaddingBottom: 0; - --pf-c-toolbar--PaddingBottom: 0; -} -.pf-ri__topology-demo .pf-c-toolbar__item .pf-l-flex { - --pf-l-flex--FlexWrap: no-wrap; -} -.pf-ri__topology-demo .pf-c-toolbar__item .pf-c-form-control { - width: 85px; -} -.pf-ri-topology-context-menu { - z-index: 1050; -} - -.pf-ri-topology-context-menu__kebab-wrapper.pf-c-dropdown__menu-item { - padding: 0; -} -.pf-ri__topology-demo__package-input { - width: 75px; -} - -.pf-ri-topology__node__background { - fill: var(--pf-global--palette--black-400); - stroke-width: 1px; - stroke: var(--pf-global--palette--black-1000); -} - -.pf-ri-topology__node__background.pf-m-selected { - fill: var(--pf-global--active-color--100); -} - -.pf-ri-topology__node__background.pf-m-hover { - fill: var(--pf-global--palette--green-300); -} - -.pf-ri-topology__node__background.pf-m-drop-target { - fill: var(--pf-global--palette--light-blue-200); -} - -.pf-c-page__main-section#\/topology-demo-page-section, .pf-c-page__main-section#\/topology-pipelines-demo-page-section { - --pf-c-page__main-section--PaddingTop: 0; - --pf-c-page__main-section--PaddingRight: 0; - --pf-c-page__main-section--PaddingLeft: 0; - --pf-c-page__main-section--PaddingBottom: 0; -} diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.tsx deleted file mode 100644 index 7da19d1e8b8..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyDemo.tsx +++ /dev/null @@ -1,287 +0,0 @@ -import React from 'react'; -import { Tab, Tabs, TabTitleText } from '@patternfly/react-core'; -import { Shapes } from './Shapes'; -import { SingleNode, SingleEdge, Group, GroupHull, MultiEdge, AutoSizeNode } from './Basics'; -import { ControlledSelection, MultiSelect, Performance, UncontrolledSelection } from './Selection'; -import { PanZoom } from './PanZoom'; -import { Cola, Dagre, Force } from './Layouts'; -import { Anchors, CreateConnector, Reconnect } from './Connectors'; -import { Dnd, DndShiftRegroup } from './DragDrop'; -import { ContextMenuOnNode, ControlledContextMenu, UncontrolledContextMenu } from './ContextMenus'; -import { Topology, WithResizableSideBar, WithSideBar } from './TopologyPackage'; -import { ComplexGroup } from './Groups'; -import { CollapsibleGroups } from './CollapsibleGroups'; -import { - NodeHoverStyles, - NodeLabelHoverStyles, - NodeLabelSelectedStyles, - NodeLabelStyles, - NodeHorizontalLabelStyles, - NodeSelectedStyles, - NodeStyles, - NodeBadgedLabelStyles, - NodeContextMenuLabelStyles, - NodeIconLabelStyles, - NodeStatusDecoratorStyles, - NodeDecoratorStyles, - NodeSecondaryLabelStyles, - GroupStyles, - GroupSelectedStyles, - GroupHoverStyles, - GroupDropTargetStyles, - GroupedGroupsStyles, - CollapsibleGroupStyles, - EdgeStyles, - EdgeAnimationStyles, - EdgeTerminalStyles, - EdgeTerminalStatusStyles, - EdgeTerminalTagStyles -} from './Styles'; - -import './TopologyDemo.css'; - -const BASIC = 0; -const STYLES = 1; -const SELECTION = 2; -const PAN_ZOOM = 3; -const LAYOUT = 4; -const CONNECTOR = 5; -const DRAG_AND_DROP = 6; -const SHAPES = 7; -const CONTEXT_MENU = 8; -const TOPOLOGY_PACKAGE = 9; -const COMPLEX_GROUP = 10; -const COLLAPSIBLE_GROUPS = 11; - -export const TopologyDemo: React.FunctionComponent = () => { - const [activeKey, setActiveKey] = React.useState(STYLES); - const [activeSecondaryKey, setActiveSecondaryKey] = React.useState(0); - const [activeTertiaryKey, setActiveTertiaryKey] = React.useState(0); - - const handleTabClick = (_event: React.MouseEvent, tabIndex: number) => { - setActiveKey(tabIndex); - setActiveSecondaryKey(0); - setActiveTertiaryKey(0); - }; - - const handleSecondaryTabClick = (_event: React.MouseEvent, tabIndex: number) => { - setActiveSecondaryKey(tabIndex); - setActiveTertiaryKey(0); - }; - - const handleTertiaryTabClick = (_event: React.MouseEvent, tabIndex: number) => { - setActiveTertiaryKey(tabIndex); - }; - - return ( -
- - Basic}> - - Single Node}> - - - Single Edge}> - - - Multi Edge}> - - - Group}> - - - Group Hull}> - - - Auto Size Node}> - - - - - Styles}> - - Nodes}> - - Nodes}> - - - Hover Nodes}> - - - Selected Nodes}> - - - Status Decorators}> - - - Decorators}> - - - - - Labels}> - - Node Labels}> - - - Hover Labels}> - - - Selected Labels}> - - - Horizontal Labels}> - - - Badged Labels}> - - - Context Menu Labels}> - - - Icon Labels}> - - - Secondary Labels}> - - - - - Groups}> - - Group}> - - - Hover Group}> - - - Selected Group}> - - - Drop Target Group}> - - - Grouped Groups}> - - - Collapsible Groups}> - - - - - Edges}> - - Edge Styles}> - - - Animated Edges}> - - - Edge Terminal Types}> - - - Edge Terminal Status}> - - - Edge Terminal Tags}> - - - - - - - Selection}> - - Uncontrolled}> - - - Controlled}> - - - Multi Select}> - - - Performance}> - - - - - Pan Zoom}> - - - Layout}> - - Force}> - - - Dagre}> - - - Cola}> - - - - - Connector}> - - Reconnect}> - - - Create Connector}> - - - Anchors}> - - - - - Drag and Drop}> - - Dnd}> - - - Dnd Shift Regroup}> - - - - - Shapes}> - - - Context Menu}> - - Controlled Context Menu}> - - - Uncontrolled Context Menu}> - - - Context Menu on Node}> - - - - - Topology Package}> - - Topology}> - - - With Side Bar}> - - - With Resizeable Side Bar}> - - - - - Complex Group}> - - - Collapsible Groups}> - - - -
- ); -}; -TopologyDemo.displayName = 'TopologyDemo'; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPackage.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPackage.tsx deleted file mode 100644 index fd73ef14fa0..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPackage.tsx +++ /dev/null @@ -1,192 +0,0 @@ -import * as React from 'react'; -import { action } from 'mobx'; -import * as _ from 'lodash'; -import { - createTopologyControlButtons, - defaultControlButtonsOptions, - EdgeModel, - NodeModel, - SELECTION_EVENT, - SelectionEventListener, - TopologyControlBar, - TopologySideBar, - TopologyView, - useEventListener, - useVisualizationController, - Visualization, - VisualizationProvider, - VisualizationSurface -} from '@patternfly/react-topology'; -import stylesComponentFactory from './components/stylesComponentFactory'; -import defaultLayoutFactory from './layouts/defaultLayoutFactory'; -import defaultComponentFactory from './components/defaultComponentFactory'; -import { generateDataModel, generateEdge, generateNode } from './data/generator'; -import { useTopologyOptions } from './useTopologyOptions'; - -interface TopologyViewComponentProps { - useSidebar: boolean; - sideBarResizable?: boolean; -} - -const TopologyViewComponent: React.FunctionComponent = ({ - useSidebar, - sideBarResizable = false -}) => { - const [selectedIds, setSelectedIds] = React.useState([]); - const controller = useVisualizationController(); - - const { - layout, - nodeOptions, - edgeOptions, - nestedLevel, - creationCounts, - medScale, - lowScale, - contextToolbar, - viewToolbar - } = useTopologyOptions(controller); - - React.useEffect(() => { - const dataModel = generateDataModel( - creationCounts.numNodes, - creationCounts.numGroups, - creationCounts.numEdges, - nestedLevel, - nodeOptions, - edgeOptions - ); - - const model = { - graph: { - id: 'g1', - type: 'graph', - layout - }, - ...dataModel - }; - - controller.fromModel(model, false); - // Don't update on option changes, its handled differently to not re-layout - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [creationCounts, layout]); - - useEventListener(SELECTION_EVENT, ids => { - setSelectedIds(ids); - }); - - React.useEffect(() => { - controller.getGraph().setDetailsLevelThresholds({ - low: lowScale, - medium: medScale - }); - }, [controller, lowScale, medScale]); - - const topologySideBar = ( - 0} resizable={sideBarResizable} onClose={() => setSelectedIds([])}> -
{_.head(selectedIds)}
-
- ); - - React.useEffect(() => { - const currentModel = controller.toModel(); - const nodes = currentModel.nodes; - if (nodes.length) { - const updatedNodes: NodeModel[] = nodes.map((node, index) => { - if (node.group) { - return node; - } - return { - ...node, - ...generateNode(index, nodeOptions) - }; - }); - controller.fromModel({ nodes: updatedNodes, edges: currentModel.edges }); - } - // Don't update on controller change - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [nodeOptions]); - - React.useEffect(() => { - const currentModel = controller.toModel(); - const edges = currentModel.edges; - if (edges.length) { - const updatedEdges: EdgeModel[] = edges.map((edge, index) => ({ - ...edge, - ...generateEdge(index, edge.source, edge.target, edgeOptions) - })); - controller.fromModel({ edges: updatedEdges, nodes: currentModel.nodes }); - } - }, [edgeOptions, controller]); - - return ( - { - controller.getGraph().scaleBy(4 / 3); - }), - zoomOutCallback: action(() => { - controller.getGraph().scaleBy(0.75); - }), - fitToScreenCallback: action(() => { - controller.getGraph().fit(80); - }), - resetViewCallback: action(() => { - controller.getGraph().reset(); - controller.getGraph().layout(); - }), - legend: false - })} - /> - } - contextToolbar={contextToolbar} - viewToolbar={viewToolbar} - sideBar={useSidebar && topologySideBar} - sideBarOpen={useSidebar && _.size(selectedIds) > 0} - sideBarResizable={sideBarResizable} - > - - - ); -}; - -export const Topology = React.memo(() => { - const controller = new Visualization(); - controller.registerLayoutFactory(defaultLayoutFactory); - controller.registerComponentFactory(defaultComponentFactory); - controller.registerComponentFactory(stylesComponentFactory); - - return ( - - - - ); -}); - -export const WithSideBar = React.memo(() => { - const controller = new Visualization(); - controller.registerLayoutFactory(defaultLayoutFactory); - controller.registerComponentFactory(defaultComponentFactory); - controller.registerComponentFactory(stylesComponentFactory); - - return ( - - - - ); -}); - -export const WithResizableSideBar = React.memo(() => { - const controller = new Visualization(); - controller.registerLayoutFactory(defaultLayoutFactory); - controller.registerComponentFactory(defaultComponentFactory); - controller.registerComponentFactory(stylesComponentFactory); - return ( - - - - ); -}); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPipelineDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPipelineDemo.tsx deleted file mode 100644 index 897025812a0..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/TopologyPipelineDemo.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { Tab, Tabs, TabTitleText } from '@patternfly/react-core'; -import { TASKS_TITLE, TopologyPipelineTasks } from './PipelineTasks'; -import { LAYOUT_TITLE, PipelineLayout } from './PipelineLayout'; - -import './TopologyDemo.css'; - -const TASKS = 0; -const LAYOUT = 1; - -export const TopologyPipelineDemo: React.FunctionComponent = () => { - const [activeKey, setActiveKey] = React.useState(TASKS); - - const handleTabClick = (_event: React.MouseEvent, tabIndex: number) => { - setActiveKey(tabIndex); - }; - - return ( -
- - {TASKS_TITLE}}> - - - {LAYOUT_TITLE}}> - - - -
- ); -}; -TopologyPipelineDemo.displayName = 'TopologyPipelineDemo'; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomCircleNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomCircleNode.tsx deleted file mode 100644 index 50818e265d1..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomCircleNode.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - WithCreateConnectorProps, - Dimensions, - Node, - WithContextMenuProps, - WithDragNodeProps, - WithSelectionProps, - WithDndDragProps, - WithDndDropProps, - ShapeProps, - useAnchor, - EllipseAnchor, - action -} from '@patternfly/react-topology'; -import DemoDefaultNode from './DemoDefaultNode'; - -type CustomCircleNodeProps = { - element: Node; - droppable?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps & - WithCreateConnectorProps & - WithContextMenuProps; - -const CustomCircle: React.FunctionComponent = ({ element, className }) => { - useAnchor(EllipseAnchor); - React.useEffect(() => { - // init height - action(() => element.setDimensions(new Dimensions(40, 40)))(); - }, [element]); - const r = element.getDimensions().width / 2; - return ( - { - const size = element.getDimensions().width === 40 ? 80 : 40; - action(() => element.setDimensions(new Dimensions(size, size)))(); - }} - /> - ); -}; - -const CustomCircleNode: React.FunctionComponent = props => ( - CustomCircle} {...props} /> -); - -export default observer(CustomCircleNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPathNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPathNode.tsx deleted file mode 100644 index a29facce9d8..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPathNode.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - WithCreateConnectorProps, - Node, - WithContextMenuProps, - WithDragNodeProps, - WithSelectionProps, - WithDndDragProps, - WithDndDropProps -} from '@patternfly/react-topology'; -import Path from './shapes/Path'; -import DemoDefaultNode from './DemoDefaultNode'; - -type CustomPathNodeProps = { - element: Node; - droppable?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps & - WithCreateConnectorProps & - WithContextMenuProps; - -const CustomPathNode: React.FunctionComponent = props => ( - Path} {...props} /> -); - -export default observer(CustomPathNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPolygonNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPolygonNode.tsx deleted file mode 100644 index faaea99116a..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomPolygonNode.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - WithCreateConnectorProps, - Node, - WithContextMenuProps, - WithDragNodeProps, - WithSelectionProps, - WithDndDragProps, - WithDndDropProps -} from '@patternfly/react-topology'; -import Polygon from './shapes/Polygon'; -import DemoDefaultNode from './DemoDefaultNode'; - -type CustomPolygonNodeProps = { - element: Node; - droppable?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps & - WithCreateConnectorProps & - WithContextMenuProps; - -const CustomPolygonNode: React.FunctionComponent = props => ( - Polygon} {...props} /> -); - -export default observer(CustomPolygonNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomRectNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomRectNode.tsx deleted file mode 100644 index b5b716b8610..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/CustomRectNode.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - WithCreateConnectorProps, - Node, - WithContextMenuProps, - WithDragNodeProps, - WithSelectionProps, - WithDndDragProps, - WithDndDropProps, - ShapeProps, - useAnchor, - RectAnchor -} from '@patternfly/react-topology'; -import DemoDefaultNode from './DemoDefaultNode'; - -type CustomRectNodeProps = { - element: Node; - droppable?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps & - WithCreateConnectorProps & - WithContextMenuProps; - -const CustomRect: React.FunctionComponent = observer(({ className }) => { - useAnchor(RectAnchor); - return ; -}); - -const CustomRectNode: React.FunctionComponent = props => ( - CustomRect} {...props} /> -); - -export default observer(CustomRectNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultEdge.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultEdge.tsx deleted file mode 100644 index 41373175c94..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultEdge.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - Edge, - EdgeConnectorArrow, - EdgeTerminalType, - Layer, - Point, - useBendpoint, - WithRemoveConnectorProps, - WithSourceDragProps, - WithTargetDragProps -} from '@patternfly/react-topology'; - -type EdgeProps = { - element: Edge; - dragging?: boolean; -} & WithSourceDragProps & - WithTargetDragProps & - WithRemoveConnectorProps; - -interface BendpointProps { - point: Point; -} - -const Bendpoint: React.FunctionComponent = observer(({ point }) => { - const [hover, setHover] = React.useState(false); - const [, ref] = useBendpoint(point); - return ( - setHover(true)} - onMouseOut={() => setHover(false)} - /> - ); -}); - -const DefaultEdge: React.FunctionComponent = ({ - element, - sourceDragRef, - targetDragRef, - dragging, - onShowRemoveConnector, - onHideRemoveConnector -}) => { - const startPoint = element.getStartPoint(); - const endPoint = element.getEndPoint(); - const bendpoints = element.getBendpoints(); - const d = `M${startPoint.x} ${startPoint.y} ${bendpoints.map((b: Point) => `L${b.x} ${b.y} `).join('')}L${ - endPoint.x - } ${endPoint.y}`; - - return ( - <> - - - {sourceDragRef && } - - - {bendpoints && bendpoints.map((p, i) => )} - - ); -}; - -export default observer(DefaultEdge); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultGroup.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultGroup.tsx deleted file mode 100644 index b85976b4745..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DefaultGroup.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - useCombineRefs, - WithDragNodeProps, - WithSelectionProps, - Node, - Rect, - Layer, - WithDndDropProps, - WithDndDragProps, - useAnchor, - RectAnchor -} from '@patternfly/react-topology'; - -type GroupProps = { - children?: React.ReactNode; - element: Node; - droppable?: boolean; - hover?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps; - -const DefaultGroup: React.FunctionComponent = ({ - element, - children, - selected, - onSelect, - dragNodeRef, - dndDragRef, - dndDropRef, - droppable, - hover, - canDrop -}) => { - useAnchor(RectAnchor); - const boxRef = React.useRef(null); - const refs = useCombineRefs(dragNodeRef, dndDragRef, dndDropRef); - - if (!droppable || !boxRef.current) { - // change the box only when not dragging - boxRef.current = element.getBounds(); - } - let fill = '#ededed'; - if (canDrop && hover) { - fill = 'lightgreen'; - } else if (canDrop && droppable) { - fill = 'lightblue'; - } else if (element.getData()) { - fill = element.getData().background; - } - - if (element.isCollapsed()) { - const { width, height } = element.getDimensions(); - return ( - - - - ); - } - - return ( - - - {children} - - ); -}; - -export default observer(DefaultGroup); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoDefaultNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoDefaultNode.tsx deleted file mode 100644 index 56d54731f45..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoDefaultNode.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import * as React from 'react'; -import classNames from 'classnames'; -import { observer } from 'mobx-react'; -import { - WithCreateConnectorProps, - Node, - WithContextMenuProps, - WithDragNodeProps, - WithSelectionProps, - WithDndDragProps, - WithDndDropProps, - useCombineRefs, - useHover, - getShapeComponent, - ShapeProps -} from '@patternfly/react-topology'; - -type DemoDefaultNodeProps = { - element: Node; - droppable?: boolean; - canDrop?: boolean; - getCustomShape?: (node: Node) => React.FunctionComponent; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps & - WithCreateConnectorProps & - WithContextMenuProps; - -const DemoDefaultNode: React.FunctionComponent = ({ - element, - selected, - onSelect, - dragNodeRef, - dndDragRef, - canDrop, - dndDropRef, - getCustomShape, - onHideCreateConnector, - onShowCreateConnector, - onContextMenu -}) => { - const [hover, hoverRef] = useHover(); - const refs = useCombineRefs(hoverRef, dragNodeRef, dndDragRef); - const { width, height } = element.getDimensions(); - - const className = classNames('pf-ri-topology__node__background', { - 'pf-m-hover': canDrop && hover, - 'pf-m-selected': selected - }); - const ShapeComponent = (getCustomShape && getCustomShape(element)) || getShapeComponent(element); - - React.useEffect(() => { - if (hover) { - onShowCreateConnector && onShowCreateConnector(); - } else { - onHideCreateConnector && onHideCreateConnector(); - } - }, [hover, onShowCreateConnector, onHideCreateConnector]); - - return ( - - - - ); -}; - -export default observer(DemoDefaultNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoFinallyNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoFinallyNode.tsx deleted file mode 100644 index 38edf32c57a..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoFinallyNode.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - DEFAULT_LAYER, - FinallyNode, - Layer, - Node, - ScaleDetailsLevel, - TOP_LAYER, - useDetailsLevel, - useHover, - WithContextMenuProps, - WithSelectionProps -} from '@patternfly/react-topology'; - -type DemoFinallyNodeProps = { - element: Node; -} & WithContextMenuProps & - WithSelectionProps; - -const DemoFinallyNode: React.FunctionComponent = ({ ...props }) => { - const [hover, hoverRef] = useHover(); - const detailsLevel = useDetailsLevel(); - - return ( - - - - - - ); -}; - -export default observer(DemoFinallyNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskGroupEdge.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskGroupEdge.tsx deleted file mode 100644 index 680ae07955f..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskGroupEdge.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { Edge, TaskEdge } from '@patternfly/react-topology'; - -export const GROUPED_PIPELINE_NODE_SEPARATION_HORIZONTAL = 200; - -interface DemoTaskEdgeProps { - element: Edge; -} - -const DemoTaskGroupEdge: React.FunctionComponent = props => ( - -); - -export default observer(DemoTaskGroupEdge); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskNode.tsx deleted file mode 100644 index dd3e6dd863c..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/DemoTaskNode.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - DEFAULT_LAYER, - DEFAULT_WHEN_OFFSET, - Layer, - Node, - ScaleDetailsLevel, - TaskNode, - TOP_LAYER, - useDetailsLevel, - useHover, - WhenDecorator, - WithContextMenuProps, - WithSelectionProps -} from '@patternfly/react-topology'; -import { PopoverProps } from '@patternfly/react-core'; - -type DemoTaskNodeProps = { - element: Node; -} & WithContextMenuProps & - WithSelectionProps; - -const DEMO_TIP_TEXT = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.'; - -const DemoTaskNode: React.FunctionComponent = ({ - element, - onContextMenu, - contextMenuOpen, - ...rest -}) => { - const data = element.getData(); - const [hover, hoverRef] = useHover(); - const detailsLevel = useDetailsLevel(); - - const passedData = React.useMemo(() => { - const newData = { ...data }; - Object.keys(newData).forEach(key => { - if (newData[key] === undefined) { - delete newData[key]; - } - }); - return newData; - }, [data]); - - const hasTaskIcon = !!(data.taskIconClass || data.taskIcon); - const whenDecorator = data.whenStatus ? ( - - ) : null; - - // Set the badgePopoverParams, but if the node has badgeTooltips, this will be ignored - const badgePopoverParams: PopoverProps = { - headerContent: 'Popover header', - bodyContent: DEMO_TIP_TEXT, - footerContent: 'Popover footer' - }; - - return ( - - - {whenDecorator} - - - ); -}; - -export default observer(DemoTaskNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/GroupHull.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/GroupHull.tsx deleted file mode 100644 index 062549058f0..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/GroupHull.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { polygonHull } from 'd3-polygon'; -import * as _ from 'lodash'; -import { - WithDragNodeProps, - WithSelectionProps, - Layer, - Node, - PointTuple, - NodeStyle, - NodeShape, - WithDndDragProps, - WithDndDropProps, - useCombineRefs, - maxPadding, - hullPath, - useAnchor, - RectAnchor -} from '@patternfly/react-topology'; - -type GroupHullProps = { - children?: React.ReactNode; - element: Node; - droppable?: boolean; - hover?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps; - -type PointWithSize = PointTuple | [number, number, number]; - -const GroupHull: React.FunctionComponent = ({ - element, - children, - selected, - onSelect, - dragNodeRef, - dndDragRef, - dndDropRef, - hover, - droppable, - canDrop -}) => { - const pathRef = React.useRef(null); - const refs = useCombineRefs(dragNodeRef, dndDragRef, dndDropRef); - useAnchor(RectAnchor); - - let fill = '#ededed'; - if (canDrop && hover) { - fill = 'lightgreen'; - } else if (canDrop && droppable) { - fill = 'lightblue'; - } else if (element.getData()) { - fill = element.getData().background; - } - - if (element.isCollapsed()) { - const { width, height } = element.getBounds(); - return ( - - - - ); - } - - if (!droppable || !pathRef.current) { - const nodeChildren = element.getNodes(); - if (nodeChildren.length === 0) { - return null; - } - const points: PointWithSize[] = []; - _.forEach(nodeChildren, c => { - if (c.getNodeShape() === NodeShape.ellipse) { - const { width, height } = c.getBounds(); - const { x, y } = c.getBounds().getCenter(); - const radius = Math.max(width, height) / 2; - points.push([x, y, radius] as PointWithSize); - } else { - // add all 4 corners - const { width, height, x, y } = c.getBounds(); - points.push([x, y, 0] as PointWithSize); - points.push([x + width, y, 0] as PointWithSize); - points.push([x, y + height, 0] as PointWithSize); - points.push([x + width, y + height, 0] as PointWithSize); - } - }); - const hullPoints: PointTuple[] | null = - points.length > 2 ? polygonHull(points as PointTuple[]) : (points as PointTuple[]); - if (!hullPoints) { - return null; - } - // cast to number and coerce - const padding = maxPadding(element.getStyle().padding); - const hullPadding = (point: PointWithSize) => (point[2] || 0) + padding; - // change the box only when not dragging - pathRef.current = hullPath(hullPoints, hullPadding); - } - - return ( - - - {children} - - ); -}; - -export default observer(GroupHull); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/MultiEdge.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/MultiEdge.tsx deleted file mode 100644 index 0f1ab8b5ec7..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/MultiEdge.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { Edge, vecSum, vecScale, unitNormal } from '@patternfly/react-topology'; - -interface MultiEdgeProps { - element: Edge; - dragging?: boolean; -} - -// TODO create utiles to support this -const MultiEdge: React.FunctionComponent = ({ element }) => { - let idx = 0; - let sum = 0; - element - .getGraph() - .getEdges() - .forEach(e => { - if (e === element) { - idx = sum; - sum++; - } else if (e.getSource() === element.getSource() && e.getTarget() === element.getTarget()) { - sum++; - } - }); - let d: string; - const startPoint = element.getStartPoint(); - const endPoint = element.getEndPoint(); - if (idx === sum - 1 && sum % 2 === 1) { - d = `M${startPoint.x} ${startPoint.y} L${endPoint.x} ${endPoint.y}`; - } else { - const pm = vecSum( - [startPoint.x + (endPoint.x - startPoint.x) / 2, startPoint.y + (endPoint.y - startPoint.y) / 2], - vecScale( - (idx % 2 === 1 ? 25 : -25) * Math.ceil((idx + 1) / 2), - unitNormal([startPoint.x, startPoint.y], [endPoint.x, endPoint.y]) - ) - ); - d = `M${startPoint.x} ${startPoint.y} Q${pm[0]} ${pm[1]} ${endPoint.x} ${endPoint.y}`; - } - - return ; -}; - -export default observer(MultiEdge) as React.FunctionComponent; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/NodeRect.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/NodeRect.tsx deleted file mode 100644 index a1d1808a11f..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/NodeRect.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { - Node, - useSvgAnchor, - WithDragNodeProps, - WithSelectionProps, - WithDndDragProps, - WithDndDropProps, - useCombineRefs -} from '@patternfly/react-topology'; - -type NodeRectProps = { - element: Node; - droppable?: boolean; - hover?: boolean; - canDrop?: boolean; -} & WithSelectionProps & - WithDragNodeProps & - WithDndDragProps & - WithDndDropProps; - -const NodeRect: React.FunctionComponent = ({ - element, - selected, - onSelect, - dragNodeRef, - dndDragRef, - droppable, - hover, - canDrop, - dndDropRef -}) => { - const anchorRef = useSvgAnchor(); - const refs = useCombineRefs(dragNodeRef, dndDragRef, dndDropRef, anchorRef); - const { width, height } = element.getDimensions(); - - let fill = 'lightgrey'; - if (canDrop && hover) { - fill = 'lightgreen'; - } else if (canDrop && droppable) { - fill = 'lightblue'; - } else if (selected) { - fill = 'blue'; - } - - return ( - - ); -}; - -export default observer(NodeRect); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleEdge.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleEdge.tsx deleted file mode 100644 index b70d5b2292c..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleEdge.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { DefaultEdge, Edge, WithContextMenuProps, WithSelectionProps } from '@patternfly/react-topology'; - -type StyleEdgeProps = { - element: Edge; -} & WithContextMenuProps & - WithSelectionProps; - -const StyleEdge: React.FunctionComponent = ({ element, onContextMenu, contextMenuOpen, ...rest }) => { - const data = element.getData(); - - const passedData = React.useMemo(() => { - const newData = { ...data }; - Object.keys(newData).forEach(key => { - if (newData[key] === undefined) { - delete newData[key]; - } - }); - return newData; - }, [data]); - - return ( - - ); -}; - -export default observer(StyleEdge); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleGroup.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleGroup.tsx deleted file mode 100644 index 1ffa4e3e6d4..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleGroup.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import * as React from 'react'; -import { - DefaultGroup, - Node, - observer, - ScaleDetailsLevel, - ShapeProps, - WithContextMenuProps, - WithDragNodeProps, - WithSelectionProps -} from '@patternfly/react-topology'; -import AlternateIcon from '@patternfly/react-icons/dist/esm/icons/regions-icon'; -import DefaultIcon from '@patternfly/react-icons/dist/esm/icons/builder-image-icon'; -import useDetailsLevel from '@patternfly/react-topology/dist/esm/hooks/useDetailsLevel'; - -const ICON_PADDING = 20; - -export enum DataTypes { - Default, - Alternate -} - -type StyleGroupProps = { - element: Node; - collapsible: boolean; - collapsedWidth?: number; - collapsedHeight?: number; - onCollapseChange?: (group: Node, collapsed: boolean) => void; - getCollapsedShape?: (node: Node) => React.FunctionComponent; - collapsedShadowOffset?: number; // defaults to 10 -} & WithContextMenuProps & - WithDragNodeProps & - WithSelectionProps; - -const StyleGroup: React.FunctionComponent = ({ - element, - onContextMenu, - contextMenuOpen, - collapsedWidth = 75, - collapsedHeight = 75, - ...rest -}) => { - const data = element.getData(); - const detailsLevel = useDetailsLevel(); - - const getTypeIcon = (dataType?: DataTypes): any => { - switch (dataType) { - case DataTypes.Alternate: - return AlternateIcon; - default: - return DefaultIcon; - } - }; - - const renderIcon = (): React.ReactNode => { - const iconSize = Math.min(collapsedWidth, collapsedHeight) - ICON_PADDING * 2; - const Component = getTypeIcon(data.dataType); - - return ( - - - - ); - }; - - const passedData = React.useMemo(() => { - const newData = { ...data }; - Object.keys(newData).forEach(key => { - if (newData[key] === undefined) { - delete newData[key]; - } - }); - return newData; - }, [data]); - - return ( - - {element.isCollapsed() ? renderIcon() : null} - - ); -}; - -export default observer(StyleGroup); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleNode.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleNode.tsx deleted file mode 100644 index a63dc813e2c..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/StyleNode.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import * as React from 'react'; -import { - Decorator, - DEFAULT_DECORATOR_RADIUS, - DEFAULT_LAYER, - DefaultNode, - getDefaultShapeDecoratorCenter, - Layer, - Node, - NodeShape, - NodeStatus, - observer, - ScaleDetailsLevel, - ShapeProps, - TOP_LAYER, - TopologyQuadrant, - useHover, - WithContextMenuProps, - WithCreateConnectorProps, - WithDragNodeProps, - WithSelectionProps -} from '@patternfly/react-topology'; -import DefaultIcon from '@patternfly/react-icons/dist/esm/icons/builder-image-icon'; -import AlternateIcon from '@patternfly/react-icons/dist/esm/icons/regions-icon'; -import FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-icon'; -import BlueprintIcon from '@patternfly/react-icons/dist/esm/icons/blueprint-icon'; -import PauseCircle from '@patternfly/react-icons/dist/esm/icons/pause-circle-icon'; -import Thumbtack from '@patternfly/react-icons/dist/esm/icons/thumbtack-icon'; -import useDetailsLevel from '@patternfly/react-topology/dist/esm/hooks/useDetailsLevel'; -import { SVGIconProps } from '@patternfly/react-icons/dist/esm/createIcon'; - -export enum DataTypes { - Default, - Alternate -} -const ICON_PADDING = 20; - -type StyleNodeProps = { - element: Node; - getCustomShape?: (node: Node) => React.FunctionComponent; - getShapeDecoratorCenter?: (quadrant: TopologyQuadrant, node: Node) => { x: number; y: number }; - showLabel?: boolean; // Defaults to true - labelIcon?: React.ComponentClass; - showStatusDecorator?: boolean; // Defaults to false - regrouping?: boolean; - dragging?: boolean; -} & WithContextMenuProps & - WithCreateConnectorProps & - WithDragNodeProps & - WithSelectionProps; - -const getTypeIcon = (dataType?: DataTypes): any => { - switch (dataType) { - case DataTypes.Alternate: - return AlternateIcon; - default: - return DefaultIcon; - } -}; - -const renderIcon = (data: { dataType?: DataTypes }, element: Node): React.ReactNode => { - const { width, height } = element.getDimensions(); - const shape = element.getNodeShape(); - const iconSize = - (shape === NodeShape.trapezoid ? width : Math.min(width, height)) - - (shape === NodeShape.stadium ? 5 : ICON_PADDING) * 2; - const Component = getTypeIcon(data.dataType); - - return ( - - - - ); -}; - -const renderDecorator = ( - element: Node, - quadrant: TopologyQuadrant, - icon: React.ReactNode, - getShapeDecoratorCenter?: ( - quadrant: TopologyQuadrant, - node: Node, - radius?: number - ) => { - x: number; - y: number; - } -): React.ReactNode => { - const { x, y } = getShapeDecoratorCenter - ? getShapeDecoratorCenter(quadrant, element) - : getDefaultShapeDecoratorCenter(quadrant, element); - - return ; -}; - -const renderDecorators = ( - element: Node, - data: { showDecorators?: boolean }, - getShapeDecoratorCenter?: ( - quadrant: TopologyQuadrant, - node: Node - ) => { - x: number; - y: number; - } -): React.ReactNode => { - if (!data.showDecorators) { - return null; - } - const nodeStatus = element.getNodeStatus(); - return ( - <> - {!nodeStatus || nodeStatus === NodeStatus.default - ? renderDecorator(element, TopologyQuadrant.upperLeft, , getShapeDecoratorCenter) - : null} - {renderDecorator(element, TopologyQuadrant.upperRight, , getShapeDecoratorCenter)} - {renderDecorator(element, TopologyQuadrant.lowerLeft, , getShapeDecoratorCenter)} - {renderDecorator(element, TopologyQuadrant.lowerRight, , getShapeDecoratorCenter)} - - ); -}; - -const StyleNode: React.FunctionComponent = ({ - element, - onContextMenu, - contextMenuOpen, - showLabel, - dragging, - regrouping, - onShowCreateConnector, - onHideCreateConnector, - ...rest -}) => { - const data = element.getData(); - const detailsLevel = useDetailsLevel(); - const [hover, hoverRef] = useHover(); - - const passedData = React.useMemo(() => { - const newData = { ...data }; - Object.keys(newData).forEach(key => { - if (newData[key] === undefined) { - delete newData[key]; - } - }); - return newData; - }, [data]); - - React.useEffect(() => { - if (detailsLevel === ScaleDetailsLevel.low) { - onHideCreateConnector && onHideCreateConnector(); - } - }, [detailsLevel, onHideCreateConnector]); - - const LabelIcon = passedData.labelIcon; - return ( - - - } - attachments={ - (hover || detailsLevel === ScaleDetailsLevel.high) && - renderDecorators(element, passedData, rest.getShapeDecoratorCenter) - } - > - {(hover || detailsLevel !== ScaleDetailsLevel.low) && renderIcon(passedData, element)} - - - - ); -}; - -export default observer(StyleNode); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/actionsComponentFactory.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/actionsComponentFactory.tsx deleted file mode 100644 index 645f62f5a51..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/actionsComponentFactory.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import * as React from 'react'; -import { - GraphElement, - ComponentFactory, - withContextMenu, - ContextMenuSeparator, - ContextMenuItem, - withDragNode, - withSelection, - ModelKind, - NodeComponentProps, - DefaultNode, - withPanZoom, - GraphComponent, - ContextSubMenuItem, - withDndDrop, - nodeDropTargetSpec, - nodeDragSourceSpec -} from '@patternfly/react-topology'; -import GroupHull from './GroupHull'; -import CustomPathNode from './CustomPathNode'; - -const contextMenuItem = (label: string, i: number): React.ReactElement => { - if (label === '-') { - return ; - } - if (label.includes('->')) { - const parent = label.slice(0, label.indexOf('->')); - const children = label.slice(label.indexOf('->') + 2).split(','); - - return ( - - {children.map((child, j) => contextMenuItem(child.trim(), j))} - - ); - } - return ( - // eslint-disable-next-line no-alert - alert(`Selected: ${label}`)}> - {label} - - ); -}; - -const createContextMenuItems = (...labels: string[]): React.ReactElement[] => labels.map(contextMenuItem); - -const defaultMenu = createContextMenuItems( - 'First', - 'Second', - 'Third', - '-', - 'Fourth', - 'Sub Menu-> Child1, Child2, Child3, -, Child4' -); - -const actionsComponentFactory: ComponentFactory = ( - kind: ModelKind, - type: string -): React.ComponentType<{ element: GraphElement }> | undefined => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - if (type === 'group') { - return withDragNode({ canCancel: false })(GroupHull); - } - if (type === 'default-node' || type === 'node') { - return withDndDrop( - nodeDropTargetSpec() - )(withDragNode(nodeDragSourceSpec(type))(withSelection()(withContextMenu(() => defaultMenu)(DefaultNode)))); - } - if (type === 'custom-node') { - return withDndDrop( - nodeDropTargetSpec() - )(withDragNode(nodeDragSourceSpec(type))(withSelection()(withContextMenu(() => defaultMenu)(CustomPathNode)))); - } - return undefined; -}; - -export default actionsComponentFactory; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/defaultComponentFactory.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/defaultComponentFactory.ts deleted file mode 100644 index 5deae22856e..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/defaultComponentFactory.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ComponentType } from 'react'; -import { GraphElement, ComponentFactory, ModelKind, GraphComponent, DefaultNode } from '@patternfly/react-topology'; -import Edge from './DefaultEdge'; -import MultiEdge from './MultiEdge'; -import Group from './DefaultGroup'; -import GroupHull from './GroupHull'; - -const defaultComponentFactory: ComponentFactory = ( - kind: ModelKind, - type: string -): ComponentType<{ element: GraphElement }> => { - switch (type) { - case 'multi-edge': - return MultiEdge; - case 'group': - return Group; - case 'group-hull': - return GroupHull; - default: - switch (kind) { - case ModelKind.graph: - return GraphComponent; - case ModelKind.node: - return DefaultNode; - case ModelKind.edge: - return Edge; - default: - return undefined; - } - } -}; - -export default defaultComponentFactory; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/pipelineComponentFactory.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/pipelineComponentFactory.tsx deleted file mode 100644 index 7d0297991f7..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/pipelineComponentFactory.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import { - GraphElement, - ComponentFactory, - ModelKind, - SpacerNode, - DefaultTaskGroup, - DEFAULT_TASK_NODE_TYPE, - DEFAULT_SPACER_NODE_TYPE, - DEFAULT_EDGE_TYPE, - DEFAULT_FINALLY_NODE_TYPE, - ContextMenuSeparator, - ContextMenuItem, - withContextMenu, - withSelection, - withPanZoom, - GraphComponent, - TaskEdge -} from '@patternfly/react-topology'; -import DemoTaskNode from './DemoTaskNode'; -import DemoFinallyNode from './DemoFinallyNode'; -import DemoTaskGroupEdge from './DemoTaskGroupEdge'; - -export const GROUPED_EDGE_TYPE = 'GROUPED_EDGE'; - -const contextMenuItem = (label: string, i: number): React.ReactElement => { - if (label === '-') { - return ; - } - return ( - // eslint-disable-next-line no-alert - alert(`Selected: ${label}`)}> - {label} - - ); -}; - -const createContextMenuItems = (...labels: string[]): React.ReactElement[] => labels.map(contextMenuItem); - -const defaultMenu = createContextMenuItems('First', 'Second', 'Third', '-', 'Fourth'); - -const pipelineComponentFactory: ComponentFactory = ( - kind: ModelKind, - type: string -): React.ComponentType<{ element: GraphElement }> | undefined => { - if (kind === ModelKind.graph) { - return withPanZoom()(GraphComponent); - } - switch (type) { - case DEFAULT_TASK_NODE_TYPE: - return withContextMenu(() => defaultMenu)(withSelection()(DemoTaskNode)); - case DEFAULT_FINALLY_NODE_TYPE: - return withContextMenu(() => defaultMenu)(withSelection()(DemoFinallyNode)); - case 'task-group': - return DefaultTaskGroup; - case 'finally-group': - return DefaultTaskGroup; - case DEFAULT_SPACER_NODE_TYPE: - return SpacerNode; - case 'finally-spacer-edge': - case DEFAULT_EDGE_TYPE: - return TaskEdge; - case GROUPED_EDGE_TYPE: - return DemoTaskGroupEdge; - default: - return undefined; - } -}; - -export default pipelineComponentFactory; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Path.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Path.tsx deleted file mode 100644 index ce9a809fa12..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Path.tsx +++ /dev/null @@ -1,19 +0,0 @@ -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(); - const refs = useCombineRefs(dndDropRef, anchorRef); - - return ( - - ); -}; - -export default Path; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Polygon.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Polygon.tsx deleted file mode 100644 index 3cc0a10501c..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapes/Polygon.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { PointTuple, ShapeProps, usePolygonAnchor } from '@patternfly/react-topology'; -import * as React from 'react'; - -const Polygon: React.FunctionComponent = ({ className, width, height, filter, dndDropRef }) => { - const points: PointTuple[] = React.useMemo( - () => [ - [width / 2, 0], - [width - width / 8, height], - [0, height / 3], - [width, height / 3], - [width / 8, height] - ], - [height, width] - ); - usePolygonAnchor(points); - return ( - `${p[0]},${p[1]}`).join(' ')} - filter={filter} - /> - ); -}; - -export default Polygon; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapesComponentFactory.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapesComponentFactory.ts deleted file mode 100644 index e7fe0bd61e7..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/shapesComponentFactory.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ComponentType } from 'react'; -import { GraphElement, ComponentFactory, ModelKind } from '@patternfly/react-topology'; -import DemoDefaultNode from './DemoDefaultNode'; -import CustomPathNode from './CustomPathNode'; -import CustomPolygonNode from './CustomPolygonNode'; - -const shapesComponentFactory: ComponentFactory = ( - kind: ModelKind, - type: string -): ComponentType<{ element: GraphElement }> | undefined => { - switch (type) { - case 'node': - return DemoDefaultNode; - case 'node-path': - return CustomPathNode; - case 'node-polygon': - return CustomPolygonNode; - default: - return undefined; - } -}; - -export default shapesComponentFactory; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/stylesComponentFactory.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/stylesComponentFactory.tsx deleted file mode 100644 index 084d0b90a77..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/components/stylesComponentFactory.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import * as React from 'react'; -import { - GraphElement, - ComponentFactory, - withContextMenu, - ContextMenuSeparator, - ContextMenuItem, - withDragNode, - withSelection, - ModelKind, - DragObjectWithType, - Node, - withPanZoom, - GraphComponent, - withCreateConnector, - Graph, - isNode, - withDndDrop, - Edge, - withTargetDrag, - withSourceDrag, - nodeDragSourceSpec, - nodeDropTargetSpec, - groupDropTargetSpec, - graphDropTargetSpec, - NODE_DRAG_TYPE, - CREATE_CONNECTOR_DROP_TYPE -} from '@patternfly/react-topology'; -import StyleNode from './StyleNode'; -import StyleGroup from './StyleGroup'; -import StyleEdge from './StyleEdge'; -import CustomPathNode from './CustomPathNode'; -import CustomPolygonNode from './CustomPolygonNode'; - -const CONNECTOR_SOURCE_DROP = 'connector-src-drop'; -const CONNECTOR_TARGET_DROP = 'connector-target-drop'; - -interface EdgeProps { - element: Edge; -} - -const contextMenuItem = (label: string, i: number): React.ReactElement => { - if (label === '-') { - return ; - } - return ( - // eslint-disable-next-line no-alert - alert(`Selected: ${label}`)}> - {label} - - ); -}; - -const createContextMenuItems = (...labels: string[]): React.ReactElement[] => labels.map(contextMenuItem); - -const defaultMenu = createContextMenuItems('First', 'Second', 'Third', '-', 'Fourth'); - -const stylesComponentFactory: ComponentFactory = ( - kind: ModelKind, - type: string -): React.ComponentType<{ element: GraphElement }> | undefined => { - if (kind === ModelKind.graph) { - return withDndDrop(graphDropTargetSpec([NODE_DRAG_TYPE]))(withPanZoom()(GraphComponent)); - } - switch (type) { - case 'node': - return withCreateConnector((source: Node, target: Node | Graph): void => { - let targetId; - const model = source.getController().toModel(); - if (isNode(target)) { - targetId = target.getId(); - } else { - return; - } - const id = `e${source.getGraph().getEdges().length + 1}`; - if (!model.edges) { - model.edges = []; - } - model.edges.push({ - id, - type: 'edge', - source: source.getId(), - target: targetId - }); - source.getController().fromModel(model); - })( - withDndDrop(nodeDropTargetSpec([CONNECTOR_SOURCE_DROP, CONNECTOR_TARGET_DROP, CREATE_CONNECTOR_DROP_TYPE]))( - withContextMenu(() => defaultMenu)( - withDragNode(nodeDragSourceSpec('node', true, true))(withSelection()(StyleNode)) - ) - ) - ); - case 'node-path': - return CustomPathNode; - case 'node-polygon': - return CustomPolygonNode; - case 'group': - return withDndDrop(groupDropTargetSpec)( - withContextMenu(() => defaultMenu)(withDragNode(nodeDragSourceSpec('group'))(withSelection()(StyleGroup))) - ); - case 'edge': - return withSourceDrag({ - item: { type: CONNECTOR_SOURCE_DROP }, - begin: (monitor, props) => { - props.element.raise(); - return props.element; - }, - drag: (event, monitor, props) => { - props.element.setStartPoint(event.x, event.y); - }, - end: (dropResult, monitor, props) => { - if (monitor.didDrop() && dropResult && props) { - props.element.setSource(dropResult); - } - props.element.setStartPoint(); - } - })( - withTargetDrag({ - item: { type: CONNECTOR_TARGET_DROP }, - begin: (monitor, props) => { - props.element.raise(); - return props.element; - }, - drag: (event, monitor, props) => { - props.element.setEndPoint(event.x, event.y); - }, - end: (dropResult, monitor, props) => { - if (monitor.didDrop() && dropResult && props) { - props.element.setTarget(dropResult); - } - props.element.setEndPoint(); - }, - collect: monitor => ({ - dragging: monitor.isDragging() - }) - })(withContextMenu(() => defaultMenu)(withSelection()(StyleEdge))) - ); - default: - return undefined; - } -}; - -export default stylesComponentFactory; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/generator.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/generator.ts deleted file mode 100644 index 3917a208d2a..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/generator.ts +++ /dev/null @@ -1,211 +0,0 @@ -import React from 'react'; -import { - EdgeAnimationSpeed, - EdgeModel, - EdgeStyle, - EdgeTerminalType, - Model, - NodeModel, - NodeShape, - NodeStatus -} from '@patternfly/react-topology'; -import SignOutAltIcon from '@patternfly/react-icons/dist/esm/icons/skull-icon'; -import { createEdge, createNode } from '../utils/styleUtils'; -import { logos } from '../utils/logos'; -import { SVGIconProps } from '@patternfly/react-icons/dist/esm/createIcon'; - -const getRandomNode = (numNodes: number, notNode = -1): number => { - let node = Math.floor(Math.random() * numNodes); - if (node === notNode) { - node = getRandomNode(numNodes, notNode); - } - return node; -}; - -export interface GeneratorNodeOptions { - shapes?: NodeShape[]; - statuses?: NodeStatus[]; - statusDecorators?: boolean; - showDecorators?: boolean; - nodeLabels?: boolean; - nodeSecondaryLabels?: boolean; - nodeBadges?: boolean; - nodeIcons?: boolean; - smallNodes?: boolean; - contextMenus?: boolean; -} - -export interface GeneratorEdgeOptions { - edgeStyles?: EdgeStyle[]; - edgeStatuses?: NodeStatus[]; - edgeAnimations?: EdgeAnimationSpeed[]; - edgeTags?: boolean; - terminalTypes?: EdgeTerminalType[]; -} - -export const DefaultNodeOptions: GeneratorNodeOptions = { - shapes: [NodeShape.ellipse], - statuses: [NodeStatus.default], - statusDecorators: false, - showDecorators: false, - nodeLabels: true, - nodeSecondaryLabels: false, - nodeBadges: false, - nodeIcons: false, - smallNodes: false, - contextMenus: false -}; - -export const DefaultEdgeOptions: GeneratorEdgeOptions = { - edgeStyles: [EdgeStyle.default], - edgeStatuses: [NodeStatus.default], - edgeAnimations: [EdgeAnimationSpeed.none], - edgeTags: false, - terminalTypes: [EdgeTerminalType.directional] -}; - -export const getNodeOptions = ( - index: number, - nodeCreationOptions: GeneratorNodeOptions -): { - status?: NodeStatus; - shape?: NodeShape; - label?: string; - secondaryLabel?: string; - badge?: string; - showStatusDecorator?: boolean; - showDecorators?: boolean; - showContextMenu?: boolean; - labelIconClass?: string; - labelIcon?: React.ComponentClass; -} => { - const shapeEnumIndex = Math.round(Math.random() * (nodeCreationOptions.shapes.length - 1)); - const labelIconClass = index % 2 === 0 && nodeCreationOptions.nodeIcons ? logos.get('icon-java') : undefined; - const labelIcon = index % 2 === 1 && nodeCreationOptions.nodeIcons ? SignOutAltIcon : undefined; - return { - status: nodeCreationOptions.statuses[index % nodeCreationOptions.statuses.length], - shape: nodeCreationOptions.shapes[shapeEnumIndex], - label: nodeCreationOptions.nodeLabels ? `Node ${index} Title` : undefined, - secondaryLabel: nodeCreationOptions.nodeSecondaryLabels ? `Node subtitle` : undefined, - badge: nodeCreationOptions.nodeBadges ? 'CS' : undefined, - showStatusDecorator: nodeCreationOptions.statusDecorators, - showDecorators: nodeCreationOptions.showDecorators, - showContextMenu: nodeCreationOptions.contextMenus, - labelIconClass, - labelIcon - }; -}; - -export const generateNode = (index: number, nodeCreationOptions: GeneratorNodeOptions): NodeModel => { - const nodeId = `node-${index}`; - const width = nodeCreationOptions.smallNodes ? 48 : 75; - let height = nodeCreationOptions.smallNodes ? 48 : 75; - - const nodeOptions = getNodeOptions(index, nodeCreationOptions); - if (nodeOptions.shape === NodeShape.stadium) { - height *= 0.5; - } - return createNode({ - id: nodeId, - width, - height, - setLocation: false, - ...nodeOptions - }); -}; - -export const generateEdge = ( - index: number, - sourceId: string, - targetId: string, - options: GeneratorEdgeOptions -): EdgeModel => - createEdge(sourceId, targetId, { - style: options.edgeStyles[index % options.edgeStyles.length], - animation: options.edgeAnimations[index % options.edgeAnimations.length], - terminalType: options.terminalTypes[index % options.terminalTypes.length], - terminalStatus: options.edgeStatuses[index % options.edgeStatuses.length], - tag: options.edgeTags ? '250kbs' : undefined, - tagStatus: options.edgeStatuses[index % options.edgeStatuses.length] - }); - -export const generateDataModel = ( - numNodes: number, - numGroups: number, - numEdges: number, - groupDepth: number = 0, - nodeOptions: GeneratorNodeOptions = {}, - edgeOptions: GeneratorEdgeOptions = {} -): Model => { - const nodeCreationOptions = { ...DefaultNodeOptions, ...nodeOptions }; - const edgeCreationOptions = { ...DefaultEdgeOptions, ...edgeOptions }; - - const groups: NodeModel[] = []; - const nodes: NodeModel[] = []; - const edges: EdgeModel[] = []; - - const createGroup = ( - childNodes: NodeModel[], - baseId: string = 'Group', - index: number, - level: number = 0 - ): NodeModel => { - const id = `${baseId}-${index}`; - const group: NodeModel = { - id, - children: [], - type: 'group', - group: true, - label: id, - style: { padding: 15 }, - // data items are used to pass to the component to show various option, demo purposes only - data: { - badge: nodeCreationOptions.nodeBadges ? 'GN' : undefined, - badgeColor: '#F2F0FC', - badgeTextColor: '#5752d1', - badgeBorderColor: '#CBC1FF', - collapsedWidth: 75, - collapsedHeight: 75, - showContextMenu: nodeCreationOptions.contextMenus, - collapsible: true - } - }; - if (level === groupDepth) { - group.children = childNodes.map(n => n.id); - } else { - const nodesPerChildGroup = Math.floor(childNodes.length / 2); - if (nodesPerChildGroup < 1) { - const g1 = createGroup(childNodes, id, 1, level + 1); - group.children = [g1.id]; - } else { - const g1 = createGroup(childNodes.slice(0, nodesPerChildGroup), id, 1, level + 1); - const g2 = createGroup(childNodes.slice(nodesPerChildGroup), id, 2, level + 1); - group.children = [g1.id, g2.id]; - } - } - - groups.push(group); - return group; - }; - - for (let i = 0; i < numNodes; i++) { - const node = generateNode(i, nodeCreationOptions); - nodes.push(node); - } - - const nodesPerGroup = Math.floor((numNodes - 2) / numGroups); - for (let i = 0; i < numGroups; i++) { - createGroup(nodes.slice(i * nodesPerGroup, (i + 1) * nodesPerGroup), 'Group', i + 1); - } - - for (let i = 0; i < numEdges; i++) { - const sourceNum = getRandomNode(numNodes); - const targetNum = getRandomNode(numNodes, sourceNum); - const edge = generateEdge(i, nodes[sourceNum].id, nodes[targetNum].id, edgeCreationOptions); - edges.push(edge); - } - - nodes.push(...groups); - - return { nodes, edges }; -}; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/group-types.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/group-types.ts deleted file mode 100644 index aafaba0b45b..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/group-types.ts +++ /dev/null @@ -1,35 +0,0 @@ -export default { - nodes: [ - { id: 'cyan', type: 'cyan', color: 'cyan', width: 200, height: 100, group: 'blue' }, - { - id: 'lightblue', - type: 'lightblue', - color: 'lightblue', - width: 200, - height: 100, - group: 'blue' - }, - { id: 'orange', type: 'orange', color: 'orange', width: 100, height: 100 }, - { id: 'pink', type: 'pink', color: 'pink', width: 100, height: 100 }, - { id: 'blue', type: 'blue', color: 'blue', width: 100, height: 200 }, - { id: 'January', group: 'cyan' }, - { id: 'February', group: 'cyan' }, - { id: 'March', group: 'lightblue' }, - { id: 'April', group: 'lightblue' }, - { id: 'May', group: 'lightblue' }, - { id: 'June', group: 'orange' }, - { id: 'July', group: 'orange' }, - { id: 'August', group: 'orange' }, - { id: 'September', group: 'pink' }, - { id: 'October', group: 'pink' }, - { id: 'November', group: 'pink' }, - { id: 'December', group: 'cyan' } - ], - links: [ - { source: 'January', target: 'June', value: 1 }, - { source: 'January', target: 'February', value: 1 }, - { source: 'January', target: 'July', value: 8 }, - { source: 'October', target: 'February', value: 6 }, - { source: 'December', target: 'May', value: 1 } - ] -}; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/miserables.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/miserables.ts deleted file mode 100644 index f66584907b3..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/miserables.ts +++ /dev/null @@ -1,337 +0,0 @@ -export default { - nodes: [ - { id: 'Myriel', group: 1 }, - { id: 'Napoleon', group: 1 }, - { id: 'Mlle.Baptistine', group: 1 }, - { id: 'Mme.Magloire', group: 1 }, - { id: 'CountessdeLo', group: 1 }, - { id: 'Geborand', group: 1 }, - { id: 'Champtercier', group: 1 }, - { id: 'Cravatte', group: 1 }, - { id: 'Count', group: 1 }, - { id: 'OldMan', group: 1 }, - { id: 'Labarre', group: 2 }, - { id: 'Valjean', group: 2 }, - { id: 'Marguerite', group: 3 }, - { id: 'Mme.deR', group: 2 }, - { id: 'Isabeau', group: 2 }, - { id: 'Gervais', group: 2 }, - { id: 'Tholomyes', group: 3 }, - { id: 'Listolier', group: 3 }, - { id: 'Fameuil', group: 3 }, - { id: 'Blacheville', group: 3 }, - { id: 'Favourite', group: 3 }, - { id: 'Dahlia', group: 3 }, - { id: 'Zephine', group: 3 }, - { id: 'Fantine', group: 3 }, - { id: 'Mme.Thenardier', group: 4 }, - { id: 'Thenardier', group: 4 }, - { id: 'Cosette', group: 5 }, - { id: 'Javert', group: 4 }, - { id: 'Fauchelevent', group: 0 }, - { id: 'Bamatabois', group: 2 }, - { id: 'Perpetue', group: 3 }, - { id: 'Simplice', group: 2 }, - { id: 'Scaufflaire', group: 2 }, - { id: 'Woman1', group: 2 }, - { id: 'Judge', group: 2 }, - { id: 'Champmathieu', group: 2 }, - { id: 'Brevet', group: 2 }, - { id: 'Chenildieu', group: 2 }, - { id: 'Cochepaille', group: 2 }, - { id: 'Pontmercy', group: 4 }, - { id: 'Boulatruelle', group: 6 }, - { id: 'Eponine', group: 4 }, - { id: 'Anzelma', group: 4 }, - { id: 'Woman2', group: 5 }, - { id: 'MotherInnocent', group: 0 }, - { id: 'Gribier', group: 0 }, - { id: 'Jondrette', group: 7 }, - { id: 'Mme.Burgon', group: 7 }, - { id: 'Gavroche', group: 8 }, - { id: 'Gillenormand', group: 5 }, - { id: 'Magnon', group: 5 }, - { id: 'Mlle.Gillenormand', group: 5 }, - { id: 'Mme.Pontmercy', group: 5 }, - { id: 'Mlle.Vaubois', group: 5 }, - { id: 'Lt.Gillenormand', group: 5 }, - { id: 'Marius', group: 8 }, - { id: 'BaronessT', group: 5 }, - { id: 'Mabeuf', group: 8 }, - { id: 'Enjolras', group: 8 }, - { id: 'Combeferre', group: 8 }, - { id: 'Prouvaire', group: 8 }, - { id: 'Feuilly', group: 8 }, - { id: 'Courfeyrac', group: 8 }, - { id: 'Bahorel', group: 8 }, - { id: 'Bossuet', group: 8 }, - { id: 'Joly', group: 8 }, - { id: 'Grantaire', group: 8 }, - { id: 'MotherPlutarch', group: 9 }, - { id: 'Gueulemer', group: 4 }, - { id: 'Babet', group: 4 }, - { id: 'Claquesous', group: 4 }, - { id: 'Montparnasse', group: 4 }, - { id: 'Toussaint', group: 5 }, - { id: 'Child1', group: 10 }, - { id: 'Child2', group: 10 }, - { id: 'Brujon', group: 4 }, - { id: 'Mme.Hucheloup', group: 8 } - ], - links: [ - { source: 'Napoleon', target: 'Myriel' }, - { source: 'Mlle.Baptistine', target: 'Myriel' }, - { source: 'Mme.Magloire', target: 'Myriel' }, - { source: 'Mme.Magloire', target: 'Mlle.Baptistine' }, - { source: 'CountessdeLo', target: 'Myriel' }, - { source: 'Geborand', target: 'Myriel' }, - { source: 'Champtercier', target: 'Myriel' }, - { source: 'Cravatte', target: 'Myriel' }, - { source: 'Count', target: 'Myriel' }, - { source: 'OldMan', target: 'Myriel' }, - { source: 'Valjean', target: 'Labarre' }, - { source: 'Valjean', target: 'Mme.Magloire' }, - { source: 'Valjean', target: 'Mlle.Baptistine' }, - { source: 'Valjean', target: 'Myriel' }, - { source: 'Marguerite', target: 'Valjean' }, - { source: 'Mme.deR', target: 'Valjean' }, - { source: 'Isabeau', target: 'Valjean' }, - { source: 'Gervais', target: 'Valjean' }, - { source: 'Listolier', target: 'Tholomyes' }, - { source: 'Fameuil', target: 'Tholomyes' }, - { source: 'Fameuil', target: 'Listolier' }, - { source: 'Blacheville', target: 'Tholomyes' }, - { source: 'Blacheville', target: 'Listolier' }, - { source: 'Blacheville', target: 'Fameuil' }, - { source: 'Favourite', target: 'Tholomyes' }, - { source: 'Favourite', target: 'Listolier' }, - { source: 'Favourite', target: 'Fameuil' }, - { source: 'Favourite', target: 'Blacheville' }, - { source: 'Dahlia', target: 'Tholomyes' }, - { source: 'Dahlia', target: 'Listolier' }, - { source: 'Dahlia', target: 'Fameuil' }, - { source: 'Dahlia', target: 'Blacheville' }, - { source: 'Dahlia', target: 'Favourite' }, - { source: 'Zephine', target: 'Tholomyes' }, - { source: 'Zephine', target: 'Listolier' }, - { source: 'Zephine', target: 'Fameuil' }, - { source: 'Zephine', target: 'Blacheville' }, - { source: 'Zephine', target: 'Favourite' }, - { source: 'Zephine', target: 'Dahlia' }, - { source: 'Fantine', target: 'Tholomyes' }, - { source: 'Fantine', target: 'Listolier' }, - { source: 'Fantine', target: 'Fameuil' }, - { source: 'Fantine', target: 'Blacheville' }, - { source: 'Fantine', target: 'Favourite' }, - { source: 'Fantine', target: 'Dahlia' }, - { source: 'Fantine', target: 'Zephine' }, - { source: 'Fantine', target: 'Marguerite' }, - { source: 'Fantine', target: 'Valjean' }, - { source: 'Mme.Thenardier', target: 'Fantine' }, - { source: 'Mme.Thenardier', target: 'Valjean' }, - { source: 'Thenardier', target: 'Mme.Thenardier' }, - { source: 'Thenardier', target: 'Fantine' }, - { source: 'Thenardier', target: 'Valjean' }, - { source: 'Cosette', target: 'Mme.Thenardier' }, - { source: 'Cosette', target: 'Valjean' }, - { source: 'Cosette', target: 'Tholomyes' }, - { source: 'Cosette', target: 'Thenardier' }, - { source: 'Javert', target: 'Valjean' }, - { source: 'Javert', target: 'Fantine' }, - { source: 'Javert', target: 'Thenardier' }, - { source: 'Javert', target: 'Mme.Thenardier' }, - { source: 'Javert', target: 'Cosette' }, - { source: 'Fauchelevent', target: 'Valjean' }, - { source: 'Fauchelevent', target: 'Javert' }, - { source: 'Bamatabois', target: 'Fantine' }, - { source: 'Bamatabois', target: 'Javert' }, - { source: 'Bamatabois', target: 'Valjean' }, - { source: 'Perpetue', target: 'Fantine' }, - { source: 'Simplice', target: 'Perpetue' }, - { source: 'Simplice', target: 'Valjean' }, - { source: 'Simplice', target: 'Fantine' }, - { source: 'Simplice', target: 'Javert' }, - { source: 'Scaufflaire', target: 'Valjean' }, - { source: 'Woman1', target: 'Valjean' }, - { source: 'Woman1', target: 'Javert' }, - { source: 'Judge', target: 'Valjean' }, - { source: 'Judge', target: 'Bamatabois' }, - { source: 'Champmathieu', target: 'Valjean' }, - { source: 'Champmathieu', target: 'Judge' }, - { source: 'Champmathieu', target: 'Bamatabois' }, - { source: 'Brevet', target: 'Judge' }, - { source: 'Brevet', target: 'Champmathieu' }, - { source: 'Brevet', target: 'Valjean' }, - { source: 'Brevet', target: 'Bamatabois' }, - { source: 'Chenildieu', target: 'Judge' }, - { source: 'Chenildieu', target: 'Champmathieu' }, - { source: 'Chenildieu', target: 'Brevet' }, - { source: 'Chenildieu', target: 'Valjean' }, - { source: 'Chenildieu', target: 'Bamatabois' }, - { source: 'Cochepaille', target: 'Judge' }, - { source: 'Cochepaille', target: 'Champmathieu' }, - { source: 'Cochepaille', target: 'Brevet' }, - { source: 'Cochepaille', target: 'Chenildieu' }, - { source: 'Cochepaille', target: 'Valjean' }, - { source: 'Cochepaille', target: 'Bamatabois' }, - { source: 'Pontmercy', target: 'Thenardier' }, - { source: 'Boulatruelle', target: 'Thenardier' }, - { source: 'Eponine', target: 'Mme.Thenardier' }, - { source: 'Eponine', target: 'Thenardier' }, - { source: 'Anzelma', target: 'Eponine' }, - { source: 'Anzelma', target: 'Thenardier' }, - { source: 'Anzelma', target: 'Mme.Thenardier' }, - { source: 'Woman2', target: 'Valjean' }, - { source: 'Woman2', target: 'Cosette' }, - { source: 'Woman2', target: 'Javert' }, - { source: 'MotherInnocent', target: 'Fauchelevent' }, - { source: 'MotherInnocent', target: 'Valjean' }, - { source: 'Gribier', target: 'Fauchelevent' }, - { source: 'Mme.Burgon', target: 'Jondrette' }, - { source: 'Gavroche', target: 'Mme.Burgon' }, - { source: 'Gavroche', target: 'Thenardier' }, - { source: 'Gavroche', target: 'Javert' }, - { source: 'Gavroche', target: 'Valjean' }, - { source: 'Gillenormand', target: 'Cosette' }, - { source: 'Gillenormand', target: 'Valjean' }, - { source: 'Magnon', target: 'Gillenormand' }, - { source: 'Magnon', target: 'Mme.Thenardier' }, - { source: 'Mlle.Gillenormand', target: 'Gillenormand' }, - { source: 'Mlle.Gillenormand', target: 'Cosette' }, - { source: 'Mlle.Gillenormand', target: 'Valjean' }, - { source: 'Mme.Pontmercy', target: 'Mlle.Gillenormand' }, - { source: 'Mme.Pontmercy', target: 'Pontmercy' }, - { source: 'Mlle.Vaubois', target: 'Mlle.Gillenormand' }, - { source: 'Lt.Gillenormand', target: 'Mlle.Gillenormand' }, - { source: 'Lt.Gillenormand', target: 'Gillenormand' }, - { source: 'Lt.Gillenormand', target: 'Cosette' }, - { source: 'Marius', target: 'Mlle.Gillenormand' }, - { source: 'Marius', target: 'Gillenormand' }, - { source: 'Marius', target: 'Pontmercy' }, - { source: 'Marius', target: 'Lt.Gillenormand' }, - { source: 'Marius', target: 'Cosette' }, - { source: 'Marius', target: 'Valjean' }, - { source: 'Marius', target: 'Tholomyes' }, - { source: 'Marius', target: 'Thenardier' }, - { source: 'Marius', target: 'Eponine' }, - { source: 'Marius', target: 'Gavroche' }, - { source: 'BaronessT', target: 'Gillenormand' }, - { source: 'BaronessT', target: 'Marius' }, - { source: 'Mabeuf', target: 'Marius' }, - { source: 'Mabeuf', target: 'Eponine' }, - { source: 'Mabeuf', target: 'Gavroche' }, - { source: 'Enjolras', target: 'Marius' }, - { source: 'Enjolras', target: 'Gavroche' }, - { source: 'Enjolras', target: 'Javert' }, - { source: 'Enjolras', target: 'Mabeuf' }, - { source: 'Enjolras', target: 'Valjean' }, - { source: 'Combeferre', target: 'Enjolras' }, - { source: 'Combeferre', target: 'Marius' }, - { source: 'Combeferre', target: 'Gavroche' }, - { source: 'Combeferre', target: 'Mabeuf' }, - { source: 'Prouvaire', target: 'Gavroche' }, - { source: 'Prouvaire', target: 'Enjolras' }, - { source: 'Prouvaire', target: 'Combeferre' }, - { source: 'Feuilly', target: 'Gavroche' }, - { source: 'Feuilly', target: 'Enjolras' }, - { source: 'Feuilly', target: 'Prouvaire' }, - { source: 'Feuilly', target: 'Combeferre' }, - { source: 'Feuilly', target: 'Mabeuf' }, - { source: 'Feuilly', target: 'Marius' }, - { source: 'Courfeyrac', target: 'Marius' }, - { source: 'Courfeyrac', target: 'Enjolras' }, - { source: 'Courfeyrac', target: 'Combeferre' }, - { source: 'Courfeyrac', target: 'Gavroche' }, - { source: 'Courfeyrac', target: 'Mabeuf' }, - { source: 'Courfeyrac', target: 'Eponine' }, - { source: 'Courfeyrac', target: 'Feuilly' }, - { source: 'Courfeyrac', target: 'Prouvaire' }, - { source: 'Bahorel', target: 'Combeferre' }, - { source: 'Bahorel', target: 'Gavroche' }, - { source: 'Bahorel', target: 'Courfeyrac' }, - { source: 'Bahorel', target: 'Mabeuf' }, - { source: 'Bahorel', target: 'Enjolras' }, - { source: 'Bahorel', target: 'Feuilly' }, - { source: 'Bahorel', target: 'Prouvaire' }, - { source: 'Bahorel', target: 'Marius' }, - { source: 'Bossuet', target: 'Marius' }, - { source: 'Bossuet', target: 'Courfeyrac' }, - { source: 'Bossuet', target: 'Gavroche' }, - { source: 'Bossuet', target: 'Bahorel' }, - { source: 'Bossuet', target: 'Enjolras' }, - { source: 'Bossuet', target: 'Feuilly' }, - { source: 'Bossuet', target: 'Prouvaire' }, - { source: 'Bossuet', target: 'Combeferre' }, - { source: 'Bossuet', target: 'Mabeuf' }, - { source: 'Bossuet', target: 'Valjean' }, - { source: 'Joly', target: 'Bahorel' }, - { source: 'Joly', target: 'Bossuet' }, - { source: 'Joly', target: 'Gavroche' }, - { source: 'Joly', target: 'Courfeyrac' }, - { source: 'Joly', target: 'Enjolras' }, - { source: 'Joly', target: 'Feuilly' }, - { source: 'Joly', target: 'Prouvaire' }, - { source: 'Joly', target: 'Combeferre' }, - { source: 'Joly', target: 'Mabeuf' }, - { source: 'Joly', target: 'Marius' }, - { source: 'Grantaire', target: 'Bossuet' }, - { source: 'Grantaire', target: 'Enjolras' }, - { source: 'Grantaire', target: 'Combeferre' }, - { source: 'Grantaire', target: 'Courfeyrac' }, - { source: 'Grantaire', target: 'Joly' }, - { source: 'Grantaire', target: 'Gavroche' }, - { source: 'Grantaire', target: 'Bahorel' }, - { source: 'Grantaire', target: 'Feuilly' }, - { source: 'Grantaire', target: 'Prouvaire' }, - { source: 'MotherPlutarch', target: 'Mabeuf' }, - { source: 'Gueulemer', target: 'Thenardier' }, - { source: 'Gueulemer', target: 'Valjean' }, - { source: 'Gueulemer', target: 'Mme.Thenardier' }, - { source: 'Gueulemer', target: 'Javert' }, - { source: 'Gueulemer', target: 'Gavroche' }, - { source: 'Gueulemer', target: 'Eponine' }, - { source: 'Babet', target: 'Thenardier' }, - { source: 'Babet', target: 'Gueulemer' }, - { source: 'Babet', target: 'Valjean' }, - { source: 'Babet', target: 'Mme.Thenardier' }, - { source: 'Babet', target: 'Javert' }, - { source: 'Babet', target: 'Gavroche' }, - { source: 'Babet', target: 'Eponine' }, - { source: 'Claquesous', target: 'Thenardier' }, - { source: 'Claquesous', target: 'Babet' }, - { source: 'Claquesous', target: 'Gueulemer' }, - { source: 'Claquesous', target: 'Valjean' }, - { source: 'Claquesous', target: 'Mme.Thenardier' }, - { source: 'Claquesous', target: 'Javert' }, - { source: 'Claquesous', target: 'Eponine' }, - { source: 'Claquesous', target: 'Enjolras' }, - { source: 'Montparnasse', target: 'Javert' }, - { source: 'Montparnasse', target: 'Babet' }, - { source: 'Montparnasse', target: 'Gueulemer' }, - { source: 'Montparnasse', target: 'Claquesous' }, - { source: 'Montparnasse', target: 'Valjean' }, - { source: 'Montparnasse', target: 'Gavroche' }, - { source: 'Montparnasse', target: 'Eponine' }, - { source: 'Montparnasse', target: 'Thenardier' }, - { source: 'Toussaint', target: 'Cosette' }, - { source: 'Toussaint', target: 'Javert' }, - { source: 'Toussaint', target: 'Valjean' }, - { source: 'Child1', target: 'Gavroche' }, - { source: 'Child2', target: 'Gavroche' }, - { source: 'Child2', target: 'Child1' }, - { source: 'Brujon', target: 'Babet' }, - { source: 'Brujon', target: 'Gueulemer' }, - { source: 'Brujon', target: 'Thenardier' }, - { source: 'Brujon', target: 'Gavroche' }, - { source: 'Brujon', target: 'Eponine' }, - { source: 'Brujon', target: 'Claquesous' }, - { source: 'Brujon', target: 'Montparnasse' }, - { source: 'Mme.Hucheloup', target: 'Bossuet' }, - { source: 'Mme.Hucheloup', target: 'Joly' }, - { source: 'Mme.Hucheloup', target: 'Grantaire' }, - { source: 'Mme.Hucheloup', target: 'Bahorel' }, - { source: 'Mme.Hucheloup', target: 'Courfeyrac' }, - { source: 'Mme.Hucheloup', target: 'Gavroche' }, - { source: 'Mme.Hucheloup', target: 'Enjolras' } - ] -}; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/reasonable.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/reasonable.ts deleted file mode 100644 index 4af62552172..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/data/reasonable.ts +++ /dev/null @@ -1,23 +0,0 @@ -export default { - nodes: [ - { id: 'January', group: 1 }, - { id: 'February', group: 1 }, - { id: 'March', group: 2 }, - { id: 'April', group: 2 }, - { id: 'May', group: 2 }, - { id: 'June', group: 3 }, - { id: 'July', group: 3 }, - { id: 'August', group: 3 }, - { id: 'September', group: 4 }, - { id: 'October', group: 4 }, - { id: 'November', group: 4 }, - { id: 'December', group: 1 } - ], - links: [ - { source: 'January', target: 'June', value: 1 }, - { source: 'January', target: 'February', value: 1 }, - { source: 'January', target: 'July', value: 8 }, - { source: 'October', target: 'February', value: 6 }, - { source: 'December', target: 'May', value: 1 } - ] -}; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/layouts/defaultLayoutFactory.ts b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/layouts/defaultLayoutFactory.ts deleted file mode 100644 index 9e78541728b..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/layouts/defaultLayoutFactory.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - Graph, - Layout, - LayoutFactory, - ForceLayout, - ColaLayout, - ConcentricLayout, - DagreLayout, - GridLayout, - BreadthFirstLayout -} from '@patternfly/react-topology'; -import { ColaGroupsLayout } from '@patternfly/react-topology/dist/esm/layouts/ColaGroupsLayout'; - -const defaultLayoutFactory: LayoutFactory = (type: string, graph: Graph): Layout | undefined => { - switch (type) { - case 'BreadthFirst': - return new BreadthFirstLayout(graph); - case 'Cola': - return new ColaLayout(graph); - case 'ColaNoForce': - return new ColaLayout(graph, { layoutOnDrag: false }); - case 'Concentric': - return new ConcentricLayout(graph); - case 'Dagre': - return new DagreLayout(graph); - case 'Force': - return new ForceLayout(graph); - case 'Grid': - return new GridLayout(graph); - case 'ColaGroups': - return new ColaGroupsLayout(graph, { layoutOnDrag: false }); - default: - return new ColaLayout(graph, { layoutOnDrag: false }); - } -}; - -export default defaultLayoutFactory; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useDemoPipelineNodes.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useDemoPipelineNodes.tsx deleted file mode 100644 index 1766b2ab8aa..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useDemoPipelineNodes.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import * as React from 'react'; -import { - DEFAULT_FINALLY_NODE_TYPE, - DEFAULT_TASK_NODE_TYPE, - DEFAULT_WHEN_OFFSET, - DEFAULT_WHEN_SIZE, - PipelineNodeModel, - RunStatus, - WhenStatus -} from '@patternfly/react-topology'; -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; -import { logos } from './utils/logos'; - -export const NODE_PADDING_VERTICAL = 45; -export const NODE_PADDING_HORIZONTAL = 15; - -export const ROW_HEIGHT = 100; -export const COLUMN_WIDTH = 250; - -export const DEFAULT_TASK_WIDTH = 180; -export const FINALLY_TASK_WIDTH = DEFAULT_TASK_WIDTH - DEFAULT_WHEN_OFFSET - DEFAULT_WHEN_SIZE; -export const DEFAULT_TASK_HEIGHT = 32; - -export const TASK_STATUSES = [ - undefined, - RunStatus.Succeeded, - RunStatus.Failed, - RunStatus.Running, - RunStatus.InProgress, - RunStatus.FailedToStart, - RunStatus.Skipped, - RunStatus.Cancelled, - RunStatus.Pending, - RunStatus.Idle -]; - -const STATUS_PER_ROW = 4; -const GRAPH_MARGIN_TOP = 40; -const PARALLEL_TASKS_COUNT = 3; -const PARALLEL_TASK_DEPTH = 2; -const FINALLY_TASKS_COUNT = 2; - -export const useDemoPipelineNodes = ( - showContextMenu: boolean, - showBadges: boolean, - showIcons: boolean, - badgeTooltips: boolean, - layout?: string, - showGroups = false -): PipelineNodeModel[] => - React.useMemo(() => { - // Create a task node for each task status - const tasks = TASK_STATUSES.map((status, index) => { - // Set all the standard fields - const task: PipelineNodeModel = { - id: `task-${status}`, - type: DEFAULT_TASK_NODE_TYPE, - label: `${status || 'No status'} Task`, - width: DEFAULT_TASK_WIDTH + (showContextMenu ? 10 : 0) + (showBadges ? 40 : 0), - height: DEFAULT_TASK_HEIGHT, - style: { - padding: [NODE_PADDING_VERTICAL, NODE_PADDING_HORIZONTAL + (showIcons ? 25 : 0)] - }, - runAfterTasks: [] - }; - - // put options in data, our DEMO task node will pass them along to the TaskNode - task.data = { - status, - badge: showBadges ? '3/4' : undefined, - badgeTooltips, - taskIconClass: showIcons ? logos.get('icon-java') : undefined, - taskIconTooltip: showIcons ? 'Environment' : undefined, - showContextMenu, - columnGroup: index % STATUS_PER_ROW - }; - - // If not using a layout, manually place the node by setting the x,y location - if (!layout) { - const row = Math.ceil((index + 1) / STATUS_PER_ROW) - 1; - const column = index % STATUS_PER_ROW; - const columnWidth = COLUMN_WIDTH + (showIcons ? 15 : 0) + (showBadges ? 32 : 0) + (showContextMenu ? 20 : 0); - task.x = (showIcons ? 28 : 0) + column * columnWidth; - task.y = GRAPH_MARGIN_TOP + row * ROW_HEIGHT; - } - - return task; - }); - - // Add when tasks to the nodes that are not first in the row - const whenTasks = tasks.filter( - (task, index) => index % (Math.floor(tasks.length / (STATUS_PER_ROW - 1)) + 1) !== 0 - ); - whenTasks.forEach((task, index) => { - task.data.whenStatus = index % 2 === 0 ? WhenStatus.Met : WhenStatus.Unmet; - task.data.whenOffset = DEFAULT_WHEN_OFFSET; - task.data.whenSize = DEFAULT_WHEN_SIZE; - }); - - // Connect the tasks in each row by setting the `runAfterTasks` value for each task - for (let i = 0; i < tasks.length; i++) { - tasks[i + 1].runAfterTasks.push(tasks[i].id); - i++; - if (i + 1 < tasks.length) { - tasks[i + 1].runAfterTasks.push(tasks[i].id); - } - i++; - if (i + 1 < tasks.length) { - tasks[i + 1].runAfterTasks.push(tasks[i].id); - } - i++; - } - - if (layout) { - const parallelTasks: PipelineNodeModel[] = []; - - for (let i = 0; i < PARALLEL_TASKS_COUNT; i++) { - const parallelTask: PipelineNodeModel = { - id: `parallelTasks-${i}`, - type: DEFAULT_TASK_NODE_TYPE, - label: `Parallel Sub-Task ${i}`, - width: DEFAULT_TASK_WIDTH + (showContextMenu ? 10 : 0) + (showBadges ? 40 : 0), - height: DEFAULT_TASK_HEIGHT, - style: { - padding: [NODE_PADDING_VERTICAL, NODE_PADDING_HORIZONTAL + (showIcons ? 25 : 0)] - }, - runAfterTasks: [] - }; - - // put options in data, our DEMO task node will pass them along to the TaskNode - parallelTask.data = { - status, - showContextMenu - }; - parallelTasks.push(parallelTask); - } - - let usedNodes = 0; - while (usedNodes < parallelTasks.length) { - for (let depth = 0; depth < PARALLEL_TASK_DEPTH; depth++) { - if (usedNodes < parallelTasks.length) { - if (depth === 0) { - parallelTasks[usedNodes].runAfterTasks = [tasks[9].id]; - } else { - parallelTasks[usedNodes].runAfterTasks = [parallelTasks[usedNodes - 1].id]; - } - } - usedNodes++; - } - } - tasks.push(...parallelTasks); - - if (showGroups) { - tasks.push({ - id: `group-parallels`, - type: 'task-group', - children: parallelTasks.map(t => t.id), - group: true, - label: 'Parallel tasks' - }); - } - } - - const finallyNodes = []; - for (let i = 0; i < FINALLY_TASKS_COUNT; i++) { - const finallyNode: PipelineNodeModel = { - id: `finally-${i}`, - type: DEFAULT_FINALLY_NODE_TYPE, - label: `Finally task ${i}`, - width: FINALLY_TASK_WIDTH, - height: DEFAULT_TASK_HEIGHT, - style: { paddingLeft: DEFAULT_WHEN_SIZE + DEFAULT_WHEN_OFFSET } - }; - - if (!layout) { - const columnWidth = COLUMN_WIDTH + (showIcons ? 15 : 0) + (showBadges ? 32 : 0) + (showContextMenu ? 20 : 0); - finallyNode.x = STATUS_PER_ROW * columnWidth; - finallyNode.y = GRAPH_MARGIN_TOP + ((3 - FINALLY_TASKS_COUNT) * ROW_HEIGHT) / 2 + ROW_HEIGHT * i; - } - finallyNodes.push(finallyNode); - } - - const finallyGroup = { - id: 'finally-group', - type: 'finally-group', - children: finallyNodes.map(n => n.id), - group: true - }; - - if (showGroups) { - const taskGroups = tasks.reduce((acc: PipelineNodeModel[], task) => { - if (task.data?.columnGroup !== undefined) { - let taskGroup = acc.find((group: PipelineNodeModel) => group.id === `group-${task.data.columnGroup}`); - if (!taskGroup) { - taskGroup = { - id: `group-${task.data.columnGroup}`, - type: 'task-group', - children: [], - group: true, - label: `Group ${task.data.columnGroup}` - }; - acc.push(taskGroup); - } - taskGroup.children.push(task.id); - } - return acc; - }, [] as PipelineNodeModel[]); - - tasks.push(...taskGroups); - } - - return [...tasks, ...finallyNodes, finallyGroup]; - }, [badgeTooltips, layout, showBadges, showContextMenu, showGroups, showIcons]); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/usePipelineOptions.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/usePipelineOptions.tsx deleted file mode 100644 index 9a6f063c17f..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/usePipelineOptions.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import { Checkbox, ToolbarItem } from '@patternfly/react-core'; -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; - -export const usePipelineOptions = ( - allowGroups = false -): { - contextToolbar: React.ReactNode; - showContextMenu: boolean; - showBadges: boolean; - showIcons: boolean; - showGroups: boolean; - badgeTooltips: boolean; -} => { - const [showContextMenu, setShowContextMenu] = React.useState(false); - const [showBadges, setShowBadges] = React.useState(false); - const [showIcons, setShowIcons] = React.useState(false); - const [showGroups, setShowGroups] = React.useState(false); - const [badgeTooltips, setBadgeTooltips] = React.useState(false); - - const contextToolbar = ( - <> - - - - - - - - - - - - - {allowGroups ? ( - - - - ) : null} - - ); - - return { contextToolbar, showContextMenu, showBadges, showIcons, showGroups, badgeTooltips }; -}; diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useTopologyOptions.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useTopologyOptions.tsx deleted file mode 100644 index ec6155e4748..00000000000 --- a/packages/react-integration/demo-app-ts/src/components/demos/TopologyDemo/useTopologyOptions.tsx +++ /dev/null @@ -1,450 +0,0 @@ -import React from 'react'; -import * as _ from 'lodash'; -import { - Button, - Dropdown, - DropdownItem, - DropdownPosition, - DropdownToggle, - Flex, - Select, - SelectOption, - SelectVariant, - Split, - SplitItem, - TextInput, - ToolbarItem, - Tooltip -} from '@patternfly/react-core'; -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; -import { DefaultEdgeOptions, DefaultNodeOptions, GeneratorEdgeOptions, GeneratorNodeOptions } from './data/generator'; -import { - EDGE_ANIMATION_SPEEDS, - EDGE_STYLES, - EDGE_TERMINAL_TYPES, - NODE_SHAPES, - NODE_STATUSES -} from './utils/styleUtils'; -import { Controller, Model, NodeShape } from '@patternfly/react-topology'; - -const GRAPH_LAYOUT_OPTIONS = ['x', 'y', 'visible', 'style', 'layout', 'scale', 'scaleExtent', 'layers']; -const NODE_LAYOUT_OPTIONS = ['x', 'y', 'visible', 'style', 'collapsed', 'width', 'height', 'shape']; - -export const useTopologyOptions = ( - controller: Controller -): { - layout: string; - nodeOptions: GeneratorNodeOptions; - edgeOptions: GeneratorEdgeOptions; - nestedLevel: number; - creationCounts: { numNodes: number; numEdges: number; numGroups: number }; - medScale: number; - lowScale: number; - contextToolbar: React.ReactNode; - viewToolbar: React.ReactNode; -} => { - const [layoutDropdownOpen, setLayoutDropdownOpen] = React.useState(false); - const [layout, setLayout] = React.useState('ColaNoForce'); - const [nodeOptionsOpen, setNodeOptionsOpen] = React.useState(false); - const [nodeShapesOpen, setNodeShapesOpen] = React.useState(false); - const [nodeOptions, setNodeOptions] = React.useState(DefaultNodeOptions); - const [edgeOptionsOpen, setEdgeOptionsOpen] = React.useState(false); - const [edgeOptions, setEdgeOptions] = React.useState(DefaultEdgeOptions); - const [savedModel, setSavedModel] = React.useState(); - const [modelSaved, setModelSaved] = React.useState(false); - const newNodeCount = React.useRef(0); - const [numNodes, setNumNodes] = React.useState(6); - const [numEdges, setNumEdges] = React.useState(2); - const [numGroups, setNumGroups] = React.useState(1); - const [nestedLevel, setNestedLevel] = React.useState(0); - const [medScale, setMedScale] = React.useState(0.5); - const [lowScale, setLowScale] = React.useState(0.3); - const [creationCounts, setCreationCounts] = React.useState<{ numNodes: number; numEdges: number; numGroups: number }>( - { numNodes, numEdges, numGroups } - ); - - const updateLayout = (newLayout: string) => { - setLayout(newLayout); - setLayoutDropdownOpen(false); - }; - - const layoutDropdown = ( - - - - - - setLayoutDropdownOpen(!layoutDropdownOpen)}>{layout}} - isOpen={layoutDropdownOpen} - dropdownItems={[ - updateLayout('Force')}> - Force - , - updateLayout('Dagre')}> - Dagre - , - updateLayout('Cola')}> - Cola - , - updateLayout('ColaGroups')}> - ColaGroups - , - updateLayout('ColaNoForce')}> - ColaNoForce - , - updateLayout('Grid')}> - Grid - , - updateLayout('Concentric')}> - Concentric - , - updateLayout('BreadthFirst')}> - BreadthFirst - - ]} - /> - - - ); - - const renderNodeOptionsDropdown = () => { - const selectContent = ( -
- setNodeOptions(prev => ({ ...prev, nodeLabels: !prev.nodeLabels }))} - /> - setNodeOptions(prev => ({ ...prev, nodeSecondaryLabels: !prev.nodeSecondaryLabels }))} - /> - 1} - onClick={() => - setNodeOptions(prev => ({ - ...prev, - statuses: prev.statuses.length > 1 ? DefaultNodeOptions.statuses : NODE_STATUSES - })) - } - /> - - setNodeOptions(prev => ({ - ...prev, - statusDecorators: !prev.statusDecorators, - showDecorators: !prev.showDecorators - })) - } - /> - setNodeOptions(prev => ({ ...prev, nodeBadges: !prev.nodeBadges }))} - /> - setNodeOptions(prev => ({ ...prev, nodeIcons: !prev.nodeIcons }))} - /> - setNodeOptions(prev => ({ ...prev, contextMenus: !prev.contextMenus }))} - /> -
- ); - - return ( - setNodeShapesOpen(prev => !prev)} - onSelect={() => {}} - isCheckboxSelectionBadgeHidden - isOpen={nodeShapesOpen} - placeholderText="Node shapes" - /> - ); - }; - - const renderEdgeOptionsDropdown = () => { - const selectContent = ( -
- 1} - onClick={() => - setEdgeOptions(prev => ({ - ...prev, - edgeStatuses: prev.edgeStatuses.length > 1 ? DefaultEdgeOptions.edgeStatuses : NODE_STATUSES - })) - } - /> - 1} - onClick={() => - setEdgeOptions(prev => ({ - ...prev, - edgeStyles: prev.edgeStyles.length > 1 ? DefaultEdgeOptions.edgeStyles : EDGE_STYLES - })) - } - /> - 1} - onClick={() => - setEdgeOptions(prev => ({ - ...prev, - edgeAnimations: prev.edgeAnimations.length > 1 ? DefaultEdgeOptions.edgeAnimations : EDGE_ANIMATION_SPEEDS - })) - } - /> - 1} - onClick={() => - setEdgeOptions(prev => ({ - ...prev, - terminalTypes: prev.terminalTypes.length > 1 ? DefaultEdgeOptions.terminalTypes : EDGE_TERMINAL_TYPES - })) - } - /> - setEdgeOptions(prev => ({ ...prev, edgeTags: !prev.edgeTags }))} - /> -
- ); - - return ( - - setViewOptions(prev => ({ ...prev, showLabels: !prev.showLabels }))} - /> - setViewOptions(prev => ({ ...prev, showBadges: !prev.showBadges }))} - /> - setViewOptions(prev => ({ ...prev, showStatusBackground: !prev.showStatusBackground }))} - /> - setViewOptions(prev => ({ ...prev, showDecorators: !prev.showDecorators }))} - /> - - } - onToggle={() => setViewOptionsOpen(prev => !prev)} - onSelect={() => {}} - isCheckboxSelectionBadgeHidden - isOpen={viewOptionsOpen} - placeholderText="Node options" - /> - - ); - - return ( - - - - - - ); -}; diff --git a/packages/react-topology/src/components/TopologyView/examples/topology-example.css b/packages/react-topology/src/components/TopologyView/examples/topology-example.css deleted file mode 100644 index 0451d5f8c56..00000000000 --- a/packages/react-topology/src/components/TopologyView/examples/topology-example.css +++ /dev/null @@ -1,49 +0,0 @@ -.ws-react-t-anchors, -.ws-react-t-control-bar, -.ws-react-t-context-menu, -.ws-react-t-custom-edges, -.ws-react-t-custom-nodes, -.ws-react-t-drag-and-drop, -.ws-react-t-getting-started, -.ws-react-t-layouts, -.ws-react-t-panzoom, -.ws-react-t-selection, -.ws-react-t-sidebar, -.ws-react-t-toolbar { - height: 600px; - border: 1px solid var(--pf-global--palette--black-900); - padding: 0; - margin: var(--pf-global--spacer--md); -} - -@media (min-width: 768px) { - .topology-example-sidebar.pf-topology-side-bar.shown { - max-width: 300px; - } -} - -.pf-theme-dark .ws-react-t-control-bar, -.pf-theme-dark .ws-react-t-custom-edges, -.pf-theme-dark .ws-react-t-custom-nodes, -.pf-theme-dark .ws-react-t-getting-started, -.pf-theme-dark .ws-react-t-panzoom, -.pf-theme-dark .ws-react-t-selection, -.pf-theme-dark .ws-react-t-sidebar, -.pf-theme-dark .ws-react-t-toolbar { - border: 1px solid var(--pf-global--palette--black-100); -} - -.ws-react-t-topology .pf-l-stack { - margin: -9px; - width: calc(100% + 18px); -} - -.ws-react-t-topology .pf-topology-view__project-toolbar .pf-c-dropdown>button { - justify-content: space-between; - width: 150px; -} - -.ws-react-t-topology .topology-view-filter-dropdown>button { - justify-content: space-between; - width: 130px; -} diff --git a/packages/react-topology/src/components/TopologyView/examples/topology-pipelines-example.css b/packages/react-topology/src/components/TopologyView/examples/topology-pipelines-example.css deleted file mode 100644 index 4db8d595d4e..00000000000 --- a/packages/react-topology/src/components/TopologyView/examples/topology-pipelines-example.css +++ /dev/null @@ -1,6 +0,0 @@ -.ws-react-t-pipelines { - height: 300px; - border: 1px solid var(--pf-global--palette--black-900); - padding: 0; - margin: var(--pf-global--spacer--md); -} diff --git a/packages/react-topology/src/components/TopologyView/index.ts b/packages/react-topology/src/components/TopologyView/index.ts deleted file mode 100644 index 8124fd0742f..00000000000 --- a/packages/react-topology/src/components/TopologyView/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './TopologyView'; diff --git a/packages/react-topology/src/components/VisualizationProvider.tsx b/packages/react-topology/src/components/VisualizationProvider.tsx deleted file mode 100644 index e5a918eeed0..00000000000 --- a/packages/react-topology/src/components/VisualizationProvider.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from 'react'; -import ControllerContext from '../utils/ControllerContext'; -import { Controller } from '../types'; -import { Visualization } from '../Visualization'; - -interface VisualizationProviderProps { - /** The graph controller to store in context */ - controller?: Controller; - /** Content rendered inside the surface */ - children?: React.ReactNode; -} - -const VisualizationProvider: React.FunctionComponent = ({ - controller, - children -}: VisualizationProviderProps) => { - const controllerRef = React.useRef(); - if (controller && controllerRef.current !== controller) { - controllerRef.current = controller; - } else if (!controllerRef.current) { - controllerRef.current = new Visualization(); - } - - return {children}; -}; - -export default VisualizationProvider; diff --git a/packages/react-topology/src/components/VisualizationSurface.tsx b/packages/react-topology/src/components/VisualizationSurface.tsx deleted file mode 100644 index c0f3c2bccaa..00000000000 --- a/packages/react-topology/src/components/VisualizationSurface.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import * as React from 'react'; -import * as _ from 'lodash'; -import { action } from 'mobx'; -// https://github.com/mobxjs/mobx-react#observer-batching -import 'mobx-react/batchingForReactDom'; -import { observer } from 'mobx-react'; -import ReactMeasure from 'react-measure'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { State } from '../types'; -import SVGDefsProvider from './defs/SVGDefsProvider'; -import ElementWrapper from './ElementWrapper'; -import Dimensions from '../geom/Dimensions'; -import useVisualizationController from '../hooks/useVisualizationController'; - -import '@patternfly/react-styles/css/components/Topology/topology-components.css'; - -interface VisualizationSurfaceProps { - /** State to be passed to the controller */ - state?: State; - /** Additional content rendered inside the surface */ - children?: React.ReactNode; -} - -const stopEvent = (e: React.MouseEvent): void => { - e.preventDefault(); - e.stopPropagation(); -}; - -const VisualizationSurface: React.FunctionComponent = ({ - state -}: VisualizationSurfaceProps) => { - const controller = useVisualizationController(); - - React.useEffect(() => { - state && controller.setState(state); - }, [controller, state]); - - const onMeasure = React.useMemo( - () => - _.debounce( - action((contentRect: { client: { width: number; height: number } }) => { - controller.getGraph().setDimensions(new Dimensions(contentRect.client.width, contentRect.client.height)); - }), - 100, - { leading: true, trailing: true } - ), - [controller] - ); - - // dispose of onMeasure - React.useEffect(() => () => onMeasure.cancel(), [onMeasure]); - - if (!controller.hasGraph()) { - return null; - } - - const graph = controller.getGraph(); - - return ( - - {({ measureRef }: { measureRef: React.LegacyRef }) => ( - // render an outer div because react-measure doesn't seem to fire events properly on svg resize -
- - - - - -
- )} -
- ); -}; - -export default observer(VisualizationSurface); diff --git a/packages/react-topology/src/components/__tests__/ComputeElementDimensions.test.tsx b/packages/react-topology/src/components/__tests__/ComputeElementDimensions.test.tsx deleted file mode 100644 index 5e5d5d368ce..00000000000 --- a/packages/react-topology/src/components/__tests__/ComputeElementDimensions.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import ComputeElementDimensions from '../ComputeElementDimensions'; - -describe('ComputeElementDimensions', () => { - it('should render invisible group', () => { - render( - - - - ); - - expect( - screen - .getByTestId('wrapper-test-id') - .querySelector('g') - ).toHaveAttribute('style', 'visibility: hidden;'); - }); -}); diff --git a/packages/react-topology/src/components/contextmenu/ContextMenu.tsx b/packages/react-topology/src/components/contextmenu/ContextMenu.tsx deleted file mode 100644 index 6f2dc3c66f2..00000000000 --- a/packages/react-topology/src/components/contextmenu/ContextMenu.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from 'react'; -import { DropdownMenu, DropdownContext } from '@patternfly/react-core'; -import { css } from '@patternfly/react-styles'; -import topologyStyles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; -// FIXME fully qualified due to the effect of long build times on storybook -import Popper from '../popper/Popper'; - -type ContextMenuProps = Pick< - React.ComponentProps, - 'children' | 'container' | 'className' | 'open' | 'reference' | 'onRequestClose' ->; - -const ContextMenu: React.FunctionComponent = ({ - children, - open = true, - onRequestClose, - ...other -}) => { - const [isOpen, setOpen] = React.useState(!!open); - React.useEffect(() => { - setOpen(open); - }, [open]); - - const handleOnRequestClose = React.useCallback(() => { - onRequestClose ? onRequestClose() : setOpen(false); - }, [onRequestClose]); - - return ( - - -
- - {children} - -
-
-
- ); -}; - -export default ContextMenu; diff --git a/packages/react-topology/src/components/contextmenu/ContextSubMenuItem.tsx b/packages/react-topology/src/components/contextmenu/ContextSubMenuItem.tsx deleted file mode 100644 index fc97b4dbafc..00000000000 --- a/packages/react-topology/src/components/contextmenu/ContextSubMenuItem.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import * as React from 'react'; -import { DropdownMenu, DropdownItem } from '@patternfly/react-core'; -import { css } from '@patternfly/react-styles'; -import topologyStyles from '@patternfly/react-styles/css/components/Topology/topology-components'; -// FIXME fully qualified due to the effect of long build times on storybook -import Popper from '../popper/Popper'; -import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon'; - -interface ContextSubMenuItemProps { - label: React.ReactNode; - children: React.ReactNode[]; -} - -const ContextSubMenuItem: React.FunctionComponent = ({ label, children, ...other }) => { - const nodeRef = React.useRef(null); - const subMenuRef = React.useRef(null); - const [open, setOpen] = React.useState(false); - const referenceCb = React.useCallback(() => nodeRef.current || { x: 0, y: 0 }, []); - - return ( - <> - e.stopPropagation()} - // mouse enter will open the sub menu - onMouseEnter={() => setOpen(true)} - onMouseLeave={e => { - // if the mouse leaves this item, close the sub menu only if the mouse did not enter the sub menu itself - if (!subMenuRef.current || !subMenuRef.current.contains(e.relatedTarget as Node)) { - setOpen(false); - } - }} - onKeyDown={e => { - // open the sub menu on enter or right arrow - if (e.key === 'ArrowRight' || e.key === 'Enter') { - setOpen(true); - e.stopPropagation(); - } - }} - > - {label} - - - } - /> - { - // only close the sub menu if clicking anywhere outside the menu item that owns the sub menu - if (!e || !nodeRef.current || !nodeRef.current.contains(e.target as Node)) { - setOpen(false); - } - }} - reference={referenceCb} - // use the parent node to capture the li - container={nodeRef.current ? nodeRef.current.parentElement : nodeRef.current} - returnFocus - > -
{ - // only close the sub menu if the mouse does not enter the item - if (!nodeRef.current || !nodeRef.current.contains(e.relatedTarget as Node)) { - setOpen(false); - } - }} - onKeyDown={e => { - // close the sub menu on left arrow - if (e.key === 'ArrowLeft') { - setOpen(false); - e.stopPropagation(); - } - }} - > - - {children} - -
-
- - ); -}; - -export default ContextSubMenuItem; diff --git a/packages/react-topology/src/components/contextmenu/index.ts b/packages/react-topology/src/components/contextmenu/index.ts deleted file mode 100644 index 7a67e6beb1d..00000000000 --- a/packages/react-topology/src/components/contextmenu/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as ContextMenu } from './ContextMenu'; -export { default as ContextSubMenuItem } from './ContextSubMenuItem'; - -// re-export dropdown components as context menu components -export { DropdownItem as ContextMenuItem, DropdownSeparator as ContextMenuSeparator } from '@patternfly/react-core'; diff --git a/packages/react-topology/src/components/decorators/Decorator.tsx b/packages/react-topology/src/components/decorators/Decorator.tsx deleted file mode 100644 index 3ef9f6dd0e2..00000000000 --- a/packages/react-topology/src/components/decorators/Decorator.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import SvgDropShadowFilter from '../svg/SvgDropShadowFilter'; -import { createSvgIdUrl, useHover } from '../../utils'; -import { DEFAULT_DECORATOR_PADDING } from '../nodes'; - -interface DecoratorTypes { - children?: React.ReactNode; - className?: string; - x: number; - y: number; - radius: number; - padding?: number; - showBackground?: boolean; - icon?: React.ReactNode; - onClick?(event: React.MouseEvent): void; - ariaLabel?: string; - circleRef?: React.Ref; -} - -const HOVER_FILTER_ID = 'DecoratorDropShadowHoverFilterId'; - -const Decorator: React.FunctionComponent = ({ - className, - x, - y, - showBackground, - radius, - padding = DEFAULT_DECORATOR_PADDING, - children, - icon, - onClick, - ariaLabel, - circleRef -}) => { - const [hover, hoverRef] = useHover(); - const iconRadius = radius - padding; - - return ( - { - e.stopPropagation(); - onClick(e); - }, - role: 'button', - 'aria-label': ariaLabel - } - : null)} - > - - {showBackground && ( - - )} - - {icon ? ( - - {icon} - - ) : null} - {children} - - - ); -}; - -export default Decorator; diff --git a/packages/react-topology/src/components/decorators/index.ts b/packages/react-topology/src/components/decorators/index.ts deleted file mode 100644 index 5041286483e..00000000000 --- a/packages/react-topology/src/components/decorators/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as Decorator } from './Decorator'; diff --git a/packages/react-topology/src/components/defs/Defs.tsx b/packages/react-topology/src/components/defs/Defs.tsx deleted file mode 100644 index 71e783d1c68..00000000000 --- a/packages/react-topology/src/components/defs/Defs.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import { DefsState, DefsMap } from './SVGDefsProvider'; -export class Defs extends React.PureComponent<{}, DefsState> { - constructor(props: {}) { - super(props); - this.state = {}; - } - public setDefs(defs: DefsMap) { - // setting the state will re-render this component - this.setState({ defs: { ...defs } }); - } - render() { - const { defs } = this.state; - return defs ? ( - - {Object.keys(defs).map(id => ( - {defs[id].node} - ))} - - ) : null; - } -} diff --git a/packages/react-topology/src/components/defs/SVGDefs.tsx b/packages/react-topology/src/components/defs/SVGDefs.tsx deleted file mode 100644 index f37426ab6b8..00000000000 --- a/packages/react-topology/src/components/defs/SVGDefs.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import SVGDefsContext, { SVGDefsContextProps } from './SVGDefsContext'; -import { SVGDefsSetter } from './SVGDefsSetter'; - -interface SVGDefsProps { - id: string; - children: React.ReactNode; -} - -export type SVGDefsSetterProps = SVGDefsContextProps & SVGDefsProps; - -/** - * Contributes `children` to the parent SVG `` element. - * A contribution is assumed to be static in nature in that the children will never change - * for a given ID. This is because there may be multiple children referencing the same defs contribution. - * The assumption must be that there is not a single owner but many owners and therefore each - * owner must be contributing the same def. - */ -export default class SVGDefs extends React.Component { - shouldComponentUpdate() { - return false; - } - - render() { - return ( - - {({ addDef, removeDef }) => } - - ); - } -} diff --git a/packages/react-topology/src/components/defs/SVGDefsContext.ts b/packages/react-topology/src/components/defs/SVGDefsContext.ts deleted file mode 100644 index cbd57a92d47..00000000000 --- a/packages/react-topology/src/components/defs/SVGDefsContext.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createContext, ReactNode } from 'react'; - -export interface SVGDefsContextProps { - addDef(id: string, node: ReactNode): void; - removeDef(id: string): void; -} - -const SVGDefsContext = createContext(undefined as any); - -export default SVGDefsContext; diff --git a/packages/react-topology/src/components/defs/SVGDefsProvider.tsx b/packages/react-topology/src/components/defs/SVGDefsProvider.tsx deleted file mode 100644 index c8655433f62..00000000000 --- a/packages/react-topology/src/components/defs/SVGDefsProvider.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import SVGDefsContext, { SVGDefsContextProps } from './SVGDefsContext'; -import { Defs } from './Defs'; - -export interface DefsMap { - [id: string]: { - count: number; - node: React.ReactNode; - }; -} - -export interface DefsState { - defs?: DefsMap; -} - -export interface SVGDefsProviderProps { - children?: React.ReactNode; -} - -/** - * Renders a `` element and sets up a {@link SVGDefsContext} provider such that child components - * may contribute to the `` without the parent component needing explicit knowledge of each contribution. - * This helps decouple the parent implementation from the children and ensures that duplicate defs entries, - * such as filters, are eliminated. - */ -class SVGDefsProvider extends React.Component { - private readonly defsRef = React.createRef(); - - private readonly defs: DefsMap = {}; - - private contextValue: SVGDefsContextProps = { - addDef: (id, node) => { - const defObj = this.defs[id]; - if (defObj) { - defObj.count++; - } else { - this.defs[id] = { - count: 1, - node - }; - this.updateDefs(); - } - }, - removeDef: id => { - const defObj = this.defs[id]; - if (--defObj.count === 0) { - delete this.defs[id]; - this.updateDefs(); - } - } - }; - - private updateDefs() { - // Set the defs directly on the child component so that only it will re-render. - // Does not use `setState` because otherwise all child components would be re-renders again - // when only the `Defs` component needs to be rendered. - this.defsRef.current && this.defsRef.current.setDefs(this.defs); - } - - render() { - return ( - - - {this.props.children} - - ); - } -} - -export default SVGDefsProvider; diff --git a/packages/react-topology/src/components/defs/SVGDefsSetter.tsx b/packages/react-topology/src/components/defs/SVGDefsSetter.tsx deleted file mode 100644 index b7b7fe032f9..00000000000 --- a/packages/react-topology/src/components/defs/SVGDefsSetter.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -import SVGDefsContext from './SVGDefsContext'; -import { SVGDefsSetterProps } from './SVGDefs'; -export class SVGDefsSetter extends React.Component { - static displayName = 'SVGDefsSetter'; - static contextType = SVGDefsContext; - context!: React.ContextType; - componentDidMount() { - const { addDef, id, children } = this.props; - addDef(id, children); - } - componentDidUpdate() { - const { addDef, id, children } = this.props; - addDef(id, children); - } - componentWillUnmount() { - const { removeDef, id } = this.props; - removeDef(id); - } - render(): any { - return null; - } -} diff --git a/packages/react-topology/src/components/defs/__mocks__/SVGDefs.tsx b/packages/react-topology/src/components/defs/__mocks__/SVGDefs.tsx deleted file mode 100644 index 13621d7a576..00000000000 --- a/packages/react-topology/src/components/defs/__mocks__/SVGDefs.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import * as React from 'react'; -import SVGDefs from '../SVGDefs'; - -// This mock simply renders the `defs` in place. -const SvgDefsMock: React.FunctionComponent> = ({ id, children }) => ( - {children} -); - -export default SvgDefsMock; diff --git a/packages/react-topology/src/components/defs/__tests__/Defs.test.tsx b/packages/react-topology/src/components/defs/__tests__/Defs.test.tsx deleted file mode 100644 index f808d5a5440..00000000000 --- a/packages/react-topology/src/components/defs/__tests__/Defs.test.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import { Defs } from '../Defs'; - -describe('Defs', () => { - it('should render initially empty', () => { - render( -
- -
- ); - expect(screen.getByTestId('wrapper-test-id').querySelector('defs')).toBeNull(); - }); -}); diff --git a/packages/react-topology/src/components/defs/__tests__/SVGDefs.spec.tsx b/packages/react-topology/src/components/defs/__tests__/SVGDefs.spec.tsx deleted file mode 100644 index a3d053dd13c..00000000000 --- a/packages/react-topology/src/components/defs/__tests__/SVGDefs.spec.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from 'react'; - -import { render } from '@testing-library/react'; - -import SVGDefs, { SVGDefsSetterProps } from '../SVGDefs'; -import SVGDefsContext, { SVGDefsContextProps } from '../SVGDefsContext'; -import { SVGDefsSetter } from '../SVGDefsSetter'; - -describe('SVGDefs', () => { - it('should get #addDef and #removeDef from context', () => { - const contextProps: SVGDefsContextProps = { - addDef: jest.fn(), - removeDef: jest.fn() - }; - const props: React.ComponentProps = { - id: 'foo', - children: - }; - const { unmount } = render( - - - - ); - - // addDef called on mount and removeDef on unmount being called - // signifies the context props were passed into SVGDefs (and therefore SVGDefsSetter). - expect(contextProps.addDef).toHaveBeenCalledWith("foo", ); - - unmount(); - expect(contextProps.removeDef).toHaveBeenLastCalledWith("foo"); - }); - - describe('SVGDefsSetter', () => { - it('should callback #addDef and #removeDef on update', () => { - const props: SVGDefsSetterProps = { - id: 'foo', - addDef: jest.fn(), - removeDef: jest.fn(), - children: , - }; - - const { unmount, rerender } = render(); - expect(props.addDef).toHaveBeenCalledWith(props.id, props.children); - - // test update - const newChild = ; - rerender({newChild}) - expect(props.addDef).toHaveBeenCalledTimes(2); - expect(props.addDef).toHaveBeenLastCalledWith(props.id, newChild); - - // test unmount - unmount(); - expect(props.removeDef).toHaveBeenCalledTimes(1); - expect(props.removeDef).toHaveBeenLastCalledWith(props.id); - }); - }); -}); diff --git a/packages/react-topology/src/components/defs/index.ts b/packages/react-topology/src/components/defs/index.ts deleted file mode 100644 index 6aedd4fe67f..00000000000 --- a/packages/react-topology/src/components/defs/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as SVGDefs } from './SVGDefs'; -export { default as SVGDefsProvider } from './SVGDefsProvider'; diff --git a/packages/react-topology/src/components/edges/DefaultConnectorTag.tsx b/packages/react-topology/src/components/edges/DefaultConnectorTag.tsx deleted file mode 100644 index fb1f3b9c8c0..00000000000 --- a/packages/react-topology/src/components/edges/DefaultConnectorTag.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import * as React from 'react'; -import Point from '../../geom/Point'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { StatusModifier, useSize } from '../../utils'; -import { NodeStatus } from '../../types'; - -interface DefaultConnectorTagProps { - className?: string; - startPoint: Point; - endPoint: Point; - tag: string; - status?: NodeStatus; - paddingX?: number; - paddingY?: number; -} - -const DefaultConnectorTag: React.FunctionComponent = ({ - className, - startPoint, - endPoint, - tag, - status, - paddingX = 4, - paddingY = 2, - ...other -}) => { - const [textSize, textRef] = useSize([tag, className]); - const { width, height, startX, startY } = React.useMemo(() => { - if (!textSize) { - return { - width: 0, - height: 0, - startX: 0, - startY: 0 - }; - } - const width = textSize ? textSize.width + paddingX * 2 : 0; - const height = textSize ? textSize.height + paddingY * 2 : 0; - const startX = -width / 2; - const startY = -height / 2; - return { - width, - height, - startX, - startY - }; - }, [textSize, paddingX, paddingY]); - - return ( - - {textSize && ( - - )} - - {tag} - - - ); -}; - -export default DefaultConnectorTag; diff --git a/packages/react-topology/src/components/edges/DefaultEdge.tsx b/packages/react-topology/src/components/edges/DefaultEdge.tsx deleted file mode 100644 index 7aab014f44b..00000000000 --- a/packages/react-topology/src/components/edges/DefaultEdge.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import * as React from 'react'; -import * as _ from 'lodash'; -import { observer } from 'mobx-react'; -import { Edge, EdgeTerminalType, NodeStatus } from '../../types'; -import { ConnectDragSource, OnSelect } from '../../behavior'; -import { useHover } from '../../utils'; -import { Layer } from '../layers'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { getEdgeAnimationDuration, getEdgeStyleClassModifier } from '../../utils/style-utils'; -import DefaultConnectorTerminal from './terminals/DefaultConnectorTerminal'; -import { TOP_LAYER } from '../../const'; -import DefaultConnectorTag from './DefaultConnectorTag'; -import { Point } from '../../geom'; -import { getConnectorStartPoint } from './terminals/terminalUtils'; - -interface DefaultEdgeProps { - /** Additional content added to the edge */ - children?: React.ReactNode; - /** Additional classes added to the edge */ - className?: string; - /** The graph edge element to represent */ - element: Edge; - /** Flag indicating if the user is dragging the edge */ - dragging?: boolean; - /** The duration in seconds for the edge animation. Defaults to the animationSpeed set on the Edge's model */ - animationDuration?: number; - /** The terminal type to use for the edge start */ - startTerminalType?: EdgeTerminalType; - /** Additional classes added to the start terminal */ - startTerminalClass?: string; - /** The status to indicate on the start terminal */ - startTerminalStatus?: NodeStatus; - /** The size of the start terminal */ - startTerminalSize?: number; - /** The terminal type to use for the edge end */ - endTerminalType?: EdgeTerminalType; - /** Additional classes added to the end terminal */ - endTerminalClass?: string; - /** The status to indicate on the end terminal */ - endTerminalStatus?: NodeStatus; - /** The size of the end terminal */ - endTerminalSize?: number; - /** Tag to show for the terminal */ - tag?: string; - /** Additional classes added to the tag */ - tagClass?: string; - /** The status to indicate on the tag */ - tagStatus?: NodeStatus; - /** Function to call for showing a remove indicator on the edge. Part of WithRemoveConnectorProps */ - onShowRemoveConnector?: () => void; - /** Function to call for removing the remove indicator on the edge. Part of WithRemoveConnectorProps */ - onHideRemoveConnector?: () => void; - /** Ref to use to start the drag of the start of the edge. Part of WithSourceDragProps */ - sourceDragRef?: ConnectDragSource; - /** Ref to use to start the drag of the end of the edge. Part of WithTargetDragProps */ - targetDragRef?: ConnectDragSource; - /** Flag indicating if the element is selected. Part of WithSelectionProps */ - selected?: boolean; - /** Function to call when the element should become selected (or deselected). Part of WithSelectionProps */ - onSelect?: OnSelect; - /** Function to call to show a context menu for the edge */ - onContextMenu?: (e: React.MouseEvent) => void; - /** Flag indicating that the context menu for the edge is currently open */ - contextMenuOpen?: boolean; -} - -const DefaultEdge: React.FunctionComponent = ({ - element, - dragging, - sourceDragRef, - targetDragRef, - animationDuration, - onShowRemoveConnector, - onHideRemoveConnector, - startTerminalType = EdgeTerminalType.none, - startTerminalClass, - startTerminalStatus, - startTerminalSize = 14, - endTerminalType = EdgeTerminalType.directional, - endTerminalClass, - endTerminalStatus, - endTerminalSize = 14, - tag, - tagClass, - tagStatus, - children, - className, - selected, - onSelect, - onContextMenu -}: DefaultEdgeProps) => { - const [hover, hoverRef] = useHover(); - const startPoint = element.getStartPoint(); - const endPoint = element.getEndPoint(); - - // eslint-disable-next-line patternfly-react/no-layout-effect - React.useLayoutEffect(() => { - if (hover && !dragging) { - onShowRemoveConnector && onShowRemoveConnector(); - } else { - onHideRemoveConnector && onHideRemoveConnector(); - } - }, [hover, dragging, onShowRemoveConnector, onHideRemoveConnector]); - - const groupClassName = css( - styles.topologyEdge, - className, - dragging && 'pf-m-dragging', - hover && !dragging && 'pf-m-hover', - selected && !dragging && 'pf-m-selected' - ); - - const edgeAnimationDuration = animationDuration ?? getEdgeAnimationDuration(element.getEdgeAnimationSpeed()); - const linkClassName = css(styles.topologyEdgeLink, getEdgeStyleClassModifier(element.getEdgeStyle())); - - const bendpoints = element.getBendpoints(); - - const d = `M${startPoint.x} ${startPoint.y} ${bendpoints.map((b: Point) => `L${b.x} ${b.y} `).join('')}L${ - endPoint.x - } ${endPoint.y}`; - - const bgStartPoint = - !startTerminalType || startTerminalType === EdgeTerminalType.none - ? [startPoint.x, startPoint.y] - : getConnectorStartPoint(_.head(bendpoints) || endPoint, startPoint, startTerminalSize); - const bgEndPoint = - !endTerminalType || endTerminalType === EdgeTerminalType.none - ? [endPoint.x, endPoint.y] - : getConnectorStartPoint(_.last(bendpoints) || startPoint, endPoint, endTerminalSize); - const backgroundPath = `M${bgStartPoint[0]} ${bgStartPoint[1]} ${bendpoints - .map((b: Point) => `L${b.x} ${b.y} `) - .join('')}L${bgEndPoint[0]} ${bgEndPoint[1]}`; - - return ( - - - - - {tag && ( - - )} - - - {children} - - - ); -}; - -export default observer(DefaultEdge); diff --git a/packages/react-topology/src/components/edges/index.ts b/packages/react-topology/src/components/edges/index.ts deleted file mode 100644 index 5af71c91dc1..00000000000 --- a/packages/react-topology/src/components/edges/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as DefaultEdge } from './DefaultEdge'; -export { default as DefaultConntectorTag } from './DefaultConnectorTag'; -export * from './terminals'; diff --git a/packages/react-topology/src/components/edges/terminals/ConnectorArrow.tsx b/packages/react-topology/src/components/edges/terminals/ConnectorArrow.tsx deleted file mode 100644 index e9c4f1fbe9a..00000000000 --- a/packages/react-topology/src/components/edges/terminals/ConnectorArrow.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import * as React from 'react'; -import * as _ from 'lodash'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import Point from '../../../geom/Point'; -import { ConnectDragSource } from '../../../behavior/dnd-types'; -import { getConnectorStartPoint, getConnectorRotationAngle, getConnectorBoundingBox } from './terminalUtils'; - -interface ConnectorArrowProps { - startPoint: Point; - endPoint: Point; - className?: string; - isTarget?: boolean; - size?: number; - dragRef?: ConnectDragSource; -} - -const pointsStringFromPoints = (points: [number, number][]): string => - _.reduce(points, (result: string, nextPoint: [number, number]) => `${result} ${nextPoint[0]},${nextPoint[1]}`, ''); - -const ConnectorArrow: React.FunctionComponent = ({ - startPoint, - endPoint, - className = '', - size = 14, - dragRef -}) => { - const polygonPoints = React.useMemo( - () => - pointsStringFromPoints([ - [0, size / 2], - [0, -size / 2], - [size, 0] - ]), - [size] - ); - - const boundingPoints = React.useMemo(() => { - if (startPoint || !endPoint) { - return null; - } - return pointsStringFromPoints(getConnectorBoundingBox(startPoint, endPoint, size)); - }, [endPoint, size, startPoint]); - - if (!startPoint || !endPoint) { - return null; - } - - const connectorStartPoint = getConnectorStartPoint(startPoint, endPoint, size); - const angleDeg = getConnectorRotationAngle(startPoint, endPoint); - - const classNames = css(styles.topologyConnectorArrow, className, dragRef && 'pf-m-draggable'); - - return ( - - - - - ); -}; - -export default ConnectorArrow; diff --git a/packages/react-topology/src/components/edges/terminals/ConnectorArrowAlt.tsx b/packages/react-topology/src/components/edges/terminals/ConnectorArrowAlt.tsx deleted file mode 100644 index efa6f013744..00000000000 --- a/packages/react-topology/src/components/edges/terminals/ConnectorArrowAlt.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import Point from '../../../geom/Point'; -import { ConnectDragSource } from '../../../behavior/dnd-types'; -import ConnectorArrow from './ConnectorArrow'; - -interface ConnectorArrowAltProps { - startPoint: Point; - endPoint: Point; - className?: string; - isTarget?: boolean; - size?: number; - dragRef?: ConnectDragSource; -} - -const ConnectorArrowAlt: React.FunctionComponent = ({ - startPoint, - endPoint, - className = '', - size, - dragRef -}) => { - const classes = css( - styles.topologyConnectorArrow, - styles.modifiers.altConnectorArrow, - className, - dragRef && 'pf-m-draggable' - ); - return ( - - ); -}; - -export default ConnectorArrowAlt; diff --git a/packages/react-topology/src/components/edges/terminals/ConnectorCircle.tsx b/packages/react-topology/src/components/edges/terminals/ConnectorCircle.tsx deleted file mode 100644 index 460a3065b56..00000000000 --- a/packages/react-topology/src/components/edges/terminals/ConnectorCircle.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import Point from '../../../geom/Point'; -import { ConnectDragSource } from '../../../behavior/dnd-types'; -import { getConnectorStartPoint } from './terminalUtils'; - -interface ConnectorCircleProps { - startPoint: Point; - endPoint: Point; - className?: string; - isTarget?: boolean; - size?: number; - dragRef?: ConnectDragSource; -} - -const ConnectorCircle: React.FunctionComponent = ({ - startPoint, - endPoint, - className = '', - isTarget = true, - size = 14, - dragRef -}) => { - if (!startPoint || !endPoint) { - return null; - } - - const connectorStartPoint = getConnectorStartPoint(startPoint, endPoint, size / 2); // add stroke width rather than rotating - const classNames = css( - styles.topologyConnectorArrow, - styles.topologyConnectorCircle, - className, - !isTarget && styles.modifiers.source, - dragRef && 'pf-m-draggable' - ); - - return ( - - - - ); -}; - -export default ConnectorCircle; diff --git a/packages/react-topology/src/components/edges/terminals/ConnectorCross.tsx b/packages/react-topology/src/components/edges/terminals/ConnectorCross.tsx deleted file mode 100644 index e0127f75333..00000000000 --- a/packages/react-topology/src/components/edges/terminals/ConnectorCross.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import Point from '../../../geom/Point'; -import { ConnectDragSource } from '../../../behavior/dnd-types'; -import { getConnectorRotationAngle, getConnectorStartPoint } from './terminalUtils'; - -interface ConnectorCrossProps { - startPoint: Point; - endPoint: Point; - className?: string; - isTarget?: boolean; - size?: number; - dragRef?: ConnectDragSource; -} - -const ConnectorCross: React.FunctionComponent = ({ - startPoint, - endPoint, - className = '', - isTarget = true, - size = 14, - dragRef -}) => { - if (!startPoint || !endPoint) { - return null; - } - - const width = size / 4; - const yDelta = size / 2; - const connectorStartPoint = getConnectorStartPoint(startPoint, endPoint, size); - const angleDeg = getConnectorRotationAngle(startPoint, endPoint); - - const classNames = css( - styles.topologyConnectorArrow, - styles.topologyConnectorCross, - className, - !isTarget && 'pf-m-source', - dragRef && 'pf-m-draggable' - ); - - return ( - - - {isTarget ? ( - <> - - - - ) : ( - - )} - - ); -}; - -export default ConnectorCross; diff --git a/packages/react-topology/src/components/edges/terminals/ConnectorSquare.tsx b/packages/react-topology/src/components/edges/terminals/ConnectorSquare.tsx deleted file mode 100644 index 8ce4be97b56..00000000000 --- a/packages/react-topology/src/components/edges/terminals/ConnectorSquare.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import Point from '../../../geom/Point'; -import { ConnectDragSource } from '../../../behavior/dnd-types'; -import { getConnectorRotationAngle, getConnectorStartPoint } from './terminalUtils'; - -interface ConnectorSquareProps { - startPoint: Point; - endPoint: Point; - className?: string; - isTarget?: boolean; - size?: number; - dragRef?: ConnectDragSource; -} - -const ConnectorSquare: React.FunctionComponent = ({ - startPoint, - endPoint, - className = '', - isTarget = true, - size = 14, - dragRef -}) => { - if (!startPoint || !endPoint) { - return null; - } - - const connectorStartPoint = getConnectorStartPoint(startPoint, endPoint, size); - const angleDeg = getConnectorRotationAngle(startPoint, endPoint); - const classNames = css( - styles.topologyConnectorArrow, - styles.topologyConnectorSquare, - !isTarget && styles.modifiers.source, - className, - dragRef && 'pf-m-draggable' - ); - - return ( - - - - ); -}; - -export default ConnectorSquare; diff --git a/packages/react-topology/src/components/edges/terminals/DefaultConnectorTerminal.tsx b/packages/react-topology/src/components/edges/terminals/DefaultConnectorTerminal.tsx deleted file mode 100644 index ac7acb7e449..00000000000 --- a/packages/react-topology/src/components/edges/terminals/DefaultConnectorTerminal.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import * as _ from 'lodash'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { Edge, EdgeTerminalType, NodeStatus } from '../../../types'; -import { ConnectDragSource } from '../../../behavior/dnd-types'; -import ConnectorArrow from './ConnectorArrow'; -import ConnectorCross from './ConnectorCross'; -import ConnectorSquare from './ConnectorSquare'; -import ConnectorCircle from './ConnectorCircle'; -import ConnectorArrowAlt from './ConnectorArrowAlt'; -import { StatusModifier } from '../../../utils'; - -interface EdgeConnectorArrowProps { - edge: Edge; - className?: string; - highlight?: boolean; - isTarget?: boolean; - status?: NodeStatus; - terminalType?: EdgeTerminalType; - size?: number; - dragRef?: ConnectDragSource; -} - -const DefaultConnectorTerminal: React.FunctionComponent = ({ - className, - edge, - isTarget = true, - terminalType, - status, - ...others -}) => { - let Terminal; - switch (terminalType) { - case EdgeTerminalType.directional: - Terminal = ConnectorArrow; - break; - case EdgeTerminalType.directionalAlt: - Terminal = ConnectorArrowAlt; - break; - case EdgeTerminalType.cross: - Terminal = ConnectorCross; - break; - case EdgeTerminalType.square: - Terminal = ConnectorSquare; - break; - case EdgeTerminalType.circle: - Terminal = ConnectorCircle; - break; - default: - return null; - } - if (!Terminal) { - return null; - } - const bendPoints = edge.getBendpoints(); - const startPoint = isTarget ? _.last(bendPoints) || edge.getStartPoint() : _.head(bendPoints) || edge.getEndPoint(); - const endPoint = isTarget ? edge.getEndPoint() : edge.getStartPoint(); - const classes = css(styles.topologyEdge, className, StatusModifier[status]); - - return ; -}; - -export default observer(DefaultConnectorTerminal); diff --git a/packages/react-topology/src/components/edges/terminals/index.ts b/packages/react-topology/src/components/edges/terminals/index.ts deleted file mode 100644 index 0ea0319d728..00000000000 --- a/packages/react-topology/src/components/edges/terminals/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { default as ConnectorArrow } from './ConnectorArrow'; -export { default as ConnectorArrowAlt } from './ConnectorArrowAlt'; -export { default as ConnectorCircle } from './ConnectorCircle'; -export { default as ConnectorCross } from './ConnectorCross'; -export { default as ConnectorSquare } from './ConnectorSquare'; -export { default as DefaultConnectorTerminal } from './DefaultConnectorTerminal'; -export { default as EdgeConnectorArrow } from './DefaultConnectorTerminal'; // Backwards compatibility diff --git a/packages/react-topology/src/components/edges/terminals/terminalUtils.ts b/packages/react-topology/src/components/edges/terminals/terminalUtils.ts deleted file mode 100644 index 0846527d137..00000000000 --- a/packages/react-topology/src/components/edges/terminals/terminalUtils.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Point } from '../../../geom'; - -export const getConnectorStartPoint = (startPoint: Point, endPoint: Point, size: number): [number, number] => { - const length = Math.sqrt((endPoint.x - startPoint.x) ** 2 + (endPoint.y - startPoint.y) ** 2); - if (!length) { - return [0, 0]; - } - const ratio = (length - size) / length; - - return [startPoint.x + (endPoint.x - startPoint.x) * ratio, startPoint.y + (endPoint.y - startPoint.y) * ratio]; -}; - -export const getConnectorRotationAngle = (startPoint: Point, endPoint: Point): number => - 180 - (Math.atan2(endPoint.y - startPoint.y, startPoint.x - endPoint.x) * 180) / Math.PI; - -export const getConnectorBoundingBox = (startPoint: Point, endPoint: Point, size: number): [number, number][] => { - const length = Math.sqrt((endPoint.x - startPoint.x) ** 2 + (endPoint.y - startPoint.y) ** 2); - if (!length) { - return null; - } - - const padding = Math.max(size, 8); - const deltaY = padding / 2; - return [ - [0, -deltaY], - [padding, -deltaY], - [padding, deltaY], - [0, deltaY] - ]; -}; diff --git a/packages/react-topology/src/components/factories/RegisterComponentFactory.tsx b/packages/react-topology/src/components/factories/RegisterComponentFactory.tsx deleted file mode 100644 index e5f4535b05f..00000000000 --- a/packages/react-topology/src/components/factories/RegisterComponentFactory.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import useComponentFactory from '../../hooks/useComponentFactory'; -import { ComponentFactory } from '../../types'; - -interface Props { - factory: ComponentFactory; -} - -const RegisterComponentFactory: React.FunctionComponent = ({ factory }) => { - useComponentFactory(factory); - return null; -}; - -export default RegisterComponentFactory; diff --git a/packages/react-topology/src/components/factories/RegisterElementFactory.tsx b/packages/react-topology/src/components/factories/RegisterElementFactory.tsx deleted file mode 100644 index aa95807a2b1..00000000000 --- a/packages/react-topology/src/components/factories/RegisterElementFactory.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import useElementFactory from '../../hooks/useElementFactory'; -import { ElementFactory } from '../../types'; - -interface Props { - factory: ElementFactory; -} - -const RegisteElementFactory: React.FunctionComponent = ({ factory }) => { - useElementFactory(factory); - return null; -}; - -export default RegisteElementFactory; diff --git a/packages/react-topology/src/components/factories/RegisterLayoutFactory.tsx b/packages/react-topology/src/components/factories/RegisterLayoutFactory.tsx deleted file mode 100644 index 8f4043f473c..00000000000 --- a/packages/react-topology/src/components/factories/RegisterLayoutFactory.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import useLayoutFactory from '../../hooks/useLayoutFactory'; -import { LayoutFactory } from '../../types'; - -interface Props { - factory: LayoutFactory; -} - -const RegisterLayoutFactory: React.FunctionComponent = ({ factory }) => { - useLayoutFactory(factory); - return null; -}; - -export default RegisterLayoutFactory; diff --git a/packages/react-topology/src/components/factories/components/componentUtils.ts b/packages/react-topology/src/components/factories/components/componentUtils.ts deleted file mode 100644 index 57d54551ecf..00000000000 --- a/packages/react-topology/src/components/factories/components/componentUtils.ts +++ /dev/null @@ -1,289 +0,0 @@ -import { action } from 'mobx'; -import { Edge, Graph, GraphElement, isEdge, Node } from '../../../types'; -import { - CREATE_CONNECTOR_DROP_TYPE, - CREATE_CONNECTOR_OPERATION, - DragObjectWithType, - DragOperationWithType, - DragSourceSpec, - DragSpecOperationType, - DropTargetMonitor, - DropTargetSpec, - Modifiers, - TargetType -} from '../../../behavior'; - -const MOVE_CONNECTOR_DROP_TYPE = '#moveConnector#'; - -const NODE_DRAG_TYPE = '#node#'; -const EDGE_DRAG_TYPE = '#edge#'; - -const MOVE_CONNECTOR_OPERATION = 'moveconnector'; -const REGROUP_OPERATION = 'regroup'; - -export interface GraphComponentProps { - element: Graph; -} - -export interface NodeComponentProps { - element: Node; -} - -export interface EdgeComponentProps { - element: Edge; -} - -/** - * type: the drag operation type - * edit: true if the operation performs an edit, used to dim invalid drop targets - * canDropOnNode: true if the drag object can be dropped on node, used to highlight valid drop nodes - */ -export type EditableDragOperationType = DragOperationWithType & { - edit?: boolean; - canDropOnNode?: (operationType: string, dragElement: GraphElement, node: Node) => boolean; -}; - -export interface DragNodeObject { - element: GraphElement; - allowRegroup: boolean; -} - -const canDropEdgeOnNode = (operation: string, element: GraphElement, node: Node): boolean => { - if (!isEdge(element)) { - return false; - } - const edge = element as Edge; - if (edge.getSource() === node) { - return false; - } - - if (edge.getTarget() === node) { - return true; - } - - return !node.getTargetEdges().find(e => e.getSource() === edge.getSource()); -}; - -const highlightNode = (monitor: DropTargetMonitor, element: Node): boolean => { - const operation = monitor.getOperation() as EditableDragOperationType; - if (!monitor.isDragging() || !operation) { - return false; - } - - if (operation.type === CREATE_CONNECTOR_OPERATION) { - return ( - monitor.getItem() !== element && - monitor.getItem().getParent() !== element && - !monitor - .getItem() - .getSourceEdges() - .find((e: Edge) => e.getTarget() === element) - ); - } - - return operation.canDropOnNode && operation.canDropOnNode(operation.type, monitor.getItem(), element); -}; - -const nodeDragSourceSpec = ( - type: string, - allowRegroup: boolean = true, - canEdit: boolean = false -): DragSourceSpec< - DragObjectWithType, - DragSpecOperationType, - Node, - { - dragging?: boolean; - regrouping?: boolean; - }, - NodeComponentProps & { canEdit?: boolean } -> => ({ - item: { type: NODE_DRAG_TYPE }, - operation: (monitor, props) => - (canEdit || props.canEdit) && allowRegroup - ? { - [Modifiers.SHIFT]: { type: REGROUP_OPERATION, edit: true } - } - : undefined, - canCancel: monitor => monitor.getOperation()?.type === REGROUP_OPERATION, - begin: (monitor, props): DragNodeObject => ({ - element: props.element, - allowRegroup: (canEdit || props.canEdit) && allowRegroup - }), - end: async (dropResult, monitor, props) => { - if (!monitor.isCancelled() && monitor.getOperation()?.type === REGROUP_OPERATION) { - if (monitor.didDrop() && dropResult && props && props.element.getParent() !== dropResult) { - const controller = props.element.getController(); - - // perform the update in an action so as not to render too soon - action(() => { - if (controller.getNodeById(props.element.getId())) { - dropResult.appendChild(props.element); - } - })(); - } else { - // cancel operation - return Promise.reject(); - } - } - return undefined; - }, - collect: monitor => ({ - dragging: monitor.isDragging(), - regrouping: monitor.getOperation()?.type === REGROUP_OPERATION - }) -}); - -const noRegroupDragSourceSpec: DragSourceSpec< - DragObjectWithType, - DragSpecOperationType, - Node, - { - dragging?: boolean; - }, - NodeComponentProps -> = { - item: { type: NODE_DRAG_TYPE }, - collect: monitor => ({ - dragging: monitor.isDragging() - }) -}; - -const nodesEdgeIsDragging = (monitor: any, props: NodeComponentProps) => { - if (!monitor.isDragging()) { - return false; - } - if (monitor.getOperation() === MOVE_CONNECTOR_OPERATION) { - return monitor.getItem().getSource() === props.element; - } - if (monitor.getOperation() === CREATE_CONNECTOR_OPERATION) { - return monitor.getItem() === props.element; - } - return false; -}; - -const nodeDropTargetSpec = ( - accept?: TargetType -): DropTargetSpec< - GraphElement, - any, - { canDrop: boolean; dropTarget: boolean; edgeDragging: boolean }, - NodeComponentProps -> => ({ - accept: accept || [EDGE_DRAG_TYPE, CREATE_CONNECTOR_DROP_TYPE], - canDrop: (item, monitor, props) => { - if (isEdge(item)) { - return canDropEdgeOnNode(monitor.getOperation()?.type, item as Edge, props.element); - } - if (item === props.element) { - return false; - } - return !props.element.getTargetEdges().find(e => e.getSource() === item); - }, - collect: (monitor, props) => ({ - canDrop: highlightNode(monitor, props.element), - dropTarget: monitor.isOver({ shallow: true }), - edgeDragging: nodesEdgeIsDragging(monitor, props) - }) -}); - -const graphDropTargetSpec = ( - accept?: TargetType -): DropTargetSpec => ({ - accept: accept || [NODE_DRAG_TYPE, EDGE_DRAG_TYPE, CREATE_CONNECTOR_DROP_TYPE], - hitTest: () => true, - canDrop: (item, monitor, props) => - monitor.isOver({ shallow: monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE }) && - ((monitor.getOperation()?.type === REGROUP_OPERATION && - // FIXME: the hasParent check is necessary due to model updates during async actions - item.element.hasParent() && - item.element.getParent() !== props.element) || - monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE), - collect: monitor => { - const operation = monitor.getOperation() as EditableDragOperationType; - const dragEditInProgress = - monitor.isDragging() && (operation?.type === CREATE_CONNECTOR_OPERATION || operation?.edit); - const dragCreate = - dragEditInProgress && - (monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE || monitor.getItemType() === MOVE_CONNECTOR_DROP_TYPE); - return { - dragEditInProgress, - dragCreate, - hasDropTarget: dragEditInProgress && monitor.hasDropTarget() - }; - }, - dropHint: 'create' -}); - -const groupDropTargetSpec: DropTargetSpec< - any, - any, - { droppable: boolean; dropTarget: boolean; canDrop: boolean }, - any -> = { - accept: [NODE_DRAG_TYPE, EDGE_DRAG_TYPE, CREATE_CONNECTOR_DROP_TYPE], - canDrop: (item, monitor) => - monitor.isOver({ shallow: monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE }) && - (monitor.getOperation()?.type === REGROUP_OPERATION || monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE), - collect: monitor => ({ - droppable: monitor.isDragging() && monitor.getOperation()?.type === REGROUP_OPERATION, - dropTarget: monitor.isOver({ shallow: monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE }), - canDrop: - monitor.isDragging() && - (monitor.getOperation()?.type === REGROUP_OPERATION || monitor.getItemType() === CREATE_CONNECTOR_DROP_TYPE), - dragRegroupable: monitor.isDragging() && monitor.getItem()?.allowRegroup - }), - dropHint: 'create' -}; - -const edgeDragSourceSpec = ( - type: string, - callback: (sourceNode: Node, targetNode: Node, replaceTargetNode?: Node) => void -): DragSourceSpec< - DragObjectWithType, - DragSpecOperationType, - Node, - { dragging: boolean }, - EdgeComponentProps -> => ({ - item: { type: EDGE_DRAG_TYPE }, - operation: { type: MOVE_CONNECTOR_OPERATION, edit: true, canDropOnNode: canDropEdgeOnNode }, - begin: (monitor, props) => { - props.element.raise(); - return props.element; - }, - drag: (event, monitor, props) => { - props.element.setEndPoint(event.x, event.y); - }, - end: (dropResult, monitor, props) => { - props.element.setEndPoint(); - if (monitor.didDrop() && dropResult && canDropEdgeOnNode(monitor.getOperation()?.type, props.element, dropResult)) { - callback(props.element.getSource(), dropResult, props.element.getTarget()); - } - }, - collect: monitor => ({ - dragging: monitor.isDragging() - }) -}); - -const noDropTargetSpec: DropTargetSpec = { - accept: [NODE_DRAG_TYPE, EDGE_DRAG_TYPE, CREATE_CONNECTOR_DROP_TYPE], - canDrop: () => false -}; - -export { - nodesEdgeIsDragging, - noRegroupDragSourceSpec, - nodeDragSourceSpec, - nodeDropTargetSpec, - graphDropTargetSpec, - groupDropTargetSpec, - edgeDragSourceSpec, - noDropTargetSpec, - REGROUP_OPERATION, - MOVE_CONNECTOR_DROP_TYPE, - NODE_DRAG_TYPE, - EDGE_DRAG_TYPE, - canDropEdgeOnNode, - highlightNode -}; diff --git a/packages/react-topology/src/components/factories/components/index.ts b/packages/react-topology/src/components/factories/components/index.ts deleted file mode 100644 index c92142b68bc..00000000000 --- a/packages/react-topology/src/components/factories/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './componentUtils'; diff --git a/packages/react-topology/src/components/factories/index.ts b/packages/react-topology/src/components/factories/index.ts deleted file mode 100644 index 34429b36729..00000000000 --- a/packages/react-topology/src/components/factories/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { default as RegisterComponentFactory } from './RegisterComponentFactory'; -export { default as RegisterElementFactory } from './RegisterElementFactory'; -export { default as RegisterLayoutFactory } from './RegisterLayoutFactory'; -export * from './components'; diff --git a/packages/react-topology/src/components/groups/CollapsedGroupAnchor.ts b/packages/react-topology/src/components/groups/CollapsedGroupAnchor.ts deleted file mode 100644 index a5cb6009ccc..00000000000 --- a/packages/react-topology/src/components/groups/CollapsedGroupAnchor.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Node } from '../../types'; -import { AbstractAnchor } from '../../anchors'; -import { Point } from '../../geom'; -import { getRectAnchorPoint } from '../../utils'; - -class CollapsedGroupAnchor extends AbstractAnchor { - protected readonly width: number; - - protected readonly height: number; - - constructor(owner: Node, width: number, height: number, offset: number = 0) { - super(owner, offset); - this.width = width; - this.height = height; - } - - getLocation(reference: Point): Point { - const center = new Point(this.owner.getPosition().x + this.width / 2, this.owner.getPosition().y + this.height / 2); - - const offset2x = this.offset * 2; - return getRectAnchorPoint(center, this.width + offset2x, this.height + offset2x, reference); - } -} - -export default CollapsedGroupAnchor; diff --git a/packages/react-topology/src/components/groups/DefaultGroup.tsx b/packages/react-topology/src/components/groups/DefaultGroup.tsx deleted file mode 100644 index efd0bf82504..00000000000 --- a/packages/react-topology/src/components/groups/DefaultGroup.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import DefaultGroupExpanded from './DefaultGroupExpanded'; -import { WithContextMenuProps, WithDndDropProps, WithSelectionProps, WithDragNodeProps } from '../../behavior'; -import { BadgeLocation, LabelPosition, Node } from '../../types'; -import DefaultGroupCollapsed from './DefaultGroupCollapsed'; -import { CollapsibleGroupProps } from './types'; - -type DefaultGroupProps = { - className?: string; - element: Node; - droppable?: boolean; - canDrop?: boolean; - dropTarget?: boolean; - dragging?: boolean; - dragRegroupable?: boolean; - hover?: boolean; - label?: string; // Defaults to element.getLabel() - secondaryLabel?: string; - showLabel?: boolean; // Defaults to true - labelPosition?: LabelPosition; // Defaults to bottom - truncateLength?: number; // Defaults to 13 - labelIconClass?: string; // Icon to show in label - labelIcon?: string; - labelIconPadding?: number; - badge?: string; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; -} & Partial; - -const DefaultGroup: React.FunctionComponent = ({ - className, - element, - onCollapseChange, - ...rest -}) => { - const handleCollapse = (group: Node, collapsed: boolean): void => { - if (collapsed && rest.collapsedWidth !== undefined && rest.collapsedHeight !== undefined) { - group.setBounds(group.getBounds().setSize(rest.collapsedWidth, rest.collapsedHeight)); - } - group.setCollapsed(collapsed); - onCollapseChange && onCollapseChange(group, collapsed); - }; - - if (element.isCollapsed()) { - return ( - - ); - } - return ; -}; - -export default observer(DefaultGroup); diff --git a/packages/react-topology/src/components/groups/DefaultGroupCollapsed.tsx b/packages/react-topology/src/components/groups/DefaultGroupCollapsed.tsx deleted file mode 100644 index 00b3ead3196..00000000000 --- a/packages/react-topology/src/components/groups/DefaultGroupCollapsed.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-alt-icon'; -import { Layer } from '../layers'; -import { GROUPS_LAYER } from '../../const'; -import { createSvgIdUrl, useCombineRefs, useHover, useSize } from '../../utils'; -import { BadgeLocation, LabelPosition, Node } from '../../types'; -import { - useDragNode, - WithContextMenuProps, - WithDndDropProps, - WithDragNodeProps, - WithSelectionProps -} from '../../behavior'; -import { Ellipse } from '../nodes/shapes'; -import NodeLabel from '../nodes/labels/NodeLabel'; -import { NODE_SHADOW_FILTER_ID_HOVER } from '../nodes/NodeShadows'; -import LabelBadge from '../nodes/labels/LabelBadge'; -import { CollapsibleGroupProps } from './types'; - -type DefaultGroupCollapsedProps = { - children?: React.ReactNode; - className?: string; - element: Node; - droppable?: boolean; - canDrop?: boolean; - dropTarget?: boolean; - dragging?: boolean; - hover?: boolean; - label?: string; // Defaults to element.getLabel() - secondaryLabel?: string; - showLabel?: boolean; // Defaults to true - labelPosition?: LabelPosition; // Defaults to bottom - truncateLength?: number; // Defaults to 13 - labelIconClass?: string; // Icon to show in label - labelIcon?: string; - labelIconPadding?: number; - badge?: string; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; -} & Partial; - -const DefaultGroupCollapsed: React.FunctionComponent = ({ - className, - element, - collapsible, - selected, - onSelect, - children, - hover, - label, - secondaryLabel, - showLabel = true, - truncateLength, - collapsedWidth, - collapsedHeight, - getCollapsedShape, - onCollapseChange, - collapsedShadowOffset = 8, - dndDropRef, - dragNodeRef, - canDrop, - dropTarget, - onContextMenu, - contextMenuOpen, - dragging, - labelPosition, - badge, - badgeColor, - badgeTextColor, - badgeBorderColor, - badgeClassName, - badgeLocation, - labelIconClass, - labelIcon, - labelIconPadding -}) => { - const [hovered, hoverRef] = useHover(); - const [labelHover, labelHoverRef] = useHover(); - const dragLabelRef = useDragNode()[1]; - const [shapeSize, shapeRef] = useSize([collapsedWidth, collapsedHeight]); - const refs = useCombineRefs(hoverRef, dragNodeRef, shapeRef); - const isHover = hover !== undefined ? hover : hovered; - const childCount = element.getAllNodeChildren().length; - const [badgeSize, badgeRef] = useSize([childCount]); - - const groupClassName = css( - styles.topologyGroup, - className, - canDrop && 'pf-m-highlight', - canDrop && dropTarget && 'pf-m-drop-target', - dragging && 'pf-m-dragging', - selected && 'pf-m-selected' - ); - - const ShapeComponent = getCollapsedShape ? getCollapsedShape(element) : Ellipse; - const filter = isHover || dragging || dropTarget ? createSvgIdUrl(NODE_SHADOW_FILTER_ID_HOVER) : undefined; - - return ( - - - - {ShapeComponent && ( - <> - - - - - - - - - )} - - - {shapeSize && childCount && ( - - )} - {showLabel && ( - : undefined} - onActionIconClick={() => onCollapseChange(element, false)} - > - {label || element.getLabel()} - - )} - {children} - - ); -}; - -export default observer(DefaultGroupCollapsed); diff --git a/packages/react-topology/src/components/groups/DefaultGroupExpanded.tsx b/packages/react-topology/src/components/groups/DefaultGroupExpanded.tsx deleted file mode 100644 index 668acf8da9a..00000000000 --- a/packages/react-topology/src/components/groups/DefaultGroupExpanded.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { polygonHull } from 'd3-polygon'; -import * as _ from 'lodash'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import CollapseIcon from '@patternfly/react-icons/dist/esm/icons/compress-alt-icon'; -import NodeLabel from '../nodes/labels/NodeLabel'; -import { Layer } from '../layers'; -import { GROUPS_LAYER } from '../../const'; -import { hullPath, maxPadding, useCombineRefs, useHover } from '../../utils'; -import { BadgeLocation, isGraph, Node, NodeShape, NodeStyle, PointTuple } from '../../types'; -import { - useDragNode, - useSvgAnchor, - WithContextMenuProps, - WithDndDropProps, - WithDragNodeProps, - WithSelectionProps -} from '../../behavior'; -import { CollapsibleGroupProps } from './types'; - -type DefaultGroupExpandedProps = { - className?: string; - element: Node; - droppable?: boolean; - canDrop?: boolean; - dropTarget?: boolean; - dragging?: boolean; - hover?: boolean; - label?: string; // Defaults to element.getLabel() - secondaryLabel?: string; - showLabel?: boolean; // Defaults to true - truncateLength?: number; // Defaults to 13 - badge?: string; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; - labelIconClass?: string; // Icon to show in label - labelIcon?: string; - labelIconPadding?: number; -} & Partial; - -type PointWithSize = [number, number, number]; - -// Return the point whose Y is the largest value. -// If multiple points are found, compute the center X between them -// export for testing only -export function computeLabelLocation(points: PointWithSize[]): PointWithSize { - let lowPoints: PointWithSize[]; - const threshold = 5; - - _.forEach(points, p => { - const delta = !lowPoints ? Infinity : Math.round(p[1]) - Math.round(lowPoints[0][1]); - if (delta > threshold) { - lowPoints = [p]; - } else if (Math.abs(delta) <= threshold) { - lowPoints.push(p); - } - }); - return [ - (_.minBy(lowPoints, p => p[0])[0] + _.maxBy(lowPoints, p => p[0])[0]) / 2, - lowPoints[0][1], - // use the max size value - _.maxBy(lowPoints, p => p[2])[2] - ]; -} - -const DefaultGroupExpanded: React.FunctionComponent = ({ - className, - element, - collapsible, - selected, - onSelect, - hover, - label, - secondaryLabel, - showLabel = true, - truncateLength, - dndDropRef, - droppable, - canDrop, - dropTarget, - onContextMenu, - contextMenuOpen, - dragging, - dragNodeRef, - badge, - badgeColor, - badgeTextColor, - badgeBorderColor, - badgeClassName, - badgeLocation, - labelIconClass, - labelIcon, - labelIconPadding, - onCollapseChange -}) => { - const [hovered, hoverRef] = useHover(); - const [labelHover, labelHoverRef] = useHover(); - const dragLabelRef = useDragNode()[1]; - const refs = useCombineRefs(hoverRef, dragNodeRef); - const isHover = hover !== undefined ? hover : hovered; - const anchorRef = useSvgAnchor(); - const outlineRef = useCombineRefs(dndDropRef, anchorRef); - const labelLocation = React.useRef(); - const pathRef = React.useRef(); - - let parent = element.getParent(); - let altGroup = false; - while (!isGraph(parent)) { - altGroup = !altGroup; - parent = parent.getParent(); - } - - // cast to number and coerce - const padding = maxPadding(element.getStyle().padding ?? 17); - const hullPadding = (point: PointWithSize | PointTuple) => (point[2] || 0) + padding; - - if (!droppable || !pathRef.current || !labelLocation.current) { - const children = element.getNodes().filter(c => c.isVisible()); - if (children.length === 0) { - return null; - } - const points: (PointWithSize | PointTuple)[] = []; - _.forEach(children, c => { - if (c.getNodeShape() === NodeShape.circle) { - const bounds = c.getBounds(); - const { width, height } = bounds; - const { x, y } = bounds.getCenter(); - const radius = Math.max(width, height) / 2; - points.push([x, y, radius] as PointWithSize); - } else { - // add all 4 corners - const { width, height, x, y } = c.getBounds(); - points.push([x, y, 0] as PointWithSize); - points.push([x + width, y, 0] as PointWithSize); - points.push([x, y + height, 0] as PointWithSize); - points.push([x + width, y + height, 0] as PointWithSize); - } - }); - const hullPoints: (PointWithSize | PointTuple)[] = - points.length > 2 ? polygonHull(points as PointTuple[]) : (points as PointTuple[]); - if (!hullPoints) { - return null; - } - - // change the box only when not dragging - pathRef.current = hullPath(hullPoints as PointTuple[], hullPadding); - - // Compute the location of the group label. - labelLocation.current = computeLabelLocation(hullPoints as PointWithSize[]); - } - - const groupClassName = css( - styles.topologyGroup, - className, - altGroup && 'pf-m-alt-group', - canDrop && 'pf-m-highlight', - dragging && 'pf-m-dragging', - selected && 'pf-m-selected' - ); - const innerGroupClassName = css( - styles.topologyGroup, - className, - altGroup && 'pf-m-alt-group', - canDrop && 'pf-m-highlight', - dragging && 'pf-m-dragging', - selected && 'pf-m-selected', - (isHover || labelHover) && 'pf-m-hover', - canDrop && dropTarget && 'pf-m-drop-target' - ); - - return ( - - - - - - - {showLabel && (label || element.getLabel()) && ( - : undefined} - onActionIconClick={() => onCollapseChange(element, true)} - > - {label || element.getLabel()} - - )} - - ); -}; - -export default observer(DefaultGroupExpanded); diff --git a/packages/react-topology/src/components/groups/index.ts b/packages/react-topology/src/components/groups/index.ts deleted file mode 100644 index dd08fa6ffef..00000000000 --- a/packages/react-topology/src/components/groups/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './types'; -export { default as DefaultGroup } from './DefaultGroup'; diff --git a/packages/react-topology/src/components/groups/types.ts b/packages/react-topology/src/components/groups/types.ts deleted file mode 100644 index ed088eb39c4..00000000000 --- a/packages/react-topology/src/components/groups/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Node } from '../../types'; -import * as React from 'react'; -import { ShapeProps } from '../nodes'; - -export interface CollapsibleGroupProps { - collapsible?: boolean; - collapsedWidth?: number; - collapsedHeight?: number; - onCollapseChange?: (group: Node, collapsed: boolean) => void; - getCollapsedShape?: (node: Node) => React.FunctionComponent; - collapsedShadowOffset?: number; // defaults to 10 -} diff --git a/packages/react-topology/src/components/index.ts b/packages/react-topology/src/components/index.ts deleted file mode 100644 index b2b017b64b2..00000000000 --- a/packages/react-topology/src/components/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -export * from './TopologyView'; -export * from './TopologyControlBar'; -export * from './TopologySideBar'; -export { default as VisualizationProvider } from './VisualizationProvider'; -export { default as VisualizationSurface } from './VisualizationSurface'; -export { default as DefaultCreateConnector } from './DefaultCreateConnector'; -export { default as DefaultRemoveConnector } from './DefaultRemoveConnector'; -export { default as GraphComponent } from './GraphComponent'; -export { default as SVGArrowMarker } from './SVGArrowMarker'; -export { default as ElementWrapper } from './ElementWrapper'; -export * from './contextmenu'; -export * from './decorators'; -export * from './groups'; -export * from './nodes'; -export * from './edges'; -export * from './factories'; -export * from './layers'; -export * from './defs'; diff --git a/packages/react-topology/src/components/layers/Layer.tsx b/packages/react-topology/src/components/layers/Layer.tsx deleted file mode 100644 index 810f9840bb1..00000000000 --- a/packages/react-topology/src/components/layers/Layer.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { createPortal } from 'react-dom'; -import ElementContext from '../../utils/ElementContext'; -import LayersContext from './LayersContext'; -import LayerContainer from './LayerContainer'; - -interface LayerProps { - id?: string; - children: React.ReactNode; - orderKey?: number; -} - -interface LayerDelegateProps { - id: string; - children: React.ReactNode; - orderKey?: number; -} - -const ORDER_KEY = '__order__'; - -const compare = (a: ChildNode, b: ChildNode): number => { - if (a === b) { - return 0; - } - const ao = a[ORDER_KEY]; - const bo = b[ORDER_KEY]; - - if (ao == null || bo == null) { - return 0; - } - - for (let i = 0; i < ao.length; i++) { - if (ao[i] !== bo[i]) { - return ao[i] - bo[i]; - } - } - return ao.length === bo.length ? 0 : ao.length - bo.length; -}; - -const LayerDelegate: React.FunctionComponent = observer(({ id, children, orderKey }) => { - const getLayerNode = React.useContext(LayersContext); - const layerNode = getLayerNode(id); - - const element = React.useContext(ElementContext); - const nodeRef = React.useRef(null); - let order: unknown; - if (id && orderKey == null) { - order = element.getOrderKey(); - } else if (id) { - order = orderKey; - } - - React.useEffect(() => { - // TODO use bisection search - if (nodeRef.current && layerNode != null) { - nodeRef.current[ORDER_KEY] = order; - const { childNodes } = layerNode; - // childNodes is not an array, disable false positive - // eslint-disable-next-line @typescript-eslint/prefer-for-of - for (let i = 0; i < childNodes.length; i++) { - const result = compare(nodeRef.current, childNodes[i]); - if (result < 0) { - if (i > 0 && childNodes[i - 1] !== nodeRef.current) { - layerNode.insertBefore(nodeRef.current, childNodes[i]); - } - return; - } - } - if (childNodes[childNodes.length - 1] !== nodeRef.current) { - layerNode.appendChild(nodeRef.current); - } - } - }, [order, layerNode]); - - return createPortal({children}, layerNode); -}); - -const Layer: React.FunctionComponent = ({ id, children, orderKey }) => - id ? ( - - {children} - - ) : ( - <>{children} - ); - -export default Layer; diff --git a/packages/react-topology/src/components/layers/LayerContainer.tsx b/packages/react-topology/src/components/layers/LayerContainer.tsx deleted file mode 100644 index 19399e4959d..00000000000 --- a/packages/react-topology/src/components/layers/LayerContainer.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import ElementContext from '../../utils/ElementContext'; -import { isNode } from '../../types'; -import { ATTR_DATA_ID, ATTR_DATA_KIND, ATTR_DATA_TYPE } from '../../const'; - -interface LayerContainerProps { - children: React.ReactNode; -} - -const LayerContainer: React.ForwardRefRenderFunction = ({ children }, ref) => { - // accumulate parent positions - const element = React.useContext(ElementContext); - let p = element; - let x = 0; - let y = 0; - while (isNode(p)) { - if (!p.isGroup() || p.isCollapsed()) { - const { x: px, y: py } = p.getPosition(); - x += px; - y += py; - } - p = p.getParent(); - } - const commonAttrs = { - [ATTR_DATA_ID]: element.getId(), - [ATTR_DATA_KIND]: element.getKind(), - [ATTR_DATA_TYPE]: element.getType() - }; - return ( - - {children} - - ); -}; - -export default observer(React.forwardRef(LayerContainer)); diff --git a/packages/react-topology/src/components/layers/LayersContext.ts b/packages/react-topology/src/components/layers/LayersContext.ts deleted file mode 100644 index 9013305239c..00000000000 --- a/packages/react-topology/src/components/layers/LayersContext.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createContext } from 'react'; - -type LayersContextProps = (id: string) => Element; - -const LayersContext = createContext(undefined as any); - -export default LayersContext; diff --git a/packages/react-topology/src/components/layers/LayersProvider.tsx b/packages/react-topology/src/components/layers/LayersProvider.tsx deleted file mode 100644 index 8d79e57491e..00000000000 --- a/packages/react-topology/src/components/layers/LayersProvider.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from 'react'; -import { DEFAULT_LAYER } from '../../const'; -import LayersContext from './LayersContext'; - -interface LayersProviderProps { - layers?: string[]; - children?: React.ReactNode; -} - -interface State { - [id: string]: Element; -} - -export default class LayersProvider extends React.Component { - constructor(props: LayersProviderProps) { - super(props); - this.state = {}; - } - - private contextValue = (id: string): Element => { - if (this.state[id]) { - return this.state[id]; - } - throw new Error(`Unknown layer '${id}'`); - }; - - private setDomLayers = (node: SVGGElement | null, id: string) => { - if (node && this.state[id] !== node) { - this.setState(state => ({ ...state, [id]: node })); - } - }; - - getLayerNode = (id: string): Element => { - const node = this.state[id]; - if (node) { - return node; - } - throw new Error(`Unknown layer '${id}'`); - }; - - render() { - const { layers, children } = this.props; - if (layers && !layers.includes(DEFAULT_LAYER)) { - throw new Error('Missing default layer.'); - } - const layerIds = layers || [DEFAULT_LAYER]; - return ( - - {layerIds.map(id => ( - this.setDomLayers(r, id)}> - {id === DEFAULT_LAYER && this.state[id] ? children : undefined} - - ))} - - ); - } -} diff --git a/packages/react-topology/src/components/layers/index.ts b/packages/react-topology/src/components/layers/index.ts deleted file mode 100644 index 9311498cc21..00000000000 --- a/packages/react-topology/src/components/layers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Layer } from './Layer'; -export { default as LayersProvider } from './LayersProvider'; diff --git a/packages/react-topology/src/components/nodes/DefaultNode.tsx b/packages/react-topology/src/components/nodes/DefaultNode.tsx deleted file mode 100644 index 909d63ed616..00000000000 --- a/packages/react-topology/src/components/nodes/DefaultNode.tsx +++ /dev/null @@ -1,367 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { css } from '@patternfly/react-styles'; -import { Tooltip, TooltipPosition } from '@patternfly/react-core'; -import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon'; -import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; -import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { BadgeLocation, GraphElement, LabelPosition, Node, NodeStatus, TopologyQuadrant } from '../../types'; -import { ConnectDragSource, ConnectDropTarget, OnSelect, WithDndDragProps } from '../../behavior'; -import Decorator from '../decorators/Decorator'; -import { createSvgIdUrl, StatusModifier, useCombineRefs, useHover } from '../../utils'; -import NodeLabel from './labels/NodeLabel'; -import NodeShadows, { NODE_SHADOW_FILTER_ID_DANGER, NODE_SHADOW_FILTER_ID_HOVER } from './NodeShadows'; -import { DEFAULT_DECORATOR_RADIUS, getDefaultShapeDecoratorCenter, getShapeComponent, ShapeProps } from './shapes'; - -const StatusQuadrant = TopologyQuadrant.upperLeft; - -const getStatusIcon = (status: NodeStatus) => { - switch (status) { - case NodeStatus.danger: - return ; - case NodeStatus.warning: - return ; - case NodeStatus.success: - return ; - default: - return null; - } -}; - -interface DefaultNodeProps { - /** Additional content added to the node */ - children?: React.ReactNode; - /** Additional classes added to the node */ - className?: string; - /** The graph node element to represent */ - element: Node; - /** Flag if the node accepts drop operations */ - droppable?: boolean; - /** Flag if the user is hovering on the node */ - hover?: boolean; - /** Flag if the current drag operation can be dropped on the node */ - canDrop?: boolean; - /** Flag if the user is dragging the node */ - dragging?: boolean; - /** Flag if the user is dragging an edge connected to the node */ - edgeDragging?: boolean; - /** Flag if the node is the current drop target */ - dropTarget?: boolean; - /** Flag indicating the node should be scaled, best on hover of the node at lowest scale level */ - scaleNode?: boolean; - /** Label for the node. Defaults to element.getLabel() */ - label?: string; - /** Secondary label for the node */ - secondaryLabel?: string; - /** Flag to show the label */ - showLabel?: boolean; - /** Additional classes to add to the label */ - labelClassName?: string; - /** Flag to scale the label, best on hover of the node at lowest scale level */ - scaleLabel?: boolean; - /** Position of the label, bottom or left. Defaults to element.getLabelPosition() or bottom */ - labelPosition?: LabelPosition; - /** The maximum length of the label before truncation */ - truncateLength?: number; - /** The label icon component to show in the label, takes precedence over labelIconClass */ - labelIcon?: React.ReactNode; - /** The Icon class to show in the label, ignored when labelIcon is specified */ - labelIconClass?: string; - /** Padding for the label's icon */ - labelIconPadding?: number; - /** Text for the label's badge */ - badge?: string; - /** Color to use for the label's badge background */ - badgeColor?: string; - /** Color to use for the label's badge text */ - badgeTextColor?: string; - /** Color to use for the label's badge border */ - badgeBorderColor?: string; - /** Additional classes to use for the label's badge */ - badgeClassName?: string; - /** Location of the badge relative to the label's text, inner or below */ - badgeLocation?: BadgeLocation; - /** Additional items to add to the node, typically decorators */ - attachments?: React.ReactNode; - /** Status of the node, Defaults to element.getNodeStatus() */ - nodeStatus?: NodeStatus; - /** Flag indicating whether the node's background color should indicate node status */ - showStatusBackground?: boolean; - /** Flag which displays the status decorator for the node */ - showStatusDecorator?: boolean; - /** Contents of a tooltip to show on the status decorator */ - statusDecoratorTooltip?: React.ReactNode; - /** Callback when the status decorator is clicked */ - onStatusDecoratorClick?: (event: React.MouseEvent, element: GraphElement) => void; - /** Function to return a custom shape component for the element */ - getCustomShape?: (node: Node) => React.FunctionComponent; - /** Function to return the center for a decorator for the quadrant */ - getShapeDecoratorCenter?: (quadrant: TopologyQuadrant, node: Node) => { x: number; y: number }; - /** Flag if the element selected. Part of WithSelectionProps */ - selected?: boolean; - /** Function to call when the element should become selected (or deselected). Part of WithSelectionProps */ - onSelect?: OnSelect; - /** A ref to add to the node for dragging. Part of WithDragNodeProps */ - dragNodeRef?: WithDndDragProps['dndDragRef']; - /** A ref to add to the node for drag and drop. Part of WithDndDragProps */ - dndDragRef?: ConnectDragSource; - /** A ref to add to the node for dropping. Part of WithDndDropProps */ - dndDropRef?: ConnectDropTarget; - /** Function to call for showing a connector creation indicator. Part of WithCreateConnectorProps */ - onShowCreateConnector?: () => void; - /** Function to call to hide the connector creation indicator. Part of WithCreateConnectorProps */ - onHideCreateConnector?: () => void; - /** Function to call to show a context menu for the node */ - onContextMenu?: (e: React.MouseEvent) => void; - /** Flag indicating that the context menu for the node is currently open */ - contextMenuOpen?: boolean; -} - -const SCALE_UP_TIME = 200; - -const DefaultNode: React.FunctionComponent = ({ - className, - element, - selected, - hover, - scaleNode, - showLabel = true, - label, - secondaryLabel, - labelClassName, - labelPosition, - scaleLabel, - truncateLength, - labelIconClass, - labelIcon, - labelIconPadding, - nodeStatus, - showStatusBackground, - showStatusDecorator = false, - statusDecoratorTooltip, - getCustomShape, - getShapeDecoratorCenter, - onStatusDecoratorClick, - badge, - badgeColor, - badgeTextColor, - badgeBorderColor, - badgeClassName, - badgeLocation, - onSelect, - children, - attachments, - dragNodeRef, - dragging, - edgeDragging, - canDrop, - dropTarget, - dndDropRef, - onHideCreateConnector, - onShowCreateConnector, - onContextMenu, - contextMenuOpen -}: DefaultNodeProps) => { - const [hovered, hoverRef] = useHover(); - const status = nodeStatus || element.getNodeStatus(); - const refs = useCombineRefs(hoverRef, dragNodeRef); - const { width, height } = element.getDimensions(); - const isHover = hover !== undefined ? hover : hovered; - const [nodeScale, setNodeScale] = React.useState(1); - - const statusDecorator = React.useMemo(() => { - if (!status || !showStatusDecorator) { - return null; - } - - const icon = getStatusIcon(status); - if (!icon) { - return null; - } - - const { x, y } = getShapeDecoratorCenter - ? getShapeDecoratorCenter(StatusQuadrant, element) - : getDefaultShapeDecoratorCenter(StatusQuadrant, element); - - const decorator = ( - onStatusDecoratorClick(e, element)} - icon={{icon}} - ariaLabel={status} - /> - ); - - if (statusDecoratorTooltip) { - return ( - - {decorator} - - ); - } - - return decorator; - }, [showStatusDecorator, status, getShapeDecoratorCenter, element, statusDecoratorTooltip, onStatusDecoratorClick]); - - React.useEffect(() => { - if (isHover) { - onShowCreateConnector && onShowCreateConnector(); - } else { - onHideCreateConnector && onHideCreateConnector(); - } - }, [isHover, onShowCreateConnector, onHideCreateConnector]); - - const ShapeComponent = (getCustomShape && getCustomShape(element)) || getShapeComponent(element); - - const groupClassName = css( - styles.topologyNode, - className, - isHover && 'pf-m-hover', - (dragging || edgeDragging) && 'pf-m-dragging', - canDrop && 'pf-m-highlight', - canDrop && dropTarget && 'pf-m-drop-target', - selected && 'pf-m-selected', - StatusModifier[status] - ); - - const backgroundClassName = css( - styles.topologyNodeBackground, - showStatusBackground && StatusModifier[status], - showStatusBackground && selected && 'pf-m-selected' - ); - - let filter; - if (status === 'danger') { - filter = createSvgIdUrl(NODE_SHADOW_FILTER_ID_DANGER); - } else if (isHover || dragging || edgeDragging || dropTarget) { - filter = createSvgIdUrl(NODE_SHADOW_FILTER_ID_HOVER); - } - - const nodeLabelPosition = labelPosition || element.getLabelPosition(); - const scale = element.getGraph().getScale(); - - const animationRef = React.useRef(); - const scaleGoal = React.useRef(1); - const nodeScaled = React.useRef(false); - - React.useEffect(() => { - if (!scaleNode || scale >= 1) { - setNodeScale(1); - nodeScaled.current = false; - if (animationRef.current) { - window.cancelAnimationFrame(animationRef.current); - animationRef.current = 0; - } - } else { - scaleGoal.current = 1 / scale; - const scaleDelta = scaleGoal.current - scale; - const initTime = performance.now(); - - const bumpScale = (bumpTime: number) => { - const scalePercent = (bumpTime - initTime) / SCALE_UP_TIME; - const nextScale = Math.min(scale + scaleDelta * scalePercent, scaleGoal.current); - setNodeScale(nextScale); - if (nextScale < scaleGoal.current) { - animationRef.current = window.requestAnimationFrame(bumpScale); - } else { - nodeScaled.current = true; - animationRef.current = 0; - } - }; - - if (nodeScaled.current) { - setNodeScale(scaleGoal.current); - } else if (!animationRef.current) { - animationRef.current = window.requestAnimationFrame(bumpScale); - } - } - return () => { - if (animationRef.current) { - window.cancelAnimationFrame(animationRef.current); - animationRef.current = 0; - } - }; - }, [scale, scaleNode]); - - // counter scale label - const counterScale = (scale: number, scaleMin: number, scaleMax: number, valueMin: number, valueMax: number) => { - if (scale >= scaleMax) { - return valueMin; - } else if (scale <= scaleMin) { - return valueMax; - } - return valueMin + (1 - (scale - scaleMin) / (scaleMax - scaleMin)) * (valueMax - valueMin); - }; - const labelScale = scaleLabel ? counterScale(scale, 0.35, 0.85, 1, 1.6) : 1; - const labelPositionScale = scaleLabel ? Math.min(1, 1 / labelScale) : 1; - - const { translateX, translateY } = React.useMemo(() => { - if (!scaleNode) { - return { translateX: 0, translateY: 0 }; - } - const bounds = element.getBounds(); - const translateX = bounds.width / 2 - (bounds.width / 2) * nodeScale; - const translateY = bounds.height / 2 - (bounds.height / 2) * nodeScale; - - return { translateX, translateY }; - }, [element, nodeScale, scaleNode]); - - return ( - - - - {ShapeComponent && ( - - )} - {showLabel && (label || element.getLabel()) && ( - - - {label || element.getLabel()} - - - )} - {children} - - {statusDecorator} - {attachments} - - ); -}; - -export default observer(DefaultNode); diff --git a/packages/react-topology/src/components/nodes/NodeShadows.tsx b/packages/react-topology/src/components/nodes/NodeShadows.tsx deleted file mode 100644 index b0b0f7cfb14..00000000000 --- a/packages/react-topology/src/components/nodes/NodeShadows.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -import SvgDropShadowFilter from '../svg/SvgDropShadowFilter'; - -export const NODE_SHADOW_FILTER_ID = 'NodeShadowsFilterId'; -export const NODE_SHADOW_FILTER_ID_HOVER = 'NodeShadowsFilterId--hover'; -export const NODE_SHADOW_FILTER_ID_DANGER = 'NodeShadowsFilterId--danger'; - -const NodeShadows: React.FunctionComponent = () => ( - <> - - - - -); - -export default NodeShadows; diff --git a/packages/react-topology/src/components/nodes/index.ts b/packages/react-topology/src/components/nodes/index.ts deleted file mode 100644 index 3b4b66672ca..00000000000 --- a/packages/react-topology/src/components/nodes/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { default as DefaultNode } from './DefaultNode'; -export { default as NodeShadows } from './NodeShadows'; -export * from './shapes'; -export * from './labels'; diff --git a/packages/react-topology/src/components/nodes/labels/LabelActionIcon.tsx b/packages/react-topology/src/components/nodes/labels/LabelActionIcon.tsx deleted file mode 100644 index 6abd72a40a6..00000000000 --- a/packages/react-topology/src/components/nodes/labels/LabelActionIcon.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from 'react'; -import { useSize } from '../../../utils'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; - -interface LabelActionIconProps { - className?: string; - icon: React.ReactElement; - onClick: (e: React.MouseEvent) => void; - iconOffsetX?: number; - iconOffsetY?: number; - x: number; - y: number; - height: number; - paddingX: number; - paddingY: number; -} - -const LabelActionIcon = React.forwardRef( - ({ icon, onClick, className, x, y, paddingX, height, iconOffsetX = 0, iconOffsetY = 0 }, actionRef) => { - const [iconSize, iconRef] = useSize([icon, paddingX]); - const iconWidth = iconSize?.width ?? 0; - const iconHeight = iconSize?.height ?? 0; - const iconY = (height - iconHeight) / 2; - - const classes = css(styles.topologyNodeActionIcon, className); - - const handleClick = (e: React.MouseEvent) => { - if (onClick) { - e.stopPropagation(); - onClick(e); - } - }; - - return ( - - {iconSize && ( - - )} - - {icon} - - - ); - } -); - -export default LabelActionIcon; diff --git a/packages/react-topology/src/components/nodes/labels/LabelBadge.tsx b/packages/react-topology/src/components/nodes/labels/LabelBadge.tsx deleted file mode 100644 index 0f6629f4e8c..00000000000 --- a/packages/react-topology/src/components/nodes/labels/LabelBadge.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* eslint patternfly-react/import-tokens-icons: 0 */ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import { global_palette_blue_50 as defaultBadgeFill } from '@patternfly/react-tokens/dist/js/global_palette_blue_50'; -import { global_palette_blue_300 as defaultBadgeBorder } from '@patternfly/react-tokens/dist/js/global_palette_blue_300'; -import { global_palette_blue_300 as defaultBadgeTextColor } from '@patternfly/react-tokens/dist/js/global_palette_blue_300'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { useSize } from '../../../utils'; -import { BadgeLocation } from '../../../types'; - -interface LabelBadgeProps { - className?: string; - x: number; - y: number; - badge?: string; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; -} - -const LabelBadge = React.forwardRef( - ({ badge, badgeTextColor, badgeColor, badgeBorderColor, badgeClassName, className, x, y }, iconRef) => { - const [textSize, textRef] = useSize([]); - const classes = css(styles.topologyNodeLabelBadge, badgeClassName && badgeClassName, className && className); - - let rect = null; - let paddingX = 0; - let paddingY = 0; - let width = 0; - let height = 0; - - if (textSize) { - ({ height, width } = textSize); - paddingX = height / 2; - paddingY = height / 14; - height += paddingY * 2; - rect = ( - - ); - } - return ( - - {rect} - - {badge} - - - ); - } -); - -export default LabelBadge; diff --git a/packages/react-topology/src/components/nodes/labels/LabelContextMenu.tsx b/packages/react-topology/src/components/nodes/labels/LabelContextMenu.tsx deleted file mode 100644 index 660d0670bd6..00000000000 --- a/packages/react-topology/src/components/nodes/labels/LabelContextMenu.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react'; -import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; -import { WithContextMenuProps } from '../../../behavior'; -import LabelActionIcon from './LabelActionIcon'; - -type LabelContextMenuProps = { - className?: string; - x: number; - y: number; - height: number; - paddingX: number; - paddingY: number; -} & WithContextMenuProps; - -const LabelContextMenu = React.forwardRef( - ({ onContextMenu, className, x, y, paddingX, paddingY, height }, menuRef) => ( - } - iconOffsetX={-6} - className={className} - onClick={onContextMenu} - x={x} - y={y} - height={height} - paddingX={paddingX} - paddingY={paddingY} - /> - ) -); - -export default LabelContextMenu; diff --git a/packages/react-topology/src/components/nodes/labels/LabelIcon.tsx b/packages/react-topology/src/components/nodes/labels/LabelIcon.tsx deleted file mode 100644 index 947b4fa7383..00000000000 --- a/packages/react-topology/src/components/nodes/labels/LabelIcon.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; - -interface LabelIconProps { - className?: string; - x: number; - y: number; - width: number; - height: number; - padding?: number; - iconClass?: string; - icon?: React.ReactNode; -} - -const LabelIcon = React.forwardRef( - ({ className, x, y, width, height, iconClass, icon, padding = 4 }, circleRef) => { - const radius = width / 2; - const cx = x - radius; - const cy = y + height / 2; - const innerX = x - width + padding + 1; - const innerY = y + padding + 1; - const innerWidth = width - padding * 2 - 2; // -2 for 1px border on each side - const innerHeight = height - padding * 2 - 2; // -2 for 1px border on each side - - return ( - - - {icon ? ( - - {icon} - - ) : ( - - )} - - ); - } -); - -export default LabelIcon; diff --git a/packages/react-topology/src/components/nodes/labels/NodeLabel.tsx b/packages/react-topology/src/components/nodes/labels/NodeLabel.tsx deleted file mode 100644 index 62d487cca3d..00000000000 --- a/packages/react-topology/src/components/nodes/labels/NodeLabel.tsx +++ /dev/null @@ -1,299 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { truncateMiddle } from '../../../utils/truncate-middle'; -import { createSvgIdUrl, useCombineRefs, useHover, useSize } from '../../../utils'; -import { WithContextMenuProps, WithDndDragProps } from '../../../behavior'; -import NodeShadows, { NODE_SHADOW_FILTER_ID_DANGER, NODE_SHADOW_FILTER_ID_HOVER } from '../NodeShadows'; -import LabelBadge from './LabelBadge'; -import LabelContextMenu from './LabelContextMenu'; -import LabelIcon from './LabelIcon'; -import LabelActionIcon from './LabelActionIcon'; -import { BadgeLocation, LabelPosition, NodeStatus } from '../../../types'; - -type NodeLabelProps = { - children?: string; - className?: string; - paddingX?: number; - paddingY?: number; - x?: number; - y?: number; - position?: LabelPosition; - cornerRadius?: number; - status?: NodeStatus; - secondaryLabel?: string; - truncateLength?: number; // Defaults to 13 - labelIconClass?: string; // Icon to show in label - labelIcon?: React.ReactNode; - labelIconPadding?: number; - dragRef?: WithDndDragProps['dndDragRef']; - hover?: boolean; - dragging?: boolean; - edgeDragging?: boolean; - dropTarget?: boolean; - actionIcon?: React.ReactElement; - actionIconClassName?: string; - onActionIconClick?: (e: React.MouseEvent) => void; - badge?: string; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; -} & Partial; - -/** - * Renders a `` component with a `` box behind. - */ -const NodeLabel: React.FunctionComponent = ({ - children, - className, - paddingX = 0, - paddingY = 0, - cornerRadius = 4, - x = 0, - y = 0, - position = LabelPosition.bottom, - secondaryLabel, - status, - badge, - badgeColor, - badgeTextColor, - badgeBorderColor, - badgeClassName, - badgeLocation = BadgeLocation.inner, - labelIconClass, - labelIcon, - labelIconPadding = 4, - truncateLength, - dragRef, - hover, - dragging, - edgeDragging, - dropTarget, - onContextMenu, - contextMenuOpen, - actionIcon, - actionIconClassName, - onActionIconClick, - ...other -}) => { - const [labelHover, labelHoverRef] = useHover(); - const refs = useCombineRefs(dragRef, typeof truncateLength === 'number' ? labelHoverRef : undefined); - - const [textSize, textRef] = useSize([children, truncateLength, className, labelHover]); - const [secondaryTextSize, secondaryTextRef] = useSize([secondaryLabel, truncateLength, className, labelHover]); - const [badgeSize, badgeRef] = useSize([badge]); - const [actionSize, actionRef] = useSize([actionIcon, paddingX]); - const [contextSize, contextRef] = useSize([onContextMenu, paddingX]); - - const { - width, - height, - backgroundHeight, - startX, - startY, - badgeStartX, - badgeStartY, - actionStartX, - contextStartX, - iconSpace, - badgeSpace - } = React.useMemo(() => { - if (!textSize) { - return { - width: 0, - height: 0, - backgroundHeight: 0, - startX: 0, - startY: 0, - badgeStartX: 0, - badgeStartY: 0, - actionStartX: 0, - contextStartX: 0, - iconSpace: 0, - badgeSpace: 0 - }; - } - const badgeSpace = badge && badgeSize && badgeLocation === BadgeLocation.inner ? badgeSize.width + paddingX : 0; - const height = Math.max(textSize.height, badgeSize?.height ?? 0) + paddingY * 2; - const iconSpace = labelIconClass || labelIcon ? (height + paddingY * 0.5) / 2 : 0; - const actionSpace = actionIcon && actionSize ? actionSize.width : 0; - const contextSpace = onContextMenu && contextSize ? contextSize.width : 0; - const primaryWidth = iconSpace + badgeSpace + paddingX + textSize.width + actionSpace + contextSpace + paddingX; - const secondaryWidth = secondaryLabel && secondaryTextSize ? secondaryTextSize.width + 2 * paddingX : 0; - const width = Math.max(primaryWidth, secondaryWidth); - const startX = position === LabelPosition.right ? x + iconSpace : x - width / 2 + iconSpace / 2; - const startY = position === LabelPosition.right ? y - height / 2 : y; - const actionStartX = iconSpace + badgeSpace + paddingX + textSize.width + paddingX; - const contextStartX = actionStartX + actionSpace; - const backgroundHeight = - height + (secondaryLabel && secondaryTextSize ? secondaryTextSize.height + paddingY * 2 : 0); - let badgeStartX = 0; - let badgeStartY = 0; - if (badgeSize) { - if (badgeLocation === BadgeLocation.below) { - badgeStartX = (width - badgeSize.width) / 2; - badgeStartY = height + paddingY; - } else { - badgeStartX = iconSpace + paddingX; - badgeStartY = (height - badgeSize.height) / 2; - } - } - - return { - width, - height, - backgroundHeight, - startX, - startY, - actionStartX, - contextStartX, - badgeStartX, - badgeStartY, - iconSpace, - badgeSpace: badgeSize && badgeLocation === BadgeLocation.inner ? badgeSpace : 0 - }; - }, [ - textSize, - badge, - badgeSize, - badgeLocation, - paddingX, - paddingY, - labelIconClass, - labelIcon, - actionIcon, - actionSize, - onContextMenu, - contextSize, - secondaryLabel, - secondaryTextSize, - position, - x, - y - ]); - - let filterId; - if (status === 'danger') { - filterId = NODE_SHADOW_FILTER_ID_DANGER; - } else if (hover || dragging || edgeDragging || dropTarget) { - filterId = NODE_SHADOW_FILTER_ID_HOVER; - } - - return ( - - - {textSize && ( - - )} - {textSize && badge && ( - - )} - {textSize && secondaryLabel && ( - <> - - - {truncateLength > 0 && !labelHover - ? truncateMiddle(secondaryLabel, { length: truncateLength }) - : secondaryLabel} - - - )} - {textSize && (labelIconClass || labelIcon) && ( - - )} - - {truncateLength > 0 && !labelHover ? truncateMiddle(children, { length: truncateLength }) : children} - - {textSize && actionIcon && ( - <> - - - - )} - {textSize && onContextMenu && ( - <> - - - - )} - - ); -}; - -export default NodeLabel; diff --git a/packages/react-topology/src/components/nodes/labels/index.ts b/packages/react-topology/src/components/nodes/labels/index.ts deleted file mode 100644 index 11dcc59c8e2..00000000000 --- a/packages/react-topology/src/components/nodes/labels/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as LabelActionIcon } from './LabelActionIcon'; -export { default as LabelBadge } from './LabelBadge'; -export { default as LabelContextMenu } from './LabelContextMenu'; -export { default as LabelIcon } from './LabelIcon'; -export { default as NodeLabel } from './NodeLabel'; diff --git a/packages/react-topology/src/components/nodes/shapes/Ellipse.tsx b/packages/react-topology/src/components/nodes/shapes/Ellipse.tsx deleted file mode 100644 index d299e875683..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Ellipse.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import * as React from 'react'; -import { useAnchor } from '../../../behavior'; -import { EllipseAnchor } from '../../../anchors'; -import { ShapeProps } from './shapeUtils'; - -type EllipseProps = ShapeProps; - -const Ellipse: React.FunctionComponent = ({ - className = css(styles.topologyNodeBackground), - width, - height, - filter, - dndDropRef -}) => { - useAnchor(EllipseAnchor); - return ( - - ); -}; - -export default Ellipse; diff --git a/packages/react-topology/src/components/nodes/shapes/Hexagon.tsx b/packages/react-topology/src/components/nodes/shapes/Hexagon.tsx deleted file mode 100644 index fd13a1867fb..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Hexagon.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { HEXAGON_CORNER_RADIUS, ShapeProps } from './shapeUtils'; -import { SidedShape } from './index'; - -type HexagonProps = ShapeProps & { - cornerRadius?: number; -}; - -const Hexagon: React.FunctionComponent = props => ( - -); - -export default Hexagon; diff --git a/packages/react-topology/src/components/nodes/shapes/Octagon.tsx b/packages/react-topology/src/components/nodes/shapes/Octagon.tsx deleted file mode 100644 index 5bb02b107ac..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Octagon.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { OCTAGON_CORNER_RADIUS, ShapeProps } from './shapeUtils'; -import { SidedShape } from './index'; - -type OctagonProps = ShapeProps & { - cornerRadius?: number; -}; - -const Octagon: React.FunctionComponent = props => ( - -); - -export default Octagon; diff --git a/packages/react-topology/src/components/nodes/shapes/Rectangle.tsx b/packages/react-topology/src/components/nodes/shapes/Rectangle.tsx deleted file mode 100644 index 536d42f22d9..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Rectangle.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { useAnchor } from '../../../behavior'; -import { RectAnchor } from '../../../anchors'; -import { ShapeProps } from './shapeUtils'; - -type RectangleProps = ShapeProps & { - cornerRadius?: number; -}; - -const Rectangle: React.FunctionComponent = ({ - className = css(styles.topologyNodeBackground), - width, - height, - filter, - cornerRadius = 15, - dndDropRef -}) => { - useAnchor(RectAnchor); - return ( - - ); -}; - -export default Rectangle; diff --git a/packages/react-topology/src/components/nodes/shapes/Rhombus.tsx b/packages/react-topology/src/components/nodes/shapes/Rhombus.tsx deleted file mode 100644 index c8cf54d2c40..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Rhombus.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { PointTuple } from '../../../types'; -import { getHullPath, RHOMBUS_CORNER_RADIUS, ShapeProps } from './shapeUtils'; -import { useSvgAnchor } from '../../../behavior'; -import { useCombineRefs } from '../../../utils'; - -type RhombusProps = ShapeProps & { - cornerRadius?: number; -}; - -const getRhombusPoints = (width: number, height: number, padding: number): PointTuple[] => [ - [width / 2, -padding], - [width + padding, height / 2], - [width / 2, height + padding], - [-padding, height / 2] -]; - -const Rhombus: React.FunctionComponent = ({ - className = css(styles.topologyNodeBackground), - width, - height, - filter, - cornerRadius = RHOMBUS_CORNER_RADIUS, - dndDropRef -}) => { - const anchorRef = useSvgAnchor(); - const refs = useCombineRefs(dndDropRef, anchorRef); - const points = React.useMemo(() => { - const polygonPoints: PointTuple[] = getRhombusPoints(width, height, cornerRadius / 2); - - return cornerRadius - ? getHullPath(getRhombusPoints(width, height, -cornerRadius), cornerRadius) - : polygonPoints.map(p => `${p[0]},${p[1]}`).join(' '); - }, [cornerRadius, height, width]); - - return cornerRadius ? ( - - ) : ( - - ); -}; - -export default Rhombus; diff --git a/packages/react-topology/src/components/nodes/shapes/SidedShape.tsx b/packages/react-topology/src/components/nodes/shapes/SidedShape.tsx deleted file mode 100644 index e74da83a5ad..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/SidedShape.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import * as React from 'react'; -import { getPathForSides, getPointsForSides, ShapeProps } from './shapeUtils'; -import { usePolygonAnchor } from '../../../behavior'; - -type SidedProps = ShapeProps & { - sides?: number; - cornerRadius?: number; -}; - -const SidedShape: React.FunctionComponent = ({ - className = css(styles.topologyNodeBackground), - width, - height, - filter, - sides = 6, - cornerRadius = 0, - dndDropRef -}) => { - const [polygonPoints, points] = React.useMemo(() => { - const polygonPoints = getPointsForSides(sides, Math.min(width, height)); - return [ - polygonPoints, - cornerRadius - ? getPathForSides(sides, Math.min(width, height), cornerRadius) - : polygonPoints.map(p => `${p[0]},${p[1]}`).join(' ') - ]; - }, [cornerRadius, height, sides, width]); - - usePolygonAnchor(polygonPoints); - - return cornerRadius ? ( - - ) : ( - - ); -}; - -export default SidedShape; diff --git a/packages/react-topology/src/components/nodes/shapes/Stadium.tsx b/packages/react-topology/src/components/nodes/shapes/Stadium.tsx deleted file mode 100644 index 24c5a691451..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Stadium.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import * as React from 'react'; -import { useSvgAnchor } from '../../../behavior'; -import { getHullPath, ShapeProps } from './shapeUtils'; -import { PointTuple } from '../../../types'; -import { useCombineRefs } from '../../../utils'; - -const getStadiumPoints = (width: number, radius: number): PointTuple[] => [ - [radius, radius], - [width - radius, radius], - [width - radius, radius], - [radius, radius] -]; - -const Stadium: React.FunctionComponent = ({ - className = css(styles.topologyNodeBackground), - width, - height, - filter, - dndDropRef -}) => { - const anchorRef = useSvgAnchor(); - const refs = useCombineRefs(dndDropRef, anchorRef); - const points = React.useMemo(() => getHullPath(getStadiumPoints(width, height / 2), height / 2), [height, width]); - - return ; -}; - -export default Stadium; diff --git a/packages/react-topology/src/components/nodes/shapes/Trapezoid.tsx b/packages/react-topology/src/components/nodes/shapes/Trapezoid.tsx deleted file mode 100644 index 74b892aa461..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/Trapezoid.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import * as React from 'react'; -import { PointTuple } from '../../../types'; -import { getHullPath, TRAPEZOID_CORNER_RADIUS, ShapeProps } from './shapeUtils'; -import { usePolygonAnchor } from '../../../behavior'; - -const TOP_INSET_AMOUNT = 1 / 8; - -const getTrapezoidPoints = (width: number, height: number, padding: number, outline: boolean = false): PointTuple[] => { - const yPadding = outline ? 0 : padding; - const topXPadding = outline ? padding / 4 : padding; - const bottomXPadding = outline ? -padding / 4 : padding; - - return [ - [width * TOP_INSET_AMOUNT + topXPadding, yPadding], - [width - width * TOP_INSET_AMOUNT - topXPadding, yPadding], - [width - bottomXPadding, height - yPadding], - [bottomXPadding, height - yPadding] - ]; -}; - -type TrapezoidProps = ShapeProps & { - cornerRadius?: number; -}; - -const Trapezoid: React.FunctionComponent = ({ - className = css(styles.topologyNodeBackground), - width, - height, - filter, - cornerRadius = TRAPEZOID_CORNER_RADIUS, - dndDropRef -}) => { - const [polygonPoints, points] = React.useMemo(() => { - const polygonPoints: PointTuple[] = getTrapezoidPoints(width, height, cornerRadius, true); - - const path = cornerRadius - ? getHullPath(getTrapezoidPoints(width, height, cornerRadius), cornerRadius) - : polygonPoints.map(p => `${p[0]},${p[1]}`).join(' '); - - return [polygonPoints, path]; - }, [height, cornerRadius, width]); - - usePolygonAnchor(polygonPoints); - - return cornerRadius ? ( - - ) : ( - - ); -}; - -export default Trapezoid; diff --git a/packages/react-topology/src/components/nodes/shapes/index.ts b/packages/react-topology/src/components/nodes/shapes/index.ts deleted file mode 100644 index 2b2a65f1b1b..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { default as Ellipse } from './Ellipse'; -export { default as Hexagon } from './Hexagon'; -export { default as Octagon } from './Octagon'; -export { default as Rectangle } from './Rectangle'; -export { default as Rhombus } from './Rhombus'; -export { default as Stadium } from './Stadium'; -export { default as Trapezoid } from './Trapezoid'; -export { default as SidedShape } from './SidedShape'; -export * from './shapeUtils'; diff --git a/packages/react-topology/src/components/nodes/shapes/shapeUtils.ts b/packages/react-topology/src/components/nodes/shapes/shapeUtils.ts deleted file mode 100644 index 12e3d5d751c..00000000000 --- a/packages/react-topology/src/components/nodes/shapes/shapeUtils.ts +++ /dev/null @@ -1,162 +0,0 @@ -import * as React from 'react'; -import { Node, NodeShape, PointTuple, TopologyQuadrant } from '../../../types'; -import { polygonHull } from 'd3-polygon'; -import { hullPath, pointTuplesToPath } from '../../../utils'; -import { Ellipse, Hexagon, Octagon, Rectangle, Trapezoid, Rhombus, Stadium } from './index'; - -const TWO_PI = Math.PI * 2; - -export const HEXAGON_CORNER_RADIUS = 6; -export const OCTAGON_CORNER_RADIUS = 4; -export const RHOMBUS_CORNER_RADIUS = 10; -export const TRAPEZOID_CORNER_RADIUS = 10; - -export const LOWER_LEFT_RADIANS = (3 * Math.PI) / 4; -export const LOWER_RIGHT_RADIANS = Math.PI / 4; -export const UPPER_LEFT_RADIANS = (5 * Math.PI) / 4; -export const UPPER_RIGHT_RADIANS = (7 * Math.PI) / 4; - -export const DEFAULT_DECORATOR_RADIUS = 12; -export const DEFAULT_DECORATOR_PADDING = 4; - -export interface ShapeProps { - className?: string; - element: Node; - width: number; - height: number; - filter?: string; - sides?: number; - cornerRadius?: number; - dndDropRef?: (node: SVGElement | null) => void; -} - -const quadrantRadians = (quadrant: TopologyQuadrant): number => { - switch (quadrant) { - case TopologyQuadrant.upperRight: - return UPPER_RIGHT_RADIANS; - case TopologyQuadrant.lowerRight: - return LOWER_RIGHT_RADIANS; - case TopologyQuadrant.upperLeft: - return UPPER_LEFT_RADIANS; - case TopologyQuadrant.lowerLeft: - return LOWER_LEFT_RADIANS; - } - return UPPER_RIGHT_RADIANS; -}; - -export const getPointsForSides = (numSides: number, size: number, padding = 0): PointTuple[] => { - const points: PointTuple[] = []; - const angle = TWO_PI / numSides; - const radius = size / 2; - - for (let point = 0; point < numSides; point++) { - points.push([ - radius + (radius - padding) * Math.cos(angle * point), - radius + (radius - padding) * Math.sin(angle * point) - ]); - } - - return points; -}; - -export const getHullPath = (points: PointTuple[], padding: number): string => { - const hullPoints: PointTuple[] = polygonHull(points); - return hullPath(hullPoints, padding); -}; -export const getPathForSides = (numSides: number, size: number, padding = 0): string => { - const points = getPointsForSides(numSides, size, padding); - if (!padding) { - return pointTuplesToPath(points); - } - - return getHullPath(points, padding); -}; - -export const getShapeComponent = (node: Node): React.FunctionComponent => { - switch (node.getNodeShape()) { - case NodeShape.circle: - case NodeShape.ellipse: - return Ellipse; - case NodeShape.stadium: - return Stadium; - case NodeShape.rhombus: - return Rhombus; - case NodeShape.trapezoid: - return Trapezoid; - case NodeShape.rect: - return Rectangle; - case NodeShape.hexagon: - return Hexagon; - case NodeShape.octagon: - return Octagon; - default: - return Ellipse; - } -}; - -export const getDefaultShapeDecoratorCenter = (quadrant: TopologyQuadrant, node: Node): { x: number; y: number } => { - const { width, height } = node.getDimensions(); - const shape = node.getNodeShape(); - const nodeCenterX = width / 2; - const nodeCenterY = height / 2; - let deltaX = width / 2; - let deltaY = height / 2; - - switch (shape) { - case NodeShape.circle: - case NodeShape.ellipse: - return { - x: nodeCenterX + Math.cos(quadrantRadians(quadrant)) * deltaX, - y: nodeCenterY + Math.sin(quadrantRadians(quadrant)) * deltaY - }; - case NodeShape.rect: - break; - case NodeShape.rhombus: - deltaX = width / 3; - deltaY = height / 3; - break; - case NodeShape.trapezoid: - if (quadrant === TopologyQuadrant.upperRight || quadrant === TopologyQuadrant.upperLeft) { - deltaX = deltaX * 0.875 - TRAPEZOID_CORNER_RADIUS; - } - break; - case NodeShape.hexagon: - deltaX = deltaX * 0.75 - HEXAGON_CORNER_RADIUS; - deltaY = deltaY * 0.75; - break; - case NodeShape.octagon: - deltaX = deltaX - OCTAGON_CORNER_RADIUS; - deltaY = deltaY - height / 5; - break; - default: - break; - } - - switch (quadrant) { - case TopologyQuadrant.upperRight: - return { - x: nodeCenterX + deltaX, - y: nodeCenterY - deltaY - }; - case TopologyQuadrant.lowerRight: - return { - x: nodeCenterX + deltaX, - y: nodeCenterY + deltaY - }; - case TopologyQuadrant.upperLeft: - return { - x: nodeCenterX - deltaX, - y: nodeCenterY - deltaY - }; - case TopologyQuadrant.lowerLeft: - return { - x: nodeCenterX - deltaX, - y: nodeCenterY + deltaY - }; - default: - return { - x: nodeCenterX, - y: nodeCenterY - }; - } -}; diff --git a/packages/react-topology/src/components/popper/Popper.tsx b/packages/react-topology/src/components/popper/Popper.tsx deleted file mode 100644 index 6e33b9f0b81..00000000000 --- a/packages/react-topology/src/components/popper/Popper.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import * as React from 'react'; -import PopperJS, { PopperOptions } from 'popper.js'; -import useCombineRefs from '../../utils/useCombineRefs'; -import Portal from './Portal'; - -// alignment with PopperJS reference API -interface PopperJSReference { - getBoundingClientRect: PopperJS['reference']['getBoundingClientRect']; - clientWidth: number; - clientHeight: number; -} - -interface ClientRectProp { - x: number; - y: number; - width?: number; - height?: number; -} - -type Reference = Element | PopperJSReference | ClientRectProp; - -class VirtualReference implements PopperJSReference { - private rect: ClientRect; - - constructor({ height = 0, width = 0, x, y }: ClientRectProp) { - this.rect = { - bottom: y + height, - height, - left: x, - right: x + width, - top: y, - width, - x, - y, - toJSON: () => {} - }; - } - - getBoundingClientRect(): ClientRect { - return this.rect; - } - - get clientWidth(): number { - return this.rect.width || 0; - } - - get clientHeight(): number { - return this.rect.height || 0; - } -} - -const getReference = (reference: Reference): PopperJSReference => - 'getBoundingClientRect' in reference ? reference : new VirtualReference(reference); - -interface PopperProps { - children?: React.ReactNode; - closeOnEsc?: boolean; - closeOnOutsideClick?: boolean; - container?: React.ComponentProps['container']; - className?: string; - open?: boolean; - onRequestClose?: (e?: Event) => void; - placement?: - | 'bottom-end' - | 'bottom-start' - | 'bottom' - | 'left-end' - | 'left-start' - | 'left' - | 'right-end' - | 'right-start' - | 'right' - | 'top-end' - | 'top-start' - | 'top'; - popperOptions?: PopperOptions; - popperRef?: React.Ref; - reference: Reference | (() => Reference); - zIndex?: number; - returnFocus?: boolean; -} - -const DEFAULT_POPPER_OPTIONS: PopperOptions = {}; - -const Popper: React.FunctionComponent = ({ - children, - container, - className, - open, - placement = 'bottom-start', - reference, - popperOptions = DEFAULT_POPPER_OPTIONS, - closeOnEsc, - closeOnOutsideClick, - onRequestClose, - popperRef: popperRefIn, - zIndex = 9999, - returnFocus -}) => { - const controlled = typeof open === 'boolean'; - const openProp = controlled ? open || false : true; - const nodeRef = React.useRef(); - const popperRef = React.useRef(null); - const popperRefs = useCombineRefs(popperRef, popperRefIn); - const [isOpen, setOpenState] = React.useState(openProp); - const focusRef = React.useRef(); - const onRequestCloseRef = React.useRef(onRequestClose); - onRequestCloseRef.current = onRequestClose; - - const setOpen = React.useCallback( - (newOpen: boolean) => { - if (returnFocus && newOpen !== isOpen) { - if (newOpen) { - if (document.activeElement) { - focusRef.current = document.activeElement; - } - } else if (focusRef.current instanceof HTMLElement && focusRef.current.ownerDocument) { - focusRef.current.focus(); - } - } - setOpenState(newOpen); - }, - [returnFocus, isOpen] - ); - - React.useEffect(() => { - setOpen(openProp); - }, [openProp, setOpen]); - - const onKeyDown = React.useCallback( - (e: KeyboardEvent) => { - if (e.key === 'Escape') { - controlled ? onRequestCloseRef.current && onRequestCloseRef.current() : setOpen(false); - } - }, - [controlled, setOpen] - ); - - const onClickOutside = React.useCallback( - (e: Event) => { - if (!nodeRef.current || (e.target instanceof Node && !nodeRef.current.contains(e.target))) { - controlled ? onRequestCloseRef.current && onRequestCloseRef.current(e) : setOpen(false); - } - }, - [controlled, setOpen] - ); - - const destroy = React.useCallback(() => { - if (popperRef.current) { - popperRef.current.destroy(); - popperRefs(null); - document.removeEventListener('keydown', onKeyDown, true); - document.removeEventListener('mousedown', onClickOutside, true); - document.removeEventListener('touchstart', onClickOutside, true); - } - }, [onClickOutside, onKeyDown, popperRefs]); - - const initialize = React.useCallback(() => { - if (!nodeRef.current || !reference || !isOpen) { - return; - } - - destroy(); - - popperRefs( - new PopperJS(getReference(typeof reference === 'function' ? reference() : reference), nodeRef.current, { - placement, - ...popperOptions, - modifiers: { - preventOverflow: { - boundariesElement: 'viewport' - }, - ...popperOptions.modifiers - } - }) - ); - - // init document listenerrs - if (closeOnEsc) { - document.addEventListener('keydown', onKeyDown, true); - } - if (closeOnOutsideClick) { - document.addEventListener('mousedown', onClickOutside, true); - document.addEventListener('touchstart', onClickOutside, true); - } - }, [ - popperRefs, - reference, - isOpen, - destroy, - placement, - popperOptions, - closeOnEsc, - closeOnOutsideClick, - onKeyDown, - onClickOutside - ]); - - const nodeRefCallback = React.useCallback>( - node => { - nodeRef.current = node; - initialize(); - }, - [initialize] - ); - - React.useEffect(() => { - initialize(); - }, [initialize]); - - React.useEffect( - () => () => { - destroy(); - }, - [destroy] - ); - - React.useEffect(() => { - if (!isOpen) { - destroy(); - } - }, [destroy, isOpen]); - - return isOpen ? ( - -
- {children} -
-
- ) : null; -}; - -export default Popper; diff --git a/packages/react-topology/src/components/popper/Portal.tsx b/packages/react-topology/src/components/popper/Portal.tsx deleted file mode 100644 index c42be825696..00000000000 --- a/packages/react-topology/src/components/popper/Portal.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { useIsomorphicLayoutEffect } from '@patternfly/react-core'; - -type GetContainer = Element | null | undefined | (() => Element); - -interface PortalProps { - children?: React.ReactNode; - container?: GetContainer; -} - -const getContainer = (container: GetContainer): Element | null | undefined => - typeof container === 'function' ? container() : container; - -const Portal: React.FunctionComponent = ({ children, container }) => { - const [containerNode, setContainerNode] = React.useState(); - - useIsomorphicLayoutEffect(() => { - setContainerNode(getContainer(container) || document.body); - }, [container]); - - return containerNode ? ReactDOM.createPortal(children, containerNode) : null; -}; - -export default Portal; diff --git a/packages/react-topology/src/components/popper/index.ts b/packages/react-topology/src/components/popper/index.ts deleted file mode 100644 index 74150c02ef8..00000000000 --- a/packages/react-topology/src/components/popper/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as Popper } from './Popper'; diff --git a/packages/react-topology/src/components/svg/SvgDropShadowFilter.tsx b/packages/react-topology/src/components/svg/SvgDropShadowFilter.tsx deleted file mode 100644 index 5755a5e6d97..00000000000 --- a/packages/react-topology/src/components/svg/SvgDropShadowFilter.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import * as React from 'react'; -// eslint-disable-next-line patternfly-react/import-tokens-icons -import { global_palette_black_1000 as globalBlack1000 } from '@patternfly/react-tokens/dist/js/global_palette_black_1000'; -import { SVGDefs } from '../defs'; - -interface SvgDropShadowFilterProps { - // The unique ID that identifies the filter. - // It is also used to uniquely identify the def entry to prevent duplicates. - id: string; - dx?: number; - dy?: number; - stdDeviation?: number; - floodOpacity?: number; - floodColor?: string; -} - -const SvgDropShadowFilter: React.FunctionComponent = ({ - id, - dx = 0, - dy = 1, - stdDeviation = 2, - floodColor = globalBlack1000.value, - floodOpacity = 0.2 -}) => { - if (window.navigator.userAgent.includes('Edge')) { - // feDropShadow is not supported by Edge - return ( - - - - - - - - - - - - - ); - } - - return ( - - - - - - ); -}; - -export default SvgDropShadowFilter; diff --git a/packages/react-topology/src/const.ts b/packages/react-topology/src/const.ts deleted file mode 100644 index 65c2981972a..00000000000 --- a/packages/react-topology/src/const.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const ATTR_DATA_KIND = 'data-kind'; -export const ATTR_DATA_TYPE = 'data-type'; -export const ATTR_DATA_ID = 'data-id'; - -export const TOP_LAYER = 'top'; -export const GROUPS_LAYER = 'groups'; -export const DEFAULT_LAYER = 'default'; -export const BOTTOM_LAYER = 'bottom'; - -export const DEFAULT_LAYERS = [BOTTOM_LAYER, GROUPS_LAYER, DEFAULT_LAYER, TOP_LAYER]; diff --git a/packages/react-topology/src/declarations.d.ts b/packages/react-topology/src/declarations.d.ts deleted file mode 100644 index 7a83cc099ad..00000000000 --- a/packages/react-topology/src/declarations.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'point-in-svg-path' { - export const pointInSvgPath: (d: string, x: number, y: number) => boolean; -} diff --git a/packages/react-topology/src/elements/BaseEdge.ts b/packages/react-topology/src/elements/BaseEdge.ts deleted file mode 100644 index e75e6bd10ae..00000000000 --- a/packages/react-topology/src/elements/BaseEdge.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { computed, observable } from 'mobx'; -import Point from '../geom/Point'; -import { Anchor, AnchorEnd, Edge, EdgeAnimationSpeed, EdgeModel, EdgeStyle, ModelKind, Node } from '../types'; -import { getTopCollapsedParent } from '../utils'; -import BaseElement from './BaseElement'; - -export default class BaseEdge extends BaseElement - implements Edge { - @observable.ref - private source?: Node; - - @observable.ref - private target?: Node; - - @observable.ref - private edgeStyle?: EdgeStyle; - - @observable.ref - private animationSpeed?: EdgeAnimationSpeed; - - @observable.shallow - private bendpoints?: Point[]; - - @observable.ref - private startPoint?: Point; - - @observable.ref - private endPoint?: Point; - - @computed - private get sourceAnchor(): Anchor { - return this.getSourceAnchorNode().getAnchor(AnchorEnd.source, this.getType()); - } - - @computed - private get targetAnchor(): Anchor { - return this.getTargetAnchorNode().getAnchor(AnchorEnd.target, this.getType()); - } - - getKind(): ModelKind { - return ModelKind.edge; - } - - getSource(): Node { - if (!this.source) { - throw new Error(`Edge with ID '${this.getId()}' has no source.`); - } - return this.source; - } - - setSource(source: Node) { - this.source = source; - } - - getTarget(): Node { - if (!this.target) { - throw new Error(`Edge with ID '${this.getId()}' has no target.`); - } - return this.target; - } - - setTarget(target: Node) { - this.target = target; - } - - getEdgeStyle(): EdgeStyle { - return this.edgeStyle || EdgeStyle.default; - } - - setEdgeStyle(edgeStyle: EdgeStyle) { - this.edgeStyle = edgeStyle; - } - - getEdgeAnimationSpeed(): EdgeAnimationSpeed { - return this.animationSpeed || EdgeAnimationSpeed.none; - } - - setEdgeAnimationSpeed(animationSpeed?: EdgeAnimationSpeed) { - this.animationSpeed = animationSpeed || EdgeAnimationSpeed.none; - } - - getSourceAnchorNode(): Node { - if (!this.source) { - throw new Error(`Edge with ID '${this.getId()}' has no source.`); - } - return getTopCollapsedParent(this.source); - } - - getTargetAnchorNode(): Node { - if (!this.target) { - throw new Error(`Edge with ID '${this.getId()}' has no target.`); - } - return getTopCollapsedParent(this.target); - } - - getBendpoints(): Point[] { - return this.bendpoints || []; - } - - setBendpoints(points: Point[]) { - this.bendpoints = points; - } - - removeBendpoint(point: Point | number): void { - if (this.bendpoints) { - if (typeof point === 'number') { - this.bendpoints.splice(point, 1); - } else { - const idx = this.bendpoints.indexOf(point); - if (idx !== -1) { - this.bendpoints.splice(idx, 1); - } - } - } - } - - getStartPoint(): Point { - if (this.startPoint) { - return this.startPoint; - } - const bendpoints = this.getBendpoints(); - let referencePoint: Point; - if (bendpoints && bendpoints.length > 0) { - [referencePoint] = bendpoints; - } else if (this.endPoint) { - referencePoint = this.endPoint; - } else { - referencePoint = this.targetAnchor.getReferencePoint(); - } - return this.sourceAnchor.getLocation(referencePoint); - } - - setStartPoint(x?: number, y?: number): void { - if (x == null || y == null) { - this.startPoint = undefined; - } else { - this.startPoint = new Point(x, y); - } - } - - getEndPoint(): Point { - if (this.endPoint) { - return this.endPoint; - } - const bendpoints = this.getBendpoints(); - let referencePoint: Point; - if (bendpoints && bendpoints.length > 0) { - referencePoint = bendpoints[bendpoints.length - 1]; - } else if (this.startPoint) { - referencePoint = this.startPoint; - } else { - referencePoint = this.sourceAnchor.getReferencePoint(); - } - return this.targetAnchor.getLocation(referencePoint); - } - - setEndPoint(x?: number, y?: number): void { - if (x == null || y == null) { - this.endPoint = undefined; - } else { - this.endPoint = new Point(x, y); - } - } - - setModel(model: E): void { - super.setModel(model); - if (model.source) { - const node = this.getController().getNodeById(model.source); - if (!node) { - throw new Error(`No source node found with ID '${model.source}'.`); - } - this.source = node; - } - if (model.target) { - const node = this.getController().getNodeById(model.target); - if (!node) { - throw new Error(`No target node found with ID '${model.target}'.`); - } - this.target = node; - } - if ('edgeStyle' in model) { - this.edgeStyle = model.edgeStyle; - } - if ('animationSpeed' in model) { - this.animationSpeed = model.animationSpeed; - } - if ('bendpoints' in model) { - this.bendpoints = model.bendpoints ? model.bendpoints.map(b => new Point(b[0], b[1])) : []; - } - } - - toModel(): EdgeModel { - return { - ...super.toModel(), - source: this.getSource() ? this.getSource().getId() : undefined, - target: this.getTarget() ? this.getTarget().getId() : undefined, - edgeStyle: this.edgeStyle, - animationSpeed: this.animationSpeed, - bendpoints: this.getBendpoints().map(bp => [bp.x, bp.y]) - }; - } -} diff --git a/packages/react-topology/src/elements/BaseElement.ts b/packages/react-topology/src/elements/BaseElement.ts deleted file mode 100644 index f723a1213d8..00000000000 --- a/packages/react-topology/src/elements/BaseElement.ts +++ /dev/null @@ -1,306 +0,0 @@ -import { observable, computed } from 'mobx'; -import * as _ from 'lodash'; -import { - ElementModel, - Graph, - GraphElement, - isGraph, - isNode, - Controller, - ModelKind, - ADD_CHILD_EVENT, - REMOVE_CHILD_EVENT, - ELEMENT_VISIBILITY_CHANGE_EVENT -} from '../types'; -import Stateful from '../utils/Stateful'; -import { Translatable } from '../geom/types'; - -export default abstract class BaseElement extends Stateful - implements GraphElement { - private id: string = ''; - - @observable - private type: string = ''; - - @observable.ref - private data?: D; - - @observable.ref - private parent?: GraphElement; - - @observable - private visible: boolean = true; - - @observable.shallow - private children: GraphElement[] = []; - - @observable.ref - private controller?: Controller; - - @observable - private label?: string; - - @observable - private style: any = {}; - - abstract getKind(): ModelKind; - - @computed({ equals: _.isEqual }) - private get ordering(): number[] { - if (!this.parent) { - return []; - } - const idx = this.parent.getChildren().indexOf(this); - const result = [...this.parent.getOrderKey(), idx]; - return result; - } - - getLabel(): string { - return this.label || ''; - } - - setLabel(label: string): void { - this.label = label; - } - - getOrderKey(): number[] { - return this.ordering; - } - - hasController(): boolean { - return this.controller !== undefined; - } - - getController(): Controller { - if (!this.controller) { - throw new Error(`GraphElement with ID '${this.getId()}' has no controller.`); - } - return this.controller; - } - - setController(controller: Controller): void { - this.controller = controller; - } - - getGraph(): Graph { - // TODO fix project eslint rules - // eslint-disable-next-line @typescript-eslint/no-this-alias - let p: GraphElement = this; - while (!isGraph(p)) { - p = p.getParent(); - } - return p; - } - - getParent(): GraphElement { - if (!this.parent) { - throw new Error(`GraphElement with ID '${this.getId()}' has no parent.`); - } - return this.parent; - } - - setParent(parent: GraphElement): void { - if (this.parent !== parent) { - if (this.parent) { - this.remove(); - } - this.parent = parent; - } - } - - hasParent(): boolean { - return this.parent !== undefined; - } - - getId(): string { - return this.id; - } - - setId(id: string): void { - this.id = id; - } - - getType(): string { - return this.type; - } - - setType(type: string): void { - this.type = type; - } - - setVisible(visible: boolean): void { - if (this.visible !== visible) { - this.visible = visible; - if (this.controller) { - this.controller.fireEvent(ELEMENT_VISIBILITY_CHANGE_EVENT, { visible, target: this }); - } - } - } - - isVisible(): boolean { - return ( - this.visible && - (!this.parent || (this.parent.isVisible() && (!isNode(this.parent) || !this.parent.isCollapsed()))) - ); - } - - getData(): D | undefined { - return this.data; - } - - setData(data: D | undefined): void { - this.data = data; - } - - getStyle(): T { - return this.style; - } - - getChildren(): GraphElement[] { - return this.children; - } - - insertChild(child: GraphElement, index: number) { - if (this.children.length === 0 || index >= this.children.length || this.children[index] !== child) { - const idx = this.children.indexOf(child); - if (idx !== -1) { - this.children.splice(idx, 1); - this.children.splice(index, 0, child); - } else { - // remove from old parent - child.remove(); - child.setParent(this); - this.children.splice(index, 0, child); - - if (this.controller) { - this.controller.fireEvent(ADD_CHILD_EVENT, { target: this, child }); - } - } - } - } - - appendChild(child: GraphElement) { - if (this.children.length === 0 || this.children[this.children.length - 1] !== child) { - const idx = this.children.indexOf(child); - if (idx !== -1) { - this.children.splice(idx, 1); - this.children.push(child); - } else { - // remove from old parent - child.remove(); - child.setParent(this); - this.children.push(child); - - if (this.controller) { - this.controller.fireEvent(ADD_CHILD_EVENT, { target: this, child }); - } - } - } - } - - removeChild(child: GraphElement) { - if (this.children) { - const idx = this.children.indexOf(child); - if (idx !== -1) { - this.children.splice(idx, 1); - child.setParent(undefined); - - if (this.controller) { - this.controller.fireEvent(REMOVE_CHILD_EVENT, { target: this, child }); - } - } - } - } - - remove(): void { - if (this.parent) { - this.parent.removeChild(this); - } - } - - setModel(model: E): void { - if ('type' in model) { - this.setType(model.type); - } - if ('visible' in model) { - this.setVisible(!!model.visible); - } - if (Array.isArray(model.children)) { - const controller = this.getController(); - - const childElements = model.children.map(id => { - const element = controller.getElementById(id); - if (!element) { - throw new Error(`No element found with ID '${id}'.`); - } - return element; - }); - - // remove children - _.difference(this.children, childElements).forEach(child => this.removeChild(child)); - - // add children - const toAdd = _.difference(childElements, this.children); - toAdd.reverse().forEach(child => this.insertChild(child, 0)); - } - if ('data' in model) { - this.data = model.data; - } - if ('label' in model) { - this.label = model.label; - } - if ('style' in model) { - _.merge(this.style, model.style); - } - } - - toModel(): ElementModel { - return { - id: this.getId(), - type: this.getType(), - label: this.getLabel(), - visible: this.isVisible(), - children: this.getChildren().map(c => c.getId()), - data: this.getData(), - style: this.getStyle() - }; - } - - raise(): void { - const { parent } = this; - if (parent) { - parent.appendChild(this); - parent.raise(); - } - } - - translateToAbsolute(t: Translatable): void { - this.translateToParent(t); - const { parent } = this; - if (parent) { - parent.translateToAbsolute(t); - } - } - - translateFromAbsolute(t: Translatable): void { - const { parent } = this; - if (parent) { - parent.translateFromAbsolute(t); - } - this.translateFromParent(t); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - translateToParent(t: Translatable): void { - // nothing to do - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - translateFromParent(t: Translatable): void { - // nothing to do - } - - destroy(): void { - // nothing to do - } -} diff --git a/packages/react-topology/src/elements/BaseGraph.ts b/packages/react-topology/src/elements/BaseGraph.ts deleted file mode 100644 index 49baec2f125..00000000000 --- a/packages/react-topology/src/elements/BaseGraph.ts +++ /dev/null @@ -1,370 +0,0 @@ -import { computed, observable } from 'mobx'; -import Rect from '../geom/Rect'; -import Point from '../geom/Point'; -import Dimensions from '../geom/Dimensions'; -import { DEFAULT_LAYERS } from '../const'; -import { - Edge, - Graph, - GRAPH_POSITION_CHANGE_EVENT, - GraphModel, - isEdge, - isNode, - Layout, - ModelKind, - Node, - NodeModel, - ScaleExtent, - ScaleDetailsLevel, - ScaleDetailsThresholds -} from '../types'; -import BaseElement from './BaseElement'; - -export default class BaseGraph extends BaseElement - implements Graph { - @observable.ref - private layers = DEFAULT_LAYERS; - - @observable - private scale = 1; - - @observable - private layoutType?: string; - - @observable.ref - private dimensions = new Dimensions(); - - @observable.ref - private position = new Point(); - - private currentLayout?: Layout; - - @observable.ref - private scaleExtent: ScaleExtent = [0.25, 4]; - - @computed - private get detailsLevel(): ScaleDetailsLevel { - if (!this.scaleDetailsThresholds) { - return ScaleDetailsLevel.high; - } - if (this.scale <= this.scaleDetailsThresholds.low) { - return ScaleDetailsLevel.low; - } else if (this.scale <= this.scaleDetailsThresholds.medium) { - return ScaleDetailsLevel.medium; - } - return ScaleDetailsLevel.high; - } - - @computed - private get edges(): Edge[] { - return this.getChildren().filter(isEdge); - } - - @computed - private get nodes(): Node[] { - return this.getChildren().filter(isNode); - } - - @observable.ref - private scaleDetailsThresholds: ScaleDetailsThresholds = { - low: 0.3, - medium: 0.5 - }; - - getKind(): ModelKind { - return ModelKind.graph; - } - - getLayers(): string[] { - return this.layers; - } - - setLayers(layers: string[]): void { - this.layers = layers; - } - - getScaleExtent(): ScaleExtent { - return this.scaleExtent; - } - - setScaleExtent(scaleExtent: ScaleExtent): void { - try { - this.getController().fireEvent(GRAPH_POSITION_CHANGE_EVENT, { graph: this }); - // eslint-disable-next-line no-empty - } catch (e) {} - this.scaleExtent = scaleExtent; - } - - getDetailsLevelThresholds(): ScaleDetailsThresholds | undefined { - return this.scaleDetailsThresholds; - } - - setDetailsLevelThresholds(settings: ScaleDetailsThresholds | undefined): void { - this.scaleDetailsThresholds = settings; - } - - getDetailsLevel(): ScaleDetailsLevel { - return this.detailsLevel; - } - - getBounds(): Rect { - const { - position: { x, y }, - dimensions: { width, height } - } = this; - return new Rect(x, y, width, height); - } - - setBounds(bounds: Rect): void { - const { width, height } = this.dimensions; - if (bounds.width !== width || bounds.height !== height) { - this.dimensions = new Dimensions(bounds.width, bounds.height); - } - const { x, y } = this.position; - if (bounds.x !== x || bounds.y !== y) { - this.setPosition(new Point(bounds.x, bounds.y)); - } - } - - getPosition(): Point { - return this.position; - } - - setPosition(point: Point): void { - try { - this.getController().fireEvent(GRAPH_POSITION_CHANGE_EVENT, { graph: this }); - // eslint-disable-next-line no-empty - } catch (e) {} - this.position = point; - } - - getDimensions(): Dimensions { - return this.dimensions; - } - - setDimensions(dimensions: Dimensions): void { - this.dimensions = dimensions; - } - - getNodes(): Node[] { - return this.nodes; - } - - getEdges(): Edge[] { - return this.edges; - } - - getLayout(): string | undefined { - return this.layoutType; - } - - setLayout(layout: string | undefined): void { - if (layout === this.layoutType) { - return; - } - - if (this.currentLayout) { - this.currentLayout.destroy(); - } - - this.layoutType = layout; - this.currentLayout = layout ? this.getController().getLayout(layout) : undefined; - } - - layout(): void { - if (this.currentLayout) { - this.currentLayout.layout(); - } - } - - getScale(): number { - return this.scale; - } - - setScale(scale: number): void { - try { - this.getController().fireEvent(GRAPH_POSITION_CHANGE_EVENT, { graph: this }); - // eslint-disable-next-line no-empty - } catch (e) {} - this.scale = scale; - } - - reset(): void { - if (this.currentLayout) { - this.currentLayout.stop(); - } - this.setScale(1); - this.setPosition(new Point(0, 0)); - } - - scaleBy(scale: number, location?: Point): void { - const b = this.getBounds(); - let { x, y } = b; - const c = location || b.getCenter().translate(-x, -y); - x = (c.x - x) / this.scale; - y = (c.y - y) / this.scale; - const newScale = Math.max(Math.min(this.scale * scale, this.scaleExtent[1]), this.scaleExtent[0]); - this.setScale(newScale); - x = c.x - x * this.scale; - y = c.y - y * this.scale; - this.setPosition(new Point(x, y)); - } - - fit(padding = 0): void { - let rect: Rect | undefined; - this.getNodes().forEach(c => { - const b = c.getBounds(); - if (!rect) { - rect = b.clone(); - } else { - rect.union(b); - } - }); - if (!rect) { - return; - } - - const { width, height } = rect; - - if (width === 0 || height === 0) { - return; - } - - const { width: fullWidth, height: fullHeight } = this.getDimensions(); - const midX = rect.x + width / 2; - const midY = rect.y + height / 2; - - // set the max scale to be the current zoom level or 1 - const maxScale = Math.max(this.getScale(), 1); - - // compute the scale - const scale = Math.min( - 1 / Math.max(width / Math.max(1, fullWidth - padding), height / Math.max(1, fullHeight - padding)), - maxScale - ); - - // translate to center - const tx = fullWidth / 2 - midX * scale; - const ty = fullHeight / 2 - midY * scale; - - // TODO should scale and bound be kept in a single geom Transform object instead of separately? - this.setScale(scale); - this.setPosition(new Point(tx, ty)); - } - - panIntoView = ( - nodeElement: Node, - { offset = 0, minimumVisible = 0 }: { offset?: number; minimumVisible?: number } = {} - ): void => { - if (!nodeElement) { - return; - } - const { x: viewX, y: viewY, width: viewWidth, height: viewHeight } = this.getBounds(); - const boundingBox = nodeElement - .getBounds() - .clone() - .scale(this.scale) - .translate(viewX, viewY); - const { x, y, width, height } = boundingBox; - let move = false; - const panOffset = offset * this.scale; - const minVisibleSize = minimumVisible * this.scale; - - const newLocation = { - x: viewX, - y: viewY - }; - - if (x + width - minVisibleSize < 0) { - newLocation.x -= x - panOffset; - move = true; - } - if (x + minVisibleSize > viewWidth) { - newLocation.x -= x + width - viewWidth + panOffset; - move = true; - } - if (y + height - minVisibleSize < 0) { - newLocation.y -= y - panOffset; - move = true; - } - if (y + minVisibleSize > viewHeight) { - newLocation.y -= y + height - viewHeight + panOffset; - move = true; - } - - if (move) { - this.setBounds(new Rect(newLocation.x, newLocation.y, viewWidth, viewHeight)); - } - }; - - isNodeInView(element: Node, { padding = 0 }): boolean { - const graph = element.getGraph(); - const { x: viewX, y: viewY, width: viewWidth, height: viewHeight } = graph.getBounds(); - const { x, y, width, height } = element - .getBounds() - .clone() - .scale(this.scale) - .translate(viewX, viewY); - - return x + width > -padding && x < viewWidth + padding && y + height > -padding && y < viewHeight + padding; - } - - setModel(model: E): void { - super.setModel(model); - - if ('layers' in model && model.layers) { - this.setLayers(model.layers); - } - if ('layout' in model) { - this.setLayout(model.layout); - } - if (model.scaleExtent && model.scaleExtent.length === 2) { - this.setScaleExtent(model.scaleExtent); - } - if ('scale' in model && typeof model.scale === 'number') { - this.setScale(+model.scale); - } - let p: Point | undefined; - if ('x' in model && model.x != null) { - if (!p) { - p = this.position.clone(); - } - p.x = model.x; - } - if ('y' in model && model.y != null) { - if (!p) { - p = this.position.clone(); - } - p.y = model.y; - } - if (p) { - this.setPosition(p); - } - } - - toModel(): GraphModel { - return { - ...super.toModel(), - layout: this.getLayout(), - x: this.getPosition().x, - y: this.getPosition().y, - scale: this.getScale(), - scaleExtent: this.getScaleExtent(), - layers: this.getLayers() - }; - } - - translateToAbsolute(): void { - // do nothing - } - - translateFromAbsolute(): void { - // do nothing - } - - destroy(): void { - if (this.currentLayout) { - this.currentLayout.destroy(); - } - } -} diff --git a/packages/react-topology/src/elements/BaseNode.ts b/packages/react-topology/src/elements/BaseNode.ts deleted file mode 100644 index 9623981352c..00000000000 --- a/packages/react-topology/src/elements/BaseNode.ts +++ /dev/null @@ -1,401 +0,0 @@ -import { observable, computed } from 'mobx'; -import { - Node, - Anchor, - NodeModel, - ModelKind, - isNode, - isEdge, - AnchorEnd, - NodeStyle, - NodeShape, - Edge, - GraphElement, - NODE_COLLAPSE_CHANGE_EVENT, - NODE_POSITIONED_EVENT, - NodeStatus, - LabelPosition -} from '../types'; -import CenterAnchor from '../anchors/CenterAnchor'; -import Rect from '../geom/Rect'; -import { Translatable } from '../geom/types'; -import BaseElement from './BaseElement'; -import Dimensions from '../geom/Dimensions'; -import Point from '../geom/Point'; - -const createAnchorKey = (end: AnchorEnd = AnchorEnd.both, type: string = ''): string => `${end}:${type}`; - -export default class BaseNode extends BaseElement - implements Node { - @observable.shallow - private anchors: { [type: string]: Anchor } = { - [createAnchorKey()]: new CenterAnchor(this) - }; - - @observable.ref - private dimensions = new Dimensions(); - - @observable - private dimensionsInitialized = false; - - private positioned = false; - - private uncollapsedCenter: Point = null; - - @observable.ref - private position = new Point(); - - @computed - private get nodes(): Node[] { - if (this.isCollapsed()) { - return []; - } - - return this.getChildren().filter(isNode); - } - - @observable - private group = false; - - @observable - private collapsed = false; - - @observable - private labelPosition = LabelPosition.bottom; - - @observable - private shape: NodeShape | undefined; - - @observable - private status: NodeStatus | undefined; - - @computed - private get groupBounds(): Rect { - const children = this.getChildren() - .filter(isNode) - .filter(n => n.isVisible()); - if (!children.length) { - return this.getInternalBounds(); - } - - let rect: Rect | undefined; - children.forEach(c => { - if (isNode(c)) { - const { padding } = c.getStyle(); - const b = c.getBounds(); - // Currently non-group nodes do not include their padding in the bounds - if (!c.isGroup() && padding) { - b.padding(c.getStyle().padding); - } - if (!rect) { - rect = b.clone(); - } else { - rect.union(b); - } - } - }); - - if (!rect) { - rect = new Rect(); - } - - const { padding } = this.getStyle(); - - return rect.padding(padding); - } - - @computed - private get sourceEdges(): Edge[] { - return this.getGraph() - .getEdges() - .filter(e => e.getSource() === this); - } - - @computed - private get targetEdges(): Edge[] { - return this.getGraph() - .getEdges() - .filter(e => e.getTarget() === this); - } - - getChildren(): GraphElement[] { - if (this.isCollapsed()) { - return super.getChildren().filter(isEdge); - } - return super.getChildren(); - } - - // Return all child leaf nodes regardless of collapse status or child groups' collapsed status - getAllNodeChildren(): Node[] { - return super.getChildren().reduce((total, nexChild) => { - if (isNode(nexChild)) { - total.push(nexChild.isGroup() ? nexChild.getAllNodeChildren() : nexChild); - } - return total; - }, []); - } - - getKind(): ModelKind { - return ModelKind.node; - } - - private getInternalBounds(): Rect { - const { position, dimensions } = this; - return new Rect(position.x, position.y, dimensions.width, dimensions.height); - } - - getBounds(): Rect { - return this.group && !this.collapsed ? this.groupBounds : this.getInternalBounds(); - } - - setBounds(bounds: Rect): void { - const { width, height } = this.dimensions; - if (bounds.width !== width || bounds.height !== height) { - this.dimensions = new Dimensions(bounds.width, bounds.height); - } - const { x, y } = this.position; - if (bounds.x !== x || bounds.y !== y) { - this.setPosition(new Point(bounds.x, bounds.y)); - } - } - - getPosition(): Point { - if (this.isGroup() && this.getChildren().length && !this.collapsed) { - return this.getBounds().getCenter(); - } - return this.position; - } - - updateChildrenPositions(point: Point, prevLocation: Point): void { - const xOffset = point.x - prevLocation.x; - const yOffset = point.y - prevLocation.y; - this.getChildren().forEach(child => { - if (isNode(child)) { - const node = child as Node; - const position = node.getPosition(); - const newPosition = new Point(position.x + xOffset, position.y + yOffset); - node.setPosition(newPosition); - } - }); - } - - setPosition(point: Point): void { - if (this.isGroup() && this.getChildren().length && !this.collapsed) { - const prevLocation = this.getBounds().getCenter(); - this.updateChildrenPositions(point, prevLocation); - return; - } - this.position = point; - this.positioned = true; - try { - this.getController().fireEvent(NODE_POSITIONED_EVENT, { node: this }); - // eslint-disable-next-line no-empty - } catch (e) {} - } - - isPositioned(): boolean { - return this.positioned; - } - - getDimensions(): Dimensions { - return this.dimensions; - } - - setDimensions(dimensions: Dimensions): void { - this.dimensions = dimensions; - this.dimensionsInitialized = true; - } - - isDimensionsInitialized(): boolean { - if (!this.dimensionsInitialized && this.isGroup()) { - const nodes = this.getChildren().filter(isNode); - if (nodes.length === 0) { - return this.dimensionsInitialized; - } - const result = nodes.every(c => c.isDimensionsInitialized()); - if (result) { - this.dimensionsInitialized = true; - } - } - return this.dimensionsInitialized; - } - - getAnchor(end?: AnchorEnd, type?: string): Anchor { - let anchor = this.anchors[createAnchorKey(end, type)]; - if (!anchor && type) { - anchor = this.anchors[createAnchorKey(end)]; - } - if (!anchor && (end === AnchorEnd.source || end === AnchorEnd.target)) { - anchor = this.anchors[createAnchorKey(AnchorEnd.both, type)]; - if (!anchor && type) { - anchor = this.anchors[createAnchorKey(AnchorEnd.both)]; - } - } - return anchor; - } - - setAnchor(anchor: Anchor, end?: AnchorEnd, type?: string): void { - const key = createAnchorKey(end, type); - if (anchor) { - this.anchors[key] = anchor; - } else { - delete this.anchors[key]; - } - } - - getNodes(): Node[] { - return this.nodes; - } - - isGroup(): boolean { - return this.group; - } - - setGroup(group: boolean): void { - this.group = group; - } - - isCollapsed(): boolean { - return this.collapsed; - } - - setCollapsed(collapsed: boolean): void { - if (collapsed !== this.collapsed) { - // Get the location prior to the collapse change and apply it after the collapse. - // This updates the new node(s) location(s) to be what the node was originally, basically - // keeping the nodes ln place so the layout doesn't start fresh (putting the new nodes at 0,0 - // TODO: Update to better position the nodes at a point location rather than relying on the setCenter updating the nodes. - const prevCenter = this.getBounds().getCenter(); - if (!collapsed && this.uncollapsedCenter) { - this.updateChildrenPositions(prevCenter, this.uncollapsedCenter); - this.uncollapsedCenter = null; - this.collapsed = collapsed; - } else { - this.uncollapsedCenter = collapsed ? prevCenter : null; - this.collapsed = collapsed; - this.setBounds(this.getBounds().setCenter(prevCenter.x, prevCenter.y)); - } - this.getController().fireEvent(NODE_COLLAPSE_CHANGE_EVENT, { node: this }); - } - } - - getLabelPosition(): LabelPosition { - return this.labelPosition; - } - - setLabelPosition(position: LabelPosition): void { - this.labelPosition = position; - } - - getNodeShape(): NodeShape { - return this.shape || (this.group ? NodeShape.rect : NodeShape.ellipse); - } - - setNodeShape(shape: NodeShape): void { - this.shape = shape; - } - - getNodeStatus(): NodeStatus { - return this.status || NodeStatus.default; - } - - setNodeStatus(status: NodeStatus): void { - this.status = status; - } - - getSourceEdges(): Edge[] { - return this.sourceEdges; - } - - getTargetEdges(): Edge[] { - return this.targetEdges; - } - - isVisible(): boolean { - return super.isVisible() && this.isDimensionsInitialized(); - } - - setModel(model: E): void { - super.setModel(model); - - let d: Dimensions | undefined; - let p: Point | undefined; - - if ('width' in model && model.width != null && model.width !== this.dimensions.width) { - if (!d) { - d = this.dimensions.clone(); - } - d.width = model.width; - } - if ('height' in model && model.height != null && model.height !== this.dimensions.height) { - if (!d) { - d = this.dimensions.clone(); - } - d.height = model.height; - } - if (d) { - this.setDimensions(d); - } - - if ('x' in model && model.x != null && model.x !== this.position.x) { - if (!p) { - p = this.position.clone(); - } - p.x = model.x; - } - if ('y' in model && model.y != null && model.y !== this.position.y) { - if (!p) { - p = this.position.clone(); - } - p.y = model.y; - } - if (p) { - this.setPosition(p); - } - - if ('group' in model) { - this.setGroup(!!model.group); - } - if ('labelPosition' in model) { - this.labelPosition = model.labelPosition; - } - if ('shape' in model) { - this.shape = model.shape; - } - if ('status' in model) { - this.status = model.status; - } - if ('collapsed' in model) { - this.setCollapsed(!!model.collapsed); - } - } - - toModel(): NodeModel { - return { - ...super.toModel(), - x: this.isPositioned() ? this.getPosition().x : undefined, - y: this.isPositioned() ? this.getPosition().y : undefined, - width: this.isDimensionsInitialized() ? this.getDimensions().width : undefined, - height: this.isDimensionsInitialized() ? this.getDimensions().height : undefined, - collapsed: this.isCollapsed(), - group: this.isGroup(), - labelPosition: this.labelPosition, - shape: this.shape, - status: this.status - }; - } - - translateToParent(t: Translatable): void { - if (!this.group || this.isCollapsed()) { - const { x, y } = this.getPosition(); - t.translate(x, y); - } - } - - translateFromParent(t: Translatable): void { - if (!this.group || this.isCollapsed()) { - const { x, y } = this.getPosition(); - t.translate(-x, -y); - } - } -} diff --git a/packages/react-topology/src/elements/__tests__/BaseGraph.spec.ts b/packages/react-topology/src/elements/__tests__/BaseGraph.spec.ts deleted file mode 100644 index 569cb1afc01..00000000000 --- a/packages/react-topology/src/elements/__tests__/BaseGraph.spec.ts +++ /dev/null @@ -1,334 +0,0 @@ -import Rect from '../../geom/Rect'; -import Point from '../../geom/Point'; -import { ModelKind, Graph, Layout, GraphModel } from '../../types'; -import BaseGraph from '../BaseGraph'; -import BaseEdge from '../BaseEdge'; -import BaseNode from '../BaseNode'; -import { Visualization } from '../../Visualization'; - -class TestLayout implements Layout { - layout = jest.fn(); - stop = jest.fn(); - destroy = jest.fn(); -} - -describe('BaseGraph', () => { - let graph: Graph; - - beforeEach(() => { - graph = new BaseGraph(); - }); - - it('should have a graph kind', () => { - expect(graph.getKind()).toBe(ModelKind.graph); - }); - - it('should update bounds', () => { - expect(graph.getBounds()).toEqual({ x: 0, y: 0, width: 0, height: 0 }); - const r = new Rect(10, 20, 30, 40); - graph.setBounds(r); - expect(graph.getBounds()).toEqual({ x: 10, y: 20, width: 30, height: 40 }); - }); - - it('should update scale', () => { - expect(graph.getScale()).toBe(1); - graph.setScale(3.5); - expect(graph.getScale()).toBe(3.5); - }); - - it('should reset position and scale', () => { - graph.setBounds(new Rect(10, 20, 30, 40)); - graph.setScale(2); - graph.reset(); - expect(graph.getScale()).toBe(1); - expect(graph.getBounds()).toEqual({ x: 0, y: 0, width: 30, height: 40 }); - }); - - it('should scaleBy the given multiple around the specified location', () => { - graph.setBounds(new Rect(0, 0, 100, 100)); - graph.scaleBy(0.5); - expect(graph.getScale()).toBe(0.5); - expect(graph.getBounds()).toEqual({ x: 25, y: 25, width: 100, height: 100 }); - graph.scaleBy(2); - expect(graph.getBounds()).toEqual({ x: 0, y: 0, width: 100, height: 100 }); - graph.scaleBy(0.5, new Point(100, 100)); - expect(graph.getBounds()).toEqual({ x: 50, y: 50, width: 100, height: 100 }); - }); - - it('should get child nodes and edges', () => { - const e1 = new BaseEdge(); - const n1 = new BaseNode(); - const n2 = new BaseNode(); - graph.appendChild(e1); - graph.appendChild(n1); - graph.appendChild(n2); - - expect(graph.getNodes()).toEqual([n1, n2]); - expect(graph.getEdges()).toEqual([e1]); - // FIXME #getChildren() returns a mobx array and we need to slice it before we can assert - expect(graph.getChildren().slice()).toEqual([e1, n1, n2]); - }); - - it('should get and set layouts', () => { - const LAYOUT1_TYPE = 'layout1'; - const LAYOUT2_TYPE = 'layout2'; - const layout1 = new TestLayout(); - const layout2 = new TestLayout(); - - const controller = new Visualization(); - controller.setGraph(graph); - controller.registerLayoutFactory(type => { - switch (type) { - case LAYOUT1_TYPE: - return layout1; - case LAYOUT2_TYPE: - return layout2; - default: - return undefined; - } - }); - - expect(graph.getLayout()).toBe(undefined); - - // set initial layout - graph.setLayout(LAYOUT1_TYPE); - expect(graph.getLayout()).toBe(LAYOUT1_TYPE); - - // run layout - expect(layout1.layout).not.toHaveBeenCalled(); - graph.layout(); - expect(layout1.layout).toHaveBeenCalledTimes(1); - - // change layout - expect(layout2.destroy).not.toHaveBeenCalled(); - graph.setLayout(LAYOUT2_TYPE); - expect(graph.getLayout()).toBe(LAYOUT2_TYPE); - expect(layout1.destroy).toHaveBeenCalledTimes(1); - - // set the same layout, ensure not destroyed - graph.setLayout(LAYOUT2_TYPE); - expect(layout2.destroy).not.toHaveBeenCalled(); - - // unset layout - graph.setLayout(undefined); - expect(layout2.destroy).toHaveBeenCalledTimes(1); - // this should be a noop - graph.layout(); - }); - - it('should adjust bounds to fit nodes', () => { - graph.setBounds(new Rect(0, 0, 100, 100)); - graph.setScaleExtent([0.1, 100]); - - // no change if no nodes - graph.fit(); - expect(graph.getScale()).toBe(1); - expect(graph.getBounds()).toEqual({ x: 0, y: 0, width: 100, height: 100 }); - - // add 1 node - const n1 = new BaseNode(); - n1.setBounds(new Rect(10, 10, 10, 10)); - graph.appendChild(n1); - - // centers the node in the view - graph.fit(); - expect(graph.getScale()).toBe(1); - expect(graph.getBounds()).toEqual({ x: 35, y: 35, width: 100, height: 100 }); - - // increases scale back to 1 if nodes fit - graph.setScale(0.25); - graph.fit(); - expect(graph.getScale()).toBe(1); - expect(graph.getBounds()).toEqual({ x: 35, y: 35, width: 100, height: 100 }); - - // keeps scale above 1 if nodes fit - graph.setScale(2); - graph.fit(); - expect(graph.getScale()).toBe(2); - expect(graph.getBounds()).toEqual({ x: 20, y: 20, width: 100, height: 100 }); - - // decreases scale so that nodes fit - graph.setScale(100); - graph.fit(); - expect(graph.getScale()).toBe(10); - expect(graph.getBounds()).toEqual({ x: -100, y: -100, width: 100, height: 100 }); - - // add another node out of bounds - const n2 = new BaseNode(); - n2.setBounds(new Rect(200, 200, 10, 10)); - graph.appendChild(n2); - - // adjusts scale as needed to ensure all nodes fit - graph.fit(); - expect(graph.getScale()).toBe(0.5); - expect(graph.getBounds()).toEqual({ x: -5, y: -5, width: 100, height: 100 }); - - // add some padding - graph.fit(20); - expect(graph.getScale()).toBe(0.4); - expect(graph.getBounds()).toEqual({ x: 6, y: 6, width: 100, height: 100 }); - }); - - it('should pan node into view', () => { - const n1 = new BaseNode(); - graph.appendChild(n1); - - // pan from left - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(-20, 0, 10, 10)); - graph.panIntoView(n1); - expect(graph.getBounds()).toEqual({ x: 20, y: 0, width: 100, height: 100 }); - - // with offset - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(-20, 0, 10, 10)); - graph.panIntoView(n1, { offset: 10 }); - expect(graph.getBounds()).toEqual({ x: 30, y: 0, width: 100, height: 100 }); - - // pan from top - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(0, -20, 10, 10)); - graph.panIntoView(n1); - expect(graph.getBounds()).toEqual({ x: 0, y: 20, width: 100, height: 100 }); - - // with offset - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(0, -20, 10, 10)); - graph.panIntoView(n1, { offset: 10 }); - expect(graph.getBounds()).toEqual({ x: 0, y: 30, width: 100, height: 100 }); - - // pan from right - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(110, 0, 10, 10)); - graph.panIntoView(n1); - expect(graph.getBounds()).toEqual({ x: -20, y: 0, width: 100, height: 100 }); - - // with offset - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(110, 0, 10, 10)); - graph.panIntoView(n1, { offset: 10 }); - expect(graph.getBounds()).toEqual({ x: -30, y: 0, width: 100, height: 100 }); - - // pan from top - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(0, 110, 10, 10)); - graph.panIntoView(n1); - expect(graph.getBounds()).toEqual({ x: 0, y: -20, width: 100, height: 100 }); - - // with offset - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(0, 110, 10, 10)); - graph.panIntoView(n1, { offset: 10 }); - expect(graph.getBounds()).toEqual({ x: 0, y: -30, width: 100, height: 100 }); - }); - - it('should pan node into view taking into account minimum visibile ', () => { - const n1 = new BaseNode(); - graph.appendChild(n1); - - // pan from left / top - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(-7, -7, 10, 10)); - graph.panIntoView(n1, { minimumVisible: 3 }); - expect(graph.getBounds()).toEqual({ x: 0, y: 0, width: 100, height: 100 }); - - n1.setBounds(new Rect(-8, -8, 10, 10)); - graph.panIntoView(n1, { minimumVisible: 3 }); - expect(graph.getBounds()).toEqual({ x: 8, y: 8, width: 100, height: 100 }); - - // pan from right / bottom - graph.setBounds(new Rect(0, 0, 100, 100)); - n1.setBounds(new Rect(97, 97, 10, 10)); - graph.panIntoView(n1, { minimumVisible: 3 }); - expect(graph.getBounds()).toEqual({ x: 0, y: 0, width: 100, height: 100 }); - - n1.setBounds(new Rect(98, 98, 10, 10)); - graph.panIntoView(n1, { minimumVisible: 3 }); - expect(graph.getBounds()).toEqual({ x: -8, y: -8, width: 100, height: 100 }); - }); - - it('should set model layout', () => { - const layoutType = 'test'; - const controller = new Visualization(); - controller.setGraph(graph); - controller.registerLayoutFactory(type => { - return type === layoutType ? new TestLayout() : undefined; - }); - - const model: GraphModel = { - id: 'g', - type: ModelKind.graph, - layout: layoutType - }; - graph.setModel(model); - expect(graph.getLayout()).toBe(model.layout); - }); - - it('should set model scale', () => { - const model: GraphModel = { - id: 'g', - type: ModelKind.graph, - scale: 4 - }; - graph.setModel(model); - expect(graph.getScale()).toBe(model.scale); - }); - - it('should set model x, y', () => { - const model1: GraphModel = { - id: 'g', - type: ModelKind.graph, - x: 10 - }; - graph.setModel(model1); - expect(graph.getBounds().x).toBe(model1.x); - - const model2: GraphModel = { - id: 'g', - type: ModelKind.graph, - y: 20 - }; - graph.setModel(model2); - expect(graph.getBounds().x).toBe(model1.x); - expect(graph.getBounds().y).toBe(model2.y); - - const model3: GraphModel = { - id: 'g', - type: ModelKind.graph, - x: 2, - y: 3 - }; - graph.setModel(model3); - expect(graph.getBounds().x).toBe(model3.x); - expect(graph.getBounds().y).toBe(model3.y); - }); - - it('should not support translate', () => { - graph.setBounds(new Rect(10, 20, 30, 40)); - const p = new Point(5, 6); - graph.translateFromAbsolute(p); - expect(p).toEqual({ x: 5, y: 6 }); - - graph.translateToParent(p); - expect(p).toEqual({ x: 5, y: 6 }); - }); - - it('should set scale extents based on model', () => { - graph.setModel({ - id: 'test-graph-id', - type: 'graph', - scaleExtent: [0.2, 3.0], - scale: 5.5 - }); - expect(graph.getScale()).toBe(5.5); - const scaleExtent = graph.getScaleExtent(); - expect(scaleExtent[0]).toBe(0.2); - expect(scaleExtent[1]).toBe(3.0); - - // Scale extents do NOT prevent setting scale out of range - graph.setScale(10); - expect(graph.getScale()).toBe(10); - graph.setScale(0.1); - expect(graph.getScale()).toBe(0.1); - }); -}); diff --git a/packages/react-topology/src/elements/__tests__/BaseNode.spec.ts b/packages/react-topology/src/elements/__tests__/BaseNode.spec.ts deleted file mode 100644 index 1d6fa6e1113..00000000000 --- a/packages/react-topology/src/elements/__tests__/BaseNode.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import Dimensions from '../../geom/Dimensions'; -import BaseNode from '../BaseNode'; - -describe('BaseNode', () => { - it('should init dimensions', () => { - let node = new BaseNode(); - expect(node.isDimensionsInitialized()).toBe(false); - node.setDimensions(new Dimensions()); - expect(node.isDimensionsInitialized()).toBe(true); - node = new BaseNode(); - node.setModel({ - id: 'test', - type: 'test', - width: 1, - height: 1 - }); - expect(node.isDimensionsInitialized()).toBe(true); - }); - - it('should be invisible until dimensions are set', () => { - const node = new BaseNode(); - node.setVisible(true); - expect(node.isDimensionsInitialized()).toBe(false); - expect(node.isVisible()).toBe(false); - node.setDimensions(new Dimensions()); - expect(node.isDimensionsInitialized()).toBe(true); - expect(node.isVisible()).toBe(true); - }); - - it('should init group dimensions based on child state', () => { - const node = new BaseNode(); - node.setGroup(true); - expect(node.isDimensionsInitialized()).toBe(false); - - const c1 = new BaseNode(); - node.appendChild(c1); - expect(node.isDimensionsInitialized()).toBe(false); - c1.setDimensions(new Dimensions()); - expect(node.isDimensionsInitialized()).toBe(true); - - node.removeChild(c1); - expect(node.isDimensionsInitialized()).toBe(true); - - node.setGroup(false); - expect(node.isDimensionsInitialized()).toBe(true); - }); -}); diff --git a/packages/react-topology/src/elements/__tests__/defaultElementFactory.spec.ts b/packages/react-topology/src/elements/__tests__/defaultElementFactory.spec.ts deleted file mode 100644 index 2a8662b2941..00000000000 --- a/packages/react-topology/src/elements/__tests__/defaultElementFactory.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import defaultElementFactory from '../defaultElementFactory'; -import { ModelKind } from '../../types'; -import BaseGraph from '../BaseGraph'; -import BaseNode from '../BaseNode'; -import BaseEdge from '../BaseEdge'; - -describe('defaultElementFactory', () => { - it('should create base elements', () => { - expect(defaultElementFactory(ModelKind.graph, '') instanceof BaseGraph).toBe(true); - expect(defaultElementFactory(ModelKind.node, '') instanceof BaseNode).toBe(true); - expect(defaultElementFactory(ModelKind.edge, '') instanceof BaseEdge).toBe(true); - }); -}); diff --git a/packages/react-topology/src/elements/defaultElementFactory.ts b/packages/react-topology/src/elements/defaultElementFactory.ts deleted file mode 100644 index d86ab9a4228..00000000000 --- a/packages/react-topology/src/elements/defaultElementFactory.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ElementFactory, GraphElement, ModelKind } from '../types'; -import BaseEdge from './BaseEdge'; -import BaseGraph from './BaseGraph'; -import BaseNode from './BaseNode'; - -const defaultElementFactory: ElementFactory = (kind: ModelKind): GraphElement | undefined => { - switch (kind) { - case ModelKind.graph: - return new BaseGraph(); - case ModelKind.node: - return new BaseNode(); - case ModelKind.edge: - return new BaseEdge(); - default: - return undefined; - } -}; - -export default defaultElementFactory; diff --git a/packages/react-topology/src/elements/index.ts b/packages/react-topology/src/elements/index.ts deleted file mode 100644 index 8955e32b127..00000000000 --- a/packages/react-topology/src/elements/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as BaseEdge } from './BaseEdge'; -export { default as BaseElement } from './BaseElement'; -export { default as BaseGraph } from './BaseGraph'; -export { default as BaseNode } from './BaseNode'; -export { default as defaultElementFactory } from './defaultElementFactory'; diff --git a/packages/react-topology/src/geom/Dimensions.ts b/packages/react-topology/src/geom/Dimensions.ts deleted file mode 100644 index 13e37c2fef6..00000000000 --- a/packages/react-topology/src/geom/Dimensions.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { DimensionsIface } from './types'; - -export default class Dimensions implements DimensionsIface { - static readonly EMPTY = new Dimensions(); - - width: number = 0; - - height: number = 0; - - private static SINGLETON = new Dimensions(); - - static singleUse(width: number = 0, height: number = 0) { - Dimensions.SINGLETON.width = width; - Dimensions.SINGLETON.height = height; - return Dimensions.SINGLETON; - } - - static fromDimensions(dimension: DimensionsIface): Dimensions { - return new Dimensions(dimension.width, dimension.height); - } - - constructor(width: number = 0, height: number = 0) { - this.width = width; - this.height = height; - } - - isEmpty(): boolean { - return this.width <= 0 || this.height <= 0; - } - - setSize(w: number, h: number): Dimensions { - this.width = w; - this.height = h; - return this; - } - - scale(scaleX: number, scaleY?: number): Dimensions { - const sy = scaleY != null ? scaleY : scaleX; - this.width *= scaleX; - this.height *= sy; - return this; - } - - resize(dw: number, dh: number): Dimensions { - this.width += dw; - this.height += dh; - return this; - } - - expand(h: number, v: number): Dimensions { - this.height += v * 2; - this.width += h * 2; - return this; - } - - clone(): Dimensions { - return Dimensions.fromDimensions(this); - } - - equals(r: DimensionsIface) { - return r.width === this.width && r.height === this.height; - } -} diff --git a/packages/react-topology/src/geom/Point.ts b/packages/react-topology/src/geom/Point.ts deleted file mode 100644 index 9f3ec753b7e..00000000000 --- a/packages/react-topology/src/geom/Point.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Translatable, PointIface } from './types'; - -export default class Point implements Translatable, PointIface { - static readonly EMPTY = new Point(); - - x: number; - - y: number; - - private static SINGLETON = new Point(); - - static singleUse(x: number = 0, y: number = 0) { - Point.SINGLETON.x = x; - Point.SINGLETON.y = y; - return Point.SINGLETON; - } - - static fromPoint(point: PointIface): Point { - return new Point(point.x, point.y); - } - - constructor(x: number = 0, y: number = 0) { - this.x = x; - this.y = y; - } - - setLocation(x: number, y: number): Point { - this.x = x; - this.y = y; - return this; - } - - negate(): Point { - this.x = -this.x; - this.y = -this.y; - return this; - } - - translate(dx: number, dy: number): Point { - this.x += dx; - this.y += dy; - return this; - } - - scale(scaleX: number, scaleY?: number): Point { - this.x *= scaleX; - this.y *= scaleY != null ? scaleY : scaleX; - return this; - } - - clone(): Point { - return Point.fromPoint(this); - } - - equals(p: PointIface) { - return p.x === this.x && p.y === this.y; - } -} diff --git a/packages/react-topology/src/geom/Rect.ts b/packages/react-topology/src/geom/Rect.ts deleted file mode 100644 index 94a5a2ab29c..00000000000 --- a/packages/react-topology/src/geom/Rect.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { Padding, Translatable, RectIface } from './types'; -import Point from './Point'; - -export default class Rect implements Translatable, RectIface { - static readonly EMPTY = new Rect(); - - width: number = 0; - - height: number = 0; - - x: number = 0; - - y: number = 0; - - private static SINGLETON = new Rect(); - - static singleUse(x: number = 0, y: number = 0, width: number = 0, height: number = 0) { - Rect.SINGLETON.x = x; - Rect.SINGLETON.y = y; - Rect.SINGLETON.width = width; - Rect.SINGLETON.height = height; - return Rect.SINGLETON; - } - - static fromRect(rect: RectIface): Rect { - return new Rect(rect.x, rect.y, rect.width, rect.height); - } - - constructor(x: number = 0, y: number = 0, width: number = 0, height: number = 0) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - isEmpty(): boolean { - return this.width <= 0 || this.height <= 0; - } - - setLocation(x: number, y: number): Rect { - this.x = x; - this.y = y; - return this; - } - - setSize(w: number, h: number): Rect { - this.width = w; - this.height = h; - return this; - } - - getCenter(): Point { - return new Point(this.x + this.width / 2, this.y + this.height / 2); - } - - setCenter(x: number, y: number): Rect { - this.x = x - this.width / 2; - this.y = y - this.height / 2; - return this; - } - - translate(dx: number, dy: number): Rect { - this.x += dx; - this.y += dy; - return this; - } - - scale(scaleX: number, scaleY?: number): Rect { - const sy = scaleY != null ? scaleY : scaleX; - const xx = this.x; - const yy = this.y; - this.x *= scaleX; - this.y *= sy; - this.width = (xx + this.width) * scaleX - this.x; - this.height = (yy + this.height) * sy - this.y; - return this; - } - - resize(dw: number, dh: number): Rect { - this.width += dw; - this.height += dh; - return this; - } - - bottom(): number { - return this.y + this.height; - } - - right(): number { - return this.x + this.width; - } - - union({ x, y, width, height }: Rect): Rect { - const right = Math.max(this.x + this.width, x + width); - const bottom = Math.max(this.y + this.height, y + height); - this.x = Math.min(this.x, x); - this.y = Math.min(this.y, y); - this.width = right - this.x; - this.height = bottom - this.y; - return this; - } - - expand(h: number, v: number): Rect { - this.y -= v; - this.height += v * 2; - this.x -= h; - this.width += h * 2; - return this; - } - - // - // Padding Format: [all], [vertical, horizontal], [top, horizontal, bottom], [top, right, bottom, left] - // - padding(padding?: Padding): Rect { - if (padding) { - if (typeof padding === 'number') { - this.expand(padding, padding); - } else if (padding.length === 1) { - this.expand(padding[0], padding[0]); - } else if (padding.length === 2) { - this.expand(padding[1], padding[0]); - } else if (padding.length === 3) { - this.y -= padding[0]; - this.height += padding[0] + padding[2]; - this.width += padding[1]; - } else if (padding.length === 4) { - this.y -= padding[0]; - this.height += padding[0] + padding[2]; - this.x -= padding[1]; - this.width += padding[1] + padding[3]; - } - } - return this; - } - - setBounds(x: number, y: number, width: number, height: number): Rect { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - return this; - } - - clone(): Rect { - return Rect.fromRect(this); - } - - equals(r: RectIface) { - return r.x === this.x && r.y === this.y && r.width === this.width && r.height === this.height; - } -} diff --git a/packages/react-topology/src/geom/__tests__/Dimensions.spec.ts b/packages/react-topology/src/geom/__tests__/Dimensions.spec.ts deleted file mode 100644 index e7c08199ea7..00000000000 --- a/packages/react-topology/src/geom/__tests__/Dimensions.spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -import Dimensions from '../Dimensions'; - -describe('Dimensions', () => { - it('should provide an empty instance', () => { - expect(Dimensions.EMPTY).toEqual({ width: 0, height: 0 }); - }); - - it('should re-use single use instance', () => { - expect(Dimensions.singleUse()).toBe(Dimensions.singleUse()); - expect(Dimensions.singleUse()).toEqual({ width: 0, height: 0 }); - expect(Dimensions.singleUse(1)).toEqual({ width: 1, height: 0 }); - expect(Dimensions.singleUse(1, 2)).toEqual({ width: 1, height: 2 }); - }); - - it('should create a new Dimensions from existing Dimensions', () => { - const d1 = new Dimensions(5, 10); - const d2 = Dimensions.fromDimensions(d1); - expect(d1).not.toBe(d2); - expect(d1).toEqual(d2); - }); - - it('should create a Dimensions', () => { - expect(new Dimensions()).toEqual({ width: 0, height: 0 }); - expect(new Dimensions(1)).toEqual({ width: 1, height: 0 }); - expect(new Dimensions(1, 2)).toEqual({ width: 1, height: 2 }); - }); - - it('should be empty if no height or width', () => { - expect(new Dimensions().isEmpty()).toBe(true); - expect(new Dimensions(1, 0).isEmpty()).toBe(true); - expect(new Dimensions(0, 1).isEmpty()).toBe(true); - expect(new Dimensions(1, 1).isEmpty()).toBe(false); - }); - - it('should set size', () => { - const d = new Dimensions(8, 9); - expect(d.setSize(2, 3)).toBe(d); - expect(d).toEqual({ width: 2, height: 3 }); - }); - - it('should scale Dimensions', () => { - const d = new Dimensions(4, 6); - expect(d.scale(2)).toBe(d); - expect(d).toEqual({ width: 8, height: 12 }); - d.scale(0.5, 2); - expect(d).toEqual({ width: 4, height: 24 }); - }); - - it('should resize the Dimensions', () => { - const d = new Dimensions(8, 9); - expect(d.resize(2, 3)).toBe(d); - expect(d).toEqual({ width: 10, height: 12 }); - }); - - it('should expand the Dimensions in size', () => { - const d = new Dimensions(8, 9); - expect(d.expand(4, 5)).toBe(d); - expect(d).toEqual({ width: 16, height: 19 }); - }); - - it('should clone Dimensions', () => { - const d1 = new Dimensions(5, 10); - const d2 = d1.clone(); - expect(d1).not.toBe(d2); - expect(d1).toEqual(d2); - }); - - it('should check Dimensions equality', () => { - const d1 = new Dimensions(5, 10); - const d2 = new Dimensions(5, 10); - const d3 = new Dimensions(1, 2); - expect(d1.equals(d2)).toBe(true); - expect(d1.equals(d3)).toBe(false); - }); -}); diff --git a/packages/react-topology/src/geom/__tests__/Point.spec.ts b/packages/react-topology/src/geom/__tests__/Point.spec.ts deleted file mode 100644 index aba006ce8ca..00000000000 --- a/packages/react-topology/src/geom/__tests__/Point.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -import Point from '../Point'; - -describe('Point', () => { - it('should provide an empty instance', () => { - expect(Point.EMPTY).toEqual({ x: 0, y: 0 }); - }); - - it('should re-use single use instance', () => { - expect(Point.singleUse()).toBe(Point.singleUse()); - expect(Point.singleUse()).toEqual({ x: 0, y: 0 }); - expect(Point.singleUse(1)).toEqual({ x: 1, y: 0 }); - expect(Point.singleUse(1, 2)).toEqual({ x: 1, y: 2 }); - }); - - it('should create a new Point from existing Point', () => { - const p1 = new Point(5, 10); - const p2 = Point.fromPoint(p1); - expect(p1).not.toBe(p2); - expect(p1).toEqual(p2); - }); - - it('should create a Point', () => { - expect(new Point()).toEqual({ x: 0, y: 0 }); - expect(new Point(1)).toEqual({ x: 1, y: 0 }); - expect(new Point(1, 2)).toEqual({ x: 1, y: 2 }); - }); - - it('should set location', () => { - const p = new Point(5, 10); - expect(p.setLocation(2, 3)).toBe(p); - expect(p).toEqual({ x: 2, y: 3 }); - }); - - it('should negate point', () => { - const p = new Point(5, 10); - expect(p.negate()).toBe(p); - expect(p).toEqual({ x: -5, y: -10 }); - }); - - it('should translate point', () => { - const p = new Point(5, 10); - expect(p.translate(2, 3)).toBe(p); - expect(p).toEqual({ x: 7, y: 13 }); - }); - - it('should scale point', () => { - const p = new Point(5, 10); - expect(p.scale(2)).toBe(p); - expect(p).toEqual({ x: 10, y: 20 }); - p.scale(1.5, 2); - expect(p).toEqual({ x: 15, y: 40 }); - }); - - it('should clone point', () => { - const p1 = new Point(5, 10); - const p2 = p1.clone(); - expect(p1).not.toBe(p2); - expect(p1).toEqual(p2); - }); - - it('should check point equality', () => { - const p1 = new Point(5, 10); - const p2 = new Point(5, 10); - const p3 = new Point(1, 2); - expect(p1.equals(p2)).toBe(true); - expect(p1.equals(p3)).toBe(false); - }); -}); diff --git a/packages/react-topology/src/geom/__tests__/Rect.spec.ts b/packages/react-topology/src/geom/__tests__/Rect.spec.ts deleted file mode 100644 index 9c80e8396eb..00000000000 --- a/packages/react-topology/src/geom/__tests__/Rect.spec.ts +++ /dev/null @@ -1,135 +0,0 @@ -import Rect from '../Rect'; - -describe('Rect', () => { - it('should provide an empty instance', () => { - expect(Rect.EMPTY).toEqual({ x: 0, y: 0, width: 0, height: 0 }); - }); - - it('should re-use single use instance', () => { - expect(Rect.singleUse()).toBe(Rect.singleUse()); - expect(Rect.singleUse()).toEqual({ x: 0, y: 0, width: 0, height: 0 }); - expect(Rect.singleUse(1)).toEqual({ x: 1, y: 0, width: 0, height: 0 }); - expect(Rect.singleUse(1, 2)).toEqual({ x: 1, y: 2, width: 0, height: 0 }); - expect(Rect.singleUse(1, 2, 3)).toEqual({ x: 1, y: 2, width: 3, height: 0 }); - expect(Rect.singleUse(1, 2, 3, 4)).toEqual({ x: 1, y: 2, width: 3, height: 4 }); - }); - - it('should create a new Rect from existing Rect', () => { - const r1 = new Rect(5, 10, 2, 4); - const r2 = Rect.fromRect(r1); - expect(r1).not.toBe(r2); - expect(r1).toEqual(r2); - }); - - it('should create a Rect', () => { - expect(new Rect()).toEqual({ x: 0, y: 0, width: 0, height: 0 }); - expect(new Rect(1)).toEqual({ x: 1, y: 0, width: 0, height: 0 }); - expect(new Rect(1, 2, 3)).toEqual({ x: 1, y: 2, width: 3, height: 0 }); - expect(new Rect(1, 2, 3, 4)).toEqual({ x: 1, y: 2, width: 3, height: 4 }); - }); - - it('should be empty if no height or width', () => { - expect(new Rect().isEmpty()).toBe(true); - expect(new Rect(0, 0, 1, 0).isEmpty()).toBe(true); - expect(new Rect(0, 0, 0, 1).isEmpty()).toBe(true); - expect(new Rect(0, 0, 1, 1).isEmpty()).toBe(false); - }); - - it('should set location', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.setLocation(2, 3)).toBe(r); - expect(r).toEqual({ x: 2, y: 3, width: 8, height: 9 }); - }); - - it('should set size', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.setSize(2, 3)).toBe(r); - expect(r).toEqual({ x: 5, y: 10, width: 2, height: 3 }); - }); - - it('should set center', () => { - const r = new Rect(6, 10, 20, 30); - expect(r.setCenter(10, 30)).toBe(r); - expect(r).toEqual({ x: 0, y: 15, width: 20, height: 30 }); - }); - - it('should get center', () => { - const r = new Rect(6, 10, 10, 16); - expect(r.getCenter()).toEqual({ x: 11, y: 18 }); - }); - - it('should translate Rect', () => { - const r = new Rect(5, 10, 3, 4); - expect(r.translate(2, 3)).toBe(r); - expect(r).toEqual({ x: 7, y: 13, width: 3, height: 4 }); - }); - - it('should scale Rect', () => { - const r = new Rect(5, 10, 4, 6); - expect(r.scale(2)).toBe(r); - expect(r).toEqual({ x: 10, y: 20, width: 8, height: 12 }); - r.scale(0.5, 2); - expect(r).toEqual({ x: 5, y: 40, width: 4, height: 24 }); - }); - - it('should resize the Rect ', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.resize(2, 3)).toBe(r); - expect(r).toEqual({ x: 5, y: 10, width: 10, height: 12 }); - }); - - it('should get the bottom y coordinate', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.bottom()).toBe(19); - }); - - it('should get the right x coordinate', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.right()).toBe(13); - }); - - it('should expand the Rect to enclose another Rect', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.union(new Rect(2, 12, 4, 27))).toBe(r); - expect(r).toEqual({ x: 2, y: 10, width: 11, height: 29 }); - }); - - it('should expand the Rect in size', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.expand(4, 5)).toBe(r); - expect(r).toEqual({ x: 1, y: 5, width: 16, height: 19 }); - }); - - it('should set padding according to css shorthand rules', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.padding()).toBe(r); - expect(r.padding()).toEqual({ x: 5, y: 10, width: 8, height: 9 }); - expect(r.padding(undefined)).toEqual({ x: 5, y: 10, width: 8, height: 9 }); - expect(r.clone().padding(5)).toEqual({ x: 0, y: 5, width: 18, height: 19 }); - expect(r.clone().padding([5])).toEqual({ x: 0, y: 5, width: 18, height: 19 }); - expect(r.clone().padding([5, 2])).toEqual({ x: 3, y: 5, width: 12, height: 19 }); - expect(r.clone().padding([5, 2, 4])).toEqual({ x: 5, y: 5, width: 10, height: 18 }); - expect(r.clone().padding([5, 2, 4, 6])).toEqual({ x: 3, y: 5, width: 16, height: 18 }); - }); - - it('should set bounds', () => { - const r = new Rect(5, 10, 8, 9); - expect(r.setBounds(2, 3, 6, 7)).toBe(r); - expect(r).toEqual({ x: 2, y: 3, width: 6, height: 7 }); - }); - - it('should clone Rect', () => { - const r1 = new Rect(5, 10); - const r2 = r1.clone(); - expect(r1).not.toBe(r2); - expect(r1).toEqual(r2); - }); - - it('should check Rect equality', () => { - const r1 = new Rect(5, 10, 1, 2); - const r2 = new Rect(5, 10, 1, 2); - const r3 = new Rect(1, 2, 3, 4); - expect(r1.equals(r2)).toBe(true); - expect(r1.equals(r3)).toBe(false); - }); -}); diff --git a/packages/react-topology/src/geom/index.ts b/packages/react-topology/src/geom/index.ts deleted file mode 100644 index 653f02d5106..00000000000 --- a/packages/react-topology/src/geom/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { default as Point } from './Point'; -export { default as Rect } from './Rect'; -export { default as Dimensions } from './Dimensions'; -export * from './types'; diff --git a/packages/react-topology/src/geom/types.ts b/packages/react-topology/src/geom/types.ts deleted file mode 100644 index 406907b5375..00000000000 --- a/packages/react-topology/src/geom/types.ts +++ /dev/null @@ -1,28 +0,0 @@ -export interface Translatable { - translate(dx: number, dy: number): Translatable; - scale(s: number): Translatable; -} - -export type Padding = - | number - | [number] - | [number, number] - | [number, number, number] - | [number, number, number, number]; - -export interface PointIface { - x: number; - y: number; -} - -export interface DimensionsIface { - width: number; - height: number; -} - -export interface RectIface { - x: number; - y: number; - width: number; - height: number; -} diff --git a/packages/react-topology/src/hooks/index.ts b/packages/react-topology/src/hooks/index.ts deleted file mode 100644 index 796613955e0..00000000000 --- a/packages/react-topology/src/hooks/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { default as useComponentFactory } from './useComponentFactory'; -export { default as useElementFactory } from './useElementFactory'; -export { default as useEventListener } from './useEventListener'; -export { default as useLayoutFactory } from './useLayoutFactory'; -export { default as useModel } from './useModel'; -export { default as useVisualizationController } from './useVisualizationController'; -export { default as useVisualizationState } from './useVisualizationState'; -export { default as useDetailsLevel } from './useDetailsLevel'; -export { default as useScaleNode } from './useScaleNode'; diff --git a/packages/react-topology/src/hooks/useComponentFactory.tsx b/packages/react-topology/src/hooks/useComponentFactory.tsx deleted file mode 100644 index 70fc4bce590..00000000000 --- a/packages/react-topology/src/hooks/useComponentFactory.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { ComponentFactory } from '../types'; -import useVisualizationController from './useVisualizationController'; - -const useComponentFactory = (factory: ComponentFactory): void => { - const controller = useVisualizationController(); - React.useEffect(() => { - controller.registerComponentFactory(factory); - // TODO support unregister? - }, [controller, factory]); -}; - -export default useComponentFactory; diff --git a/packages/react-topology/src/hooks/useDetailsLevel.tsx b/packages/react-topology/src/hooks/useDetailsLevel.tsx deleted file mode 100644 index a1985763a24..00000000000 --- a/packages/react-topology/src/hooks/useDetailsLevel.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import useVisualizationController from './useVisualizationController'; -import { ScaleDetailsLevel } from '../types'; - -const useDetailsLevel = (): ScaleDetailsLevel => { - const controller = useVisualizationController(); - if (!controller) { - return ScaleDetailsLevel.high; - } - return controller.getGraph().getDetailsLevel(); -}; - -export default useDetailsLevel; diff --git a/packages/react-topology/src/hooks/useElementFactory.tsx b/packages/react-topology/src/hooks/useElementFactory.tsx deleted file mode 100644 index 0e2001d0ac3..00000000000 --- a/packages/react-topology/src/hooks/useElementFactory.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { ElementFactory } from '../types'; -import useVisualizationController from './useVisualizationController'; - -const useElementFactory = (factory: ElementFactory): void => { - const controller = useVisualizationController(); - React.useEffect(() => { - controller.registerElementFactory(factory); - // TODO support unregister? - }, [controller, factory]); -}; - -export default useElementFactory; diff --git a/packages/react-topology/src/hooks/useEventListener.tsx b/packages/react-topology/src/hooks/useEventListener.tsx deleted file mode 100644 index 6e2c96b3fda..00000000000 --- a/packages/react-topology/src/hooks/useEventListener.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import useVisualizationController from './useVisualizationController'; -import { EventListener } from '../types'; - -const useEventListener = (type: string, listener: L): void => { - const controller = useVisualizationController(); - React.useEffect(() => { - controller.addEventListener(type, listener); - return () => { - controller.removeEventListener(type, listener); - }; - }, [controller, type, listener]); -}; - -export default useEventListener; diff --git a/packages/react-topology/src/hooks/useLayoutFactory.tsx b/packages/react-topology/src/hooks/useLayoutFactory.tsx deleted file mode 100644 index fa16a5ebe8e..00000000000 --- a/packages/react-topology/src/hooks/useLayoutFactory.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import { LayoutFactory } from '../types'; -import useVisualizationController from './useVisualizationController'; - -const useLayoutFactory = (factory: LayoutFactory): void => { - const controller = useVisualizationController(); - React.useEffect(() => { - controller.registerLayoutFactory(factory); - // TODO support unregister? - }, [controller, factory]); -}; - -export default useLayoutFactory; diff --git a/packages/react-topology/src/hooks/useModel.tsx b/packages/react-topology/src/hooks/useModel.tsx deleted file mode 100644 index 2f95986549f..00000000000 --- a/packages/react-topology/src/hooks/useModel.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import useVisualizationController from './useVisualizationController'; -import { Model } from '../types'; - -const useModel = (model: Model): void => { - const controller = useVisualizationController(); - - React.useEffect(() => { - controller.fromModel(model); - }, [controller, model]); -}; - -export default useModel; diff --git a/packages/react-topology/src/hooks/useScaleNode.tsx b/packages/react-topology/src/hooks/useScaleNode.tsx deleted file mode 100644 index 9bec3ac5cfb..00000000000 --- a/packages/react-topology/src/hooks/useScaleNode.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import * as React from 'react'; - -const useScaleNode = (scaleNode: boolean, scale: number, scaleUpTime: number = 200): number => { - const [nodeScale, setNodeScale] = React.useState(1); - const animationRef = React.useRef(); - const scaleGoal = React.useRef(1); - const nodeScaled = React.useRef(false); - - React.useEffect(() => { - if (!scaleNode || scale >= 1) { - setNodeScale(1); - nodeScaled.current = false; - if (animationRef.current) { - window.cancelAnimationFrame(animationRef.current); - animationRef.current = 0; - } - } else { - scaleGoal.current = 1 / scale; - const scaleDelta = scaleGoal.current - scale; - const initTime = performance.now(); - - const bumpScale = (bumpTime: number) => { - const scalePercent = (bumpTime - initTime) / scaleUpTime; - const nextScale = Math.min(scale + scaleDelta * scalePercent, scaleGoal.current); - setNodeScale(nextScale); - if (nextScale < scaleGoal.current) { - animationRef.current = window.requestAnimationFrame(bumpScale); - } else { - nodeScaled.current = true; - animationRef.current = 0; - } - }; - - if (nodeScaled.current) { - setNodeScale(scaleGoal.current); - } else if (!animationRef.current) { - animationRef.current = window.requestAnimationFrame(bumpScale); - } - } - return () => { - if (animationRef.current) { - window.cancelAnimationFrame(animationRef.current); - animationRef.current = 0; - } - }; - }, [scale, scaleNode, scaleUpTime]); - - return nodeScale; -}; -export default useScaleNode; diff --git a/packages/react-topology/src/hooks/useVisualizationController.tsx b/packages/react-topology/src/hooks/useVisualizationController.tsx deleted file mode 100644 index aee4353910a..00000000000 --- a/packages/react-topology/src/hooks/useVisualizationController.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import { ControllerContext } from '../utils'; -import { Controller } from '../types'; - -const useVisualizationController = (): Controller => React.useContext(ControllerContext); - -export default useVisualizationController; diff --git a/packages/react-topology/src/hooks/useVisualizationState.tsx b/packages/react-topology/src/hooks/useVisualizationState.tsx deleted file mode 100644 index 24f064810fa..00000000000 --- a/packages/react-topology/src/hooks/useVisualizationState.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import { reaction } from 'mobx'; -import useVisualizationController from './useVisualizationController'; - -const useVisualizationState = (key: string, initialState?: S): [S, (value: S) => void] => { - const keyRef = React.useRef(key); - if (keyRef.current !== key) { - throw new Error(`State key change disallowed: ${keyRef.current} => ${key}`); - } - - const [state, setState] = React.useState(initialState); - const controller = useVisualizationController(); - - const setControllerState = React.useCallback( - (value?: S): void => { - controller.setState({ [keyRef.current]: value }); - }, - [controller] - ); - - React.useEffect(() => { - // init the controller state - setControllerState(initialState); - - // sync controller state and react state such that the component is re-rendered when controller state changes - return reaction( - () => controller.getState()[keyRef.current], - (value: S) => { - setState(value); - } - ); - - // we only want to set the initial state once - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [controller]); - - return [state, setControllerState]; -}; - -export default useVisualizationState; diff --git a/packages/react-topology/src/index.ts b/packages/react-topology/src/index.ts deleted file mode 100644 index aa256a654d2..00000000000 --- a/packages/react-topology/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export * from './components'; -export * from './anchors'; -export * from './behavior'; -export * from './const'; -export * from './elements'; -export * from './geom'; -export * from './hooks'; -export * from './layouts'; -export * from './utils'; -export * from './mobx-exports'; -export * from './types'; -export * from './pipelines'; -export { Visualization } from './Visualization'; diff --git a/packages/react-topology/src/layouts/BaseLayout.ts b/packages/react-topology/src/layouts/BaseLayout.ts deleted file mode 100644 index f31f514c1d6..00000000000 --- a/packages/react-topology/src/layouts/BaseLayout.ts +++ /dev/null @@ -1,484 +0,0 @@ -import * as _ from 'lodash'; -import { action } from 'mobx'; -import { - Edge, - Graph, - Layout, - Node, - ADD_CHILD_EVENT, - REMOVE_CHILD_EVENT, - GRAPH_LAYOUT_END_EVENT, - ElementChildEventListener, - NODE_COLLAPSE_CHANGE_EVENT, - NodeCollapseChangeEventListener, - ElementVisibilityChangeEventListener, - ELEMENT_VISIBILITY_CHANGE_EVENT, - ElementVisibilityChangeEvent, - isNode -} from '../types'; -import { leafNodeElements, groupNodeElements, getClosestVisibleParent } from '../utils'; -import { - DRAG_MOVE_OPERATION, - DRAG_NODE_END_EVENT, - DRAG_NODE_START_EVENT, - DragEvent, - DragNodeEventListener, - DragOperationWithType -} from '../behavior'; -import { BaseEdge } from '../elements'; -import { ForceSimulation } from './ForceSimulation'; -import { LayoutNode } from './LayoutNode'; -import { LayoutGroup } from './LayoutGroup'; -import { LayoutLink } from './LayoutLink'; -import { LayoutOptions } from './LayoutOptions'; - -export const LAYOUT_DEFAULTS: LayoutOptions = { - linkDistance: 60, - nodeDistance: 35, - groupDistance: 35, - collideDistance: 0, - simulationSpeed: 10, - chargeStrength: 0, - allowDrag: true, - layoutOnDrag: true -}; -export class BaseLayout implements Layout { - protected readonly graph: Graph; - - protected forceSimulation: ForceSimulation; - - protected options: LayoutOptions; - - protected scheduleHandle?: number; - - private scheduleRestart = false; - - protected nodes: LayoutNode[] = []; - - protected edges: LayoutLink[] = []; - - protected groups: LayoutGroup[] = []; - - protected nodesMap: { [id: string]: LayoutNode } = {}; - - constructor(graph: Graph, options?: Partial) { - this.graph = graph; - this.options = { - ...LAYOUT_DEFAULTS, - onSimulationEnd: this.onSimulationEnd, - ...options - }; - - if (this.options.allowDrag) { - graph - .getController() - .addEventListener(DRAG_NODE_START_EVENT, this.handleDragStart) - .addEventListener(DRAG_NODE_END_EVENT, this.handleDragEnd); - } - - this.forceSimulation = new ForceSimulation(this.options); - this.startListening(); - } - - protected onSimulationEnd = () => {}; - - destroy(): void { - if (this.options.allowDrag) { - this.graph - .getController() - .removeEventListener(DRAG_NODE_START_EVENT, this.handleDragStart) - .removeEventListener(DRAG_NODE_END_EVENT, this.handleDragEnd); - } - - this.stopListening(); - - this.forceSimulation.destroy(); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected initDrag(element: Node, event: DragEvent, operation: DragOperationWithType): void {} - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected endDrag(element: Node, event: DragEvent, operation: DragOperationWithType): void {} - - handleDragStart = (element: Node, event: DragEvent, operation: DragOperationWithType) => { - this.initDrag(element, event, operation); - - if (!this.options.layoutOnDrag) { - return; - } - - if (operation.type !== DRAG_MOVE_OPERATION) { - this.forceSimulation.stopSimulation(); - return; - } - - const id = element.getId(); - let found = false; - const dragNode: LayoutNode | undefined = this.nodes.find((node: LayoutNode) => node.id === id); - if (dragNode) { - dragNode.isFixed = true; - found = true; - } else { - const dragGroup: LayoutGroup | undefined = this.groups.find((group: LayoutGroup) => group.id === id); - if (dragGroup) { - const groupNodes = dragGroup.leaves; - groupNodes.forEach((node: LayoutNode) => { - node.isFixed = true; - }); - found = true; - } - } - - if (found) { - this.forceSimulation.alphaTarget(0.1); - this.forceSimulation.restart(); - } - }; - - handleDragEnd = (element: Node, event: DragEvent, operation: DragOperationWithType) => { - this.endDrag(element, event, operation); - - if (!this.options.layoutOnDrag) { - return; - } - - if (operation.type !== DRAG_MOVE_OPERATION) { - this.forceSimulation.restart(); - return; - } - - const id = element.getId(); - const dragNode: LayoutNode | undefined = this.nodes.find((node: LayoutNode) => node.id === id); - if (dragNode) { - dragNode.isFixed = false; - } else { - const dragGroup: LayoutGroup | undefined = this.groups.find((group: LayoutGroup) => group.id === id); - if (dragGroup) { - const groupNodes = dragGroup.leaves; - groupNodes.forEach((node: LayoutNode) => { - node.isFixed = false; - }); - } - } - this.forceSimulation.alphaTarget(0); - }; - - layout = () => { - this.stopListening(); - - this.runLayout(true); - - this.startListening(); - }; - - private startListening(): void { - const controller = this.graph.getController(); - if (controller) { - controller.addEventListener(ADD_CHILD_EVENT, this.handleChildAdded); - controller.addEventListener(REMOVE_CHILD_EVENT, this.handleChildRemoved); - controller.addEventListener(ELEMENT_VISIBILITY_CHANGE_EVENT, this.handleElementVisibilityChange); - controller.addEventListener(NODE_COLLAPSE_CHANGE_EVENT, this.handleNodeCollapse); - } - } - - stop(): void { - this.stopSimulation(); - } - - private stopListening(): void { - const controller = this.graph.getController(); - if (this.scheduleHandle) { - window.cancelAnimationFrame(this.scheduleHandle); - } - if (controller) { - controller.removeEventListener(ADD_CHILD_EVENT, this.handleChildAdded); - controller.removeEventListener(REMOVE_CHILD_EVENT, this.handleChildRemoved); - controller.removeEventListener(ELEMENT_VISIBILITY_CHANGE_EVENT, this.handleElementVisibilityChange); - controller.removeEventListener(NODE_COLLAPSE_CHANGE_EVENT, this.handleNodeCollapse); - } - } - - protected handleChildAdded: ElementChildEventListener = ({ child }): void => { - if (!this.nodesMap[child.getId()]) { - this.scheduleRestart = true; - this.scheduleLayout(); - } - }; - - protected handleChildRemoved: ElementChildEventListener = ({ child }): void => { - if (this.nodesMap[child.getId()]) { - this.scheduleRestart = true; - this.scheduleLayout(); - } - }; - - protected handleElementVisibilityChange: ElementVisibilityChangeEventListener = ( - event: ElementVisibilityChangeEvent - ): void => { - if (event.visible === (this.nodesMap[event.target.getId()] === undefined)) { - this.scheduleRestart = true; - this.scheduleLayout(); - } - }; - - private handleNodeCollapse: NodeCollapseChangeEventListener = ({ node }): void => { - if (!node.isCollapsed()) { - this.scheduleRestart = true; - this.scheduleLayout(); - } - }; - - private scheduleLayout = (): void => { - if (!this.scheduleHandle) { - this.scheduleHandle = window.requestAnimationFrame(() => { - delete this.scheduleHandle; - try { - this.runLayout(false, this.scheduleRestart); - this.scheduleRestart = false; - // eslint-disable-next-line no-empty - } catch (e) {} - }); - } - }; - - protected getFixedNodeDistance = (link: any): number => - Math.sqrt((link.sourceNode.x - link.targetNode.x) ** 2 + (link.sourceNode.y - link.targetNode.y) ** 2); - - protected getLayoutNode(nodes: LayoutNode[], node: Node | null): LayoutNode | undefined { - if (!node) { - return undefined; - } - - let layoutNode = _.find(nodes, { id: node.getId() }); - if (!layoutNode && _.size(node.getNodes())) { - layoutNode = _.find(nodes, { id: node.getChildren()[0].getId() }); - } - if (!layoutNode) { - layoutNode = this.getLayoutNode(nodes, getClosestVisibleParent(node)); - } - - return layoutNode; - } - - // Faux Edges are used to layout nodes in a group together, as if they had links between them - protected getFauxEdges(groups: LayoutGroup[], nodes: LayoutNode[]): LayoutLink[] { - const fauxEdges: LayoutLink[] = []; - groups.forEach((group: LayoutGroup) => { - const groupNodes = group.element.getNodes(); - for (let i = 0; i < groupNodes.length; i++) { - for (let j = i + 1; j < groupNodes.length; j++) { - const fauxEdge = new BaseEdge(); - const source = this.getLayoutNode(nodes, groupNodes[i]); - const target = this.getLayoutNode(nodes, groupNodes[j]); - if (source && target) { - const link = this.createLayoutLink(fauxEdge, source, target, true); - fauxEdge.setController(target.element.getController()); - fauxEdges.push(link); - } - } - } - }); - - return fauxEdges; - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new LayoutNode(node, nodeDistance, index); - } - - protected createLayoutLink(edge: Edge, source: LayoutNode, target: LayoutNode, isFalse: boolean = false): LayoutLink { - return new LayoutLink(edge, source, target, isFalse); - } - - protected createLayoutGroup(node: Node, padding: number, index: number) { - return new LayoutGroup(node, padding, index); - } - - protected getNodes(leafNodes: Node[], nodeDistance: number): LayoutNode[] { - return leafNodes.map((n, index) => this.createLayoutNode(n, nodeDistance, index)); - } - - // Default is to clear any initial bend points - protected initializeEdgeBendpoints = (edge: Edge): void => { - // remove any bendpoints - if (edge.getBendpoints().length > 0) { - edge.setBendpoints([]); - } - }; - - protected getLeafNodes = (): Node[] => leafNodeElements(this.graph.getNodes()).filter(n => n.isVisible()); - - protected getGroupNodes = (): Node[] => groupNodeElements(this.graph.getNodes()).filter(g => g.isVisible()); - - protected getLinks(edges: Edge[]): LayoutLink[] { - const links: LayoutLink[] = []; - edges.forEach(e => { - const source = this.getLayoutNode(this.nodes, e.getSource()); - const target = this.getLayoutNode(this.nodes, e.getTarget()); - if (source && target) { - this.initializeEdgeBendpoints(e); - links.push(this.createLayoutLink(e, source, target)); - } - }); - - return links; - } - - protected hasVisibleChildren = (group: Node): boolean => !!group.getNodes().find(c => isNode(c) && c.isVisible()); - - // Turn empty groups into nodes - protected getNodesFromGroups(groups: Node[], nodeDistance: number, nodeCount: number): LayoutNode[] { - let count = 0; - const groupNodes: LayoutNode[] = []; - groups.forEach((group: Node) => { - if (!this.hasVisibleChildren(group)) { - groupNodes.push(this.createLayoutNode(group, nodeDistance, nodeCount + count++)); - } - }); - - return groupNodes; - } - - protected getGroups(groups: Node[], nodes: LayoutNode[], padding: number): LayoutGroup[] { - let nodeIndex = 2 * nodes.length; - // Create groups only for those with children - const layoutGroups: LayoutGroup[] = groups - .filter(g => this.hasVisibleChildren(g)) - .map((group: Node) => this.createLayoutGroup(group, padding, nodeIndex++)); - - layoutGroups.forEach((groupNode: LayoutGroup) => { - const leaves: LayoutNode[] = []; - const leafElements = groupNode.element - .getNodes() - .filter((node: any) => !node.isGroup() || !this.hasVisibleChildren(node)); - leafElements.forEach((leaf: any) => { - const layoutLeaf = nodes.find(n => n.id === leaf.getId()); - if (layoutLeaf) { - leaves.push(layoutLeaf); - layoutLeaf.parent = groupNode; - } - }); - groupNode.leaves = leaves; - const childGroups: LayoutGroup[] = []; - const groupElements = groupNode.element - .getNodes() - .filter((node: any) => node.isGroup() && node.isVisible() && !node.isCollapsed()); - groupElements.forEach((group: any) => { - const layoutGroup = layoutGroups.find(g => g.id === group.getId()); - if (layoutGroup) { - childGroups.push(layoutGroup); - layoutGroup.parent = groupNode; - } - }); - groupNode.groups = childGroups; - }); - - return layoutGroups; - } - - protected initializeNodePositions(nodes: LayoutNode[], graph: Graph, force: boolean): void { - const { width, height } = graph.getBounds(); - const cx = width / 2; - const cy = height / 2; - - nodes.forEach((node: LayoutNode) => { - // only init position for nodes that have not been positioned - if (force || !node.element.isPositioned()) { - node.setPosition(cx, cy); - } else { - node.setFixed(true); - } - }); - } - - protected setupLayout( - graph: Graph, // eslint-disable-line @typescript-eslint/no-unused-vars - nodes: LayoutNode[], // eslint-disable-line @typescript-eslint/no-unused-vars - edges: LayoutLink[], // eslint-disable-line @typescript-eslint/no-unused-vars - groups: LayoutGroup[] // eslint-disable-line @typescript-eslint/no-unused-vars - ): void {} - - protected stopSimulation(): void { - this.forceSimulation.haltForceSimulation(); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected startLayout(graph: Graph, initialRun: boolean, addingNodes: boolean, onEnd?: () => void): void {} - - // Interim, remove and update startLayout to public in next breaking change build - public doStartLayout(graph: Graph, initialRun: boolean, addingNodes: boolean, onEnd?: () => void): void { - return this.startLayout(graph, initialRun, addingNodes, onEnd); - } - - protected updateLayout(): void { - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - this.forceSimulation.alpha(0.2); - } - - @action - private runLayout(initialRun: boolean, restart = true): void { - const prevGroups = this.groups; - - // create datum - const leafNodes = this.getLeafNodes(); - const groups = this.getGroupNodes(); - - this.nodes = this.getNodes(leafNodes, this.options.nodeDistance); - - const groupNodes: LayoutNode[] = this.getNodesFromGroups(groups, this.options.nodeDistance, this.nodes.length); - if (groupNodes) { - this.nodes.push(...groupNodes); - } - - this.groups = this.getGroups(groups, this.nodes, this.options.groupDistance); - - const newNodes: LayoutNode[] = initialRun - ? this.nodes - : this.nodes.filter(node => !this.nodesMap[node.element.getId()]); - let addingNodes = restart && newNodes.length > 0; - - if (!initialRun && restart && !addingNodes) { - this.groups.forEach(group => { - const prevGroup = prevGroups.find(g => g.element.getId() === group.element.getId()); - if (!prevGroup) { - addingNodes = true; - newNodes.push(...group.leaves); - } else { - group.leaves.forEach(node => { - if (!prevGroup.leaves.find(l => l.element.getId() === node.element.getId())) { - newNodes.push(node); - } - }); - } - }); - addingNodes = newNodes.length > 0; - } - - this.edges = this.getLinks(this.graph.getEdges()); - - // initialize new node positions - this.initializeNodePositions(this.nodes, this.graph, initialRun); - - // re-create the nodes map - this.nodesMap = this.nodes.reduce((acc, n) => { - acc[n.id] = n; - return acc; - }, {}); - - // Add faux edges to keep grouped items together - this.edges.push(...this.getFauxEdges(this.groups, this.nodes)); - - this.setupLayout(this.graph, this.nodes, this.edges, this.groups); - - if (initialRun || addingNodes) { - // Reset the force simulation - this.stopSimulation(); - - this.startLayout(this.graph, initialRun, addingNodes); - } else if (restart && this.options.layoutOnDrag) { - this.updateLayout(); - } - this.graph.getController().fireEvent(GRAPH_LAYOUT_END_EVENT, { graph: this.graph }); - } -} diff --git a/packages/react-topology/src/layouts/BreadthFirstGroup.ts b/packages/react-topology/src/layouts/BreadthFirstGroup.ts deleted file mode 100644 index 7ce82878f60..00000000000 --- a/packages/react-topology/src/layouts/BreadthFirstGroup.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LayoutGroup } from './LayoutGroup'; - -export class BreadthFirstGroup extends LayoutGroup {} diff --git a/packages/react-topology/src/layouts/BreadthFirstLayout.ts b/packages/react-topology/src/layouts/BreadthFirstLayout.ts deleted file mode 100644 index 29055947883..00000000000 --- a/packages/react-topology/src/layouts/BreadthFirstLayout.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Edge, Graph, Layout, Node } from '../types'; -import { BaseLayout } from './BaseLayout'; -import { LayoutOptions } from './LayoutOptions'; -import { LayoutNode } from './LayoutNode'; -import { LayoutLink } from './LayoutLink'; -import { BreadthFirstNode } from './BreadthFirstNode'; -import { BreadthFirstLink } from './BreadthFirstLink'; -import { BreadthFirstGroup } from './BreadthFirstGroup'; - -export type BreadthFirstLayoutOptions = LayoutOptions; - -export class BreadthFirstLayout extends BaseLayout implements Layout { - private gridOptions: BreadthFirstLayoutOptions; - - constructor(graph: Graph, options?: Partial) { - super(graph, options); - this.gridOptions = { - ...this.options, - ...options - }; - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new BreadthFirstNode(node, nodeDistance, index); - } - - protected createLayoutLink(edge: Edge, source: LayoutNode, target: LayoutNode, isFalse: boolean): LayoutLink { - return new BreadthFirstLink(edge, source, target, isFalse); - } - - protected createLayoutGroup(node: Node, padding: number, index: number) { - return new BreadthFirstGroup(node, padding, index); - } - - protected startLayout(graph: Graph, initialRun: boolean, addingNodes: boolean): void { - if (initialRun || addingNodes) { - // Breath First algorithm - - // A node is visited in the order of levels - const visited = {}; - // A node is used as a source/target, helper to detect duplicates/cycles. - const processed = {}; - // The list of nodes that are roots in the graph - const roots = {}; - // Helper map with target Ids - const targetIds = {}; - // Helper map with the list of target Ids per source Id. - const sourceIds = {}; - - let padX = 0; - let padY = 0; - - // Initial loop to populated the helpers - for (const edge of this.edges) { - if (!edge.isFalse) { - const sourceId = edge.sourceNode.id; - const targetId = edge.targetNode.id; - if (!sourceIds[sourceId]) { - sourceIds[sourceId] = []; - } - sourceIds[sourceId].push(targetId); - targetIds[targetId] = true; - } - } - - for (const node of this.nodes) { - const id = node.id; - if (!targetIds[id]) { - roots[id] = true; - } - if (padX < node.width) { - padX = node.width; - } - if (padY < node.height) { - padY = node.height; - } - } - - // Visiting all nodes to have an array of arrays with ids, organized by breath first levels - const levels: any = []; - levels.push(Object.keys(roots)); - let nl = 0; - while (Object.keys(visited).length < this.nodes.length) { - const nextLevel = {}; - for (const nodeId of levels[nl]) { - if (!visited[nodeId]) { - if (sourceIds[nodeId]) { - for (const childId of sourceIds[nodeId]) { - if (!processed[childId]) { - nextLevel[childId] = true; - processed[childId] = true; - } - } - } - visited[nodeId] = true; - processed[nodeId] = true; - } - } - const nextLevelKeys = Object.keys(nextLevel); - if (nextLevelKeys.length > 0) { - levels.push(nextLevelKeys); - } - nl++; - } - - // Updating positions with levels - let x = 0; - let y = 0; - for (const level of levels) { - const sortedLevel = level.sort((a: string, b: string) => a.localeCompare(b)); - for (const nodeId of sortedLevel) { - const node = this.nodesMap[nodeId]; - node.x = x; - node.y = y; - node.update(); - x += padX; - } - y += padY; - x = 0; - } - } - } -} diff --git a/packages/react-topology/src/layouts/BreadthFirstLink.ts b/packages/react-topology/src/layouts/BreadthFirstLink.ts deleted file mode 100644 index 55b6966d526..00000000000 --- a/packages/react-topology/src/layouts/BreadthFirstLink.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LayoutLink } from './LayoutLink'; - -export class BreadthFirstLink extends LayoutLink {} diff --git a/packages/react-topology/src/layouts/BreadthFirstNode.ts b/packages/react-topology/src/layouts/BreadthFirstNode.ts deleted file mode 100644 index 976b2d84335..00000000000 --- a/packages/react-topology/src/layouts/BreadthFirstNode.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LayoutNode } from './LayoutNode'; -import { Node } from '../types'; - -export class BreadthFirstNode extends LayoutNode { - constructor(node: Node, distance: number, index: number = -1) { - super(node, distance, index); - } -} diff --git a/packages/react-topology/src/layouts/ColaGroup.ts b/packages/react-topology/src/layouts/ColaGroup.ts deleted file mode 100644 index 37866866b05..00000000000 --- a/packages/react-topology/src/layouts/ColaGroup.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LayoutGroup } from './LayoutGroup'; -import * as webcola from 'webcola'; -export class ColaGroup extends LayoutGroup implements webcola.Group {} diff --git a/packages/react-topology/src/layouts/ColaGroupsLayout.ts b/packages/react-topology/src/layouts/ColaGroupsLayout.ts deleted file mode 100644 index de4fa23bbcb..00000000000 --- a/packages/react-topology/src/layouts/ColaGroupsLayout.ts +++ /dev/null @@ -1,252 +0,0 @@ -import * as webcola from 'webcola'; -import * as d3 from 'd3'; -import { action } from 'mobx'; -import { Graph, Layout, Node } from '../types'; -import { BaseLayout } from './BaseLayout'; -import { LayoutLink } from './LayoutLink'; -import { LayoutGroup } from './LayoutGroup'; -import { LayoutNode } from './LayoutNode'; -import { ColaGroupsNode } from './ColaGroupsNode'; -import { ColaGroup } from './ColaGroup'; -import { ColaLink } from './ColaLink'; -import { ColaLayout } from './ColaLayout'; - -export interface ChildGroup { - group: LayoutGroup; - nodes: LayoutNode[]; - edges: LayoutLink[]; - groups: LayoutGroup[]; -} - -class ColaGroupsLayout extends ColaLayout implements Layout { - private layerNodes: LayoutNode[]; - - private layerGroupNodes: ChildGroup[]; - - private layerGroups: LayoutGroup[]; - - private layerEdges: LayoutLink[]; - - private layoutNodes: LayoutNode[]; - - private childLayouts: BaseLayout[]; - - protected initializeLayout(): void {} - - protected initializeColaGroupLayout(graph: Graph): void { - this.d3Cola = webcola.d3adaptor(d3); - this.d3Cola.handleDisconnected(true); - this.d3Cola.avoidOverlaps(true); - this.d3Cola.jaccardLinkLengths(40, 0.7); - this.d3Cola.on('tick', () => { - this.tickCount++; - if (this.tickCount >= 1 || this.tickCount % this.options.simulationSpeed === 0) { - action(() => this.nodes.forEach(d => d.update()))(); - } - if (this.colaOptions.maxTicks >= 0 && this.tickCount > this.colaOptions.maxTicks) { - this.d3Cola.stop(); - } - }); - this.d3Cola.on('end', () => { - this.tickCount = 0; - this.simulationRunning = false; - action(() => { - if (this.destroyed) { - this.onEnd && this.onEnd(); - return; - } - this.layoutNodes.forEach(d => { - if (!this.simulationStopped) { - d.update(); - } - d.setFixed(false); - }); - if (this.options.layoutOnDrag) { - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - } - if (this.simulationStopped) { - this.simulationStopped = false; - if (this.restartOnEnd !== undefined) { - this.startColaLayout(false, this.restartOnEnd); - this.startLayout(graph, false, this.restartOnEnd, this.onEnd); - delete this.restartOnEnd; - } - } else if (this.addingNodes) { - // One round of simulation to adjust for new nodes - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - this.forceSimulation.restart(); - } - this.onEnd && this.onEnd(); - })(); - }); - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new ColaGroupsNode(node, nodeDistance, index); - } - - protected getAllLeaves(group: LayoutGroup): LayoutNode[] { - const leaves = [...group.leaves]; - group.groups?.forEach(subGroup => leaves.push(...this.getAllLeaves(subGroup))); - return leaves; - } - protected getAllSubGroups(group: LayoutGroup): LayoutGroup[] { - const groups = [...group.groups]; - group.groups?.forEach(subGroup => groups.push(...this.getAllSubGroups(subGroup))); - return groups; - } - - protected isNodeInGroups(node: LayoutNode, groups: LayoutGroup[]): boolean { - return !!groups.find(group => group.leaves.includes(node) || this.isNodeInGroups(node, group.groups)); - } - - protected isNodeInChildGroups(node: LayoutNode, groups: ChildGroup[]): boolean { - return !!groups.find(group => group.nodes.includes(node) || this.isNodeInGroups(node, group.groups)); - } - - protected isSubGroup(group: ChildGroup, childGroups: ChildGroup[]): boolean { - return !!childGroups.find(cg => cg.groups.includes(group.group)); - } - - protected getNodeGroup(node: LayoutNode, childGroups: ChildGroup[]): ChildGroup | undefined { - return childGroups.find(group => group.nodes.includes(node) || this.isNodeInGroups(node, group.groups)); - } - - protected getGroupLayout( - graph: Graph, - group: LayoutGroup, - nodes: LayoutNode[], - edges: LayoutLink[], - groups: LayoutGroup[] - ): BaseLayout { - const layout = new ColaGroupsLayout(graph, this.options); - layout.setupLayout(graph, nodes, edges, groups); - return layout; - } - - protected setupLayout(graph: Graph, nodes: LayoutNode[], edges: LayoutLink[], groups: LayoutGroup[]): void { - const constraints = this.getConstraints(nodes as ColaGroupsNode[], groups as ColaGroup[], edges); - let childGroups = groups.reduce((acc, group) => { - if ( - !groups.find(g => group.element.getParent()?.getId() === g.element.getId()) && - (group.groups.length || group.leaves.length) - ) { - const allLeaves = this.getAllLeaves(group); - const groupEdges = edges.filter(edge => allLeaves.includes(edge.sourceNode) && allLeaves.includes(edge.target)); - const groupGroups = this.getAllSubGroups(group); - allLeaves.forEach((l, i) => { - l.index = i; - if (l.parent && !groupGroups.includes(l.parent)) { - l.parent = undefined; - } - }); - groupGroups.forEach((g, i) => { - g.index = 2 * allLeaves.length + i; - g.parent = undefined; - }); - - acc.push({ - group, - nodes: allLeaves, - edges: groupEdges, - groups: groupGroups - }); - } - return acc; - }, [] as ChildGroup[]); - const constrainedGroups = groups.filter(g => constraints.find(c => c.group === g.element.getId())); - this.layerGroups = childGroups.filter(cg => constrainedGroups.includes(cg.group)).map(cg => cg.group); - childGroups = childGroups.filter(cg => !this.layerGroups.includes(cg.group)); - this.layerNodes = nodes.filter(node => !this.isNodeInChildGroups(node, childGroups)); - this.layerGroupNodes = childGroups.filter(cg => !this.isSubGroup(cg, childGroups)); - this.layerEdges = edges.reduce((acc, edge) => { - const source = this.getNodeGroup(edge.sourceNode, childGroups); - const target = this.getNodeGroup(edge.targetNode, childGroups); - if (!source || !target || source !== target) { - acc.push(edge); - } - return acc; - }, [] as LayoutLink[]); - this.childLayouts = childGroups.map(childGroup => - this.getGroupLayout(graph, childGroup.group, childGroup.nodes, childGroup.edges, childGroup.groups) - ); - } - - private startChildLayout( - graph: Graph, - childLayout: BaseLayout, - initialRun: boolean, - addingNodes: boolean - ): Promise { - return new Promise(resolve => { - childLayout.doStartLayout(graph, initialRun, addingNodes, () => { - resolve(); - }); - }); - } - - protected startColaLayout(initialRun: boolean, addingNodes: boolean): void { - this.simulationRunning = true; - this.tickCount = 0; - this.addingNodes = addingNodes; - - const doStart = () => { - this.initializeColaGroupLayout(this.graph); - const { width, height } = this.graph.getBounds(); - this.d3Cola.size([width, height]); - this.layoutNodes = [...this.layerNodes]; - this.layerGroupNodes.forEach(cg => { - const layoutNode = this.createLayoutNode(cg.group.element, this.options.nodeDistance, cg.group.index); - this.layoutNodes.push(layoutNode); - this.layerEdges.forEach(edge => { - if (cg.nodes.find(n => n.id === edge.sourceNode.id) || this.isNodeInGroups(edge.sourceNode, cg.groups)) { - edge.sourceNode = layoutNode; - } - if (cg.nodes.find(n => n.id === edge.targetNode.id) || this.isNodeInGroups(edge.targetNode, cg.groups)) { - edge.targetNode = layoutNode; - } - }); - }); - - // Get any custom constraints - const constraints = this.getConstraints( - this.layoutNodes as ColaGroupsNode[], - this.layerGroups as ColaGroup[], - this.layerEdges - ); - this.d3Cola.constraints(constraints); - - this.d3Cola.nodes(this.layoutNodes); - this.d3Cola.groups(this.layerGroups); - this.d3Cola.links(this.layerEdges); - this.d3Cola.alpha(0.2); - - this.d3Cola.start( - addingNodes ? 0 : this.colaOptions.initialUnconstrainedIterations, - addingNodes ? 0 : this.colaOptions.initialUserConstraintIterations, - addingNodes ? 0 : this.colaOptions.initialAllConstraintsIterations, - addingNodes ? 0 : this.colaOptions.gridSnapIterations, - false, - !addingNodes - ); - }; - - if (this.childLayouts?.length) { - const runLayouts = (childLayouts: BaseLayout[]): Promise => - Promise.all( - childLayouts.map(childLayout => this.startChildLayout(this.graph, childLayout, initialRun, addingNodes)) - ); - - runLayouts(this.childLayouts) - .then(() => { - doStart(); - }) - .catch(() => {}); - return; - } - - doStart(); - } -} - -export { ColaGroupsLayout, ColaGroupsNode, ColaGroup, ColaLink }; diff --git a/packages/react-topology/src/layouts/ColaGroupsNode.ts b/packages/react-topology/src/layouts/ColaGroupsNode.ts deleted file mode 100644 index f82fa9b4120..00000000000 --- a/packages/react-topology/src/layouts/ColaGroupsNode.ts +++ /dev/null @@ -1,58 +0,0 @@ -import * as webcola from 'webcola'; -import { isNode, Node } from '../types'; -import { LayoutNode } from './LayoutNode'; -import { Point } from '../geom'; - -export class ColaGroupsNode extends LayoutNode implements webcola.Node { - // fixed is used by Cola during node additions: 1 for fixed - public fixed: number = 0; - - constructor(node: Node, distance: number, index: number = -1) { - super(node, distance, index); - // TODO: Investigate why the issue with rectangular nodes causing the layout to become vertical - // may need to do more here like what is done in ColaNode - } - setFixed(fixed: boolean): void { - super.setFixed(fixed); - this.fixed = fixed ? 1 : 0; - } - - update() { - if (!this.isFixed && this.xx != null && this.yy != null) { - if (this.node.isGroup()) { - const prevLocation = this.node.getBounds().getCenter(); - const xOffset = this.xx - prevLocation.x; - const yOffset = this.yy - prevLocation.y; - - this.node.getChildren().forEach(child => { - if (isNode(child)) { - const node = child as Node; - const position = node.getPosition(); - node.setPosition(new Point(position.x + xOffset, position.y + yOffset)); - } - }); - } else { - this.setPosition(this.xx, this.yy); - } - } - this.xx = undefined; - this.yy = undefined; - } - - get width(): number { - return this.nodeBounds.width + this.distance * 2; - } - - get height(): number { - return this.nodeBounds.height + this.distance * 2; - } - - get radius(): number { - const bounds = this.nodeBounds; - return Math.max(bounds.width, bounds.height) / 2; - } - - get collisionRadius(): number { - return this.radius + this.distance; - } -} diff --git a/packages/react-topology/src/layouts/ColaLayout.ts b/packages/react-topology/src/layouts/ColaLayout.ts deleted file mode 100644 index 30dbfe18cc1..00000000000 --- a/packages/react-topology/src/layouts/ColaLayout.ts +++ /dev/null @@ -1,199 +0,0 @@ -import * as webcola from 'webcola'; -import * as d3 from 'd3'; -import { action } from 'mobx'; -import { Edge, Graph, Layout, Node } from '../types'; -import { BaseLayout } from './BaseLayout'; -import { LayoutOptions } from './LayoutOptions'; -import { LayoutLink } from './LayoutLink'; -import { LayoutGroup } from './LayoutGroup'; -import { LayoutNode } from './LayoutNode'; -import { ColaNode } from './ColaNode'; -import { ColaGroup } from './ColaGroup'; -import { ColaLink } from './ColaLink'; - -export interface ColaLayoutOptions { - maxTicks: number; - initialUnconstrainedIterations: number; - initialUserConstraintIterations: number; - initialAllConstraintsIterations: number; - gridSnapIterations: number; -} - -const COLA_LAYOUT_DEFAULTS: ColaLayoutOptions = { - maxTicks: 1000, - initialUnconstrainedIterations: 200, - initialUserConstraintIterations: 50, - initialAllConstraintsIterations: 150, - gridSnapIterations: 10 -}; - -class ColaLayout extends BaseLayout implements Layout { - protected d3Cola: any; - - protected colaOptions: ColaLayoutOptions; - - protected tickCount = 0; - - protected destroyed = false; - - protected simulationRunning = false; - - protected simulationStopped = false; - - protected restartOnEnd: boolean = undefined; - - protected addingNodes: boolean = false; - - protected onEnd: () => void; - - constructor(graph: Graph, options?: Partial) { - super(graph, options); - this.colaOptions = { - ...COLA_LAYOUT_DEFAULTS, - ...options - }; - this.initializeLayout(); - } - - protected initializeLayout(): void { - this.d3Cola = webcola.d3adaptor(d3); - this.d3Cola.handleDisconnected(true); - this.d3Cola.avoidOverlaps(true); - - this.d3Cola.on('tick', () => { - this.tickCount++; - if (this.tickCount >= 1 || this.tickCount % this.options.simulationSpeed === 0) { - action(() => this.nodes.forEach(d => d.update()))(); - } - if (this.colaOptions.maxTicks >= 0 && this.tickCount > this.colaOptions.maxTicks) { - this.d3Cola.stop(); - } - }); - this.d3Cola.on('end', () => { - this.tickCount = 0; - this.simulationRunning = false; - action(() => { - if (this.destroyed) { - this.onEnd && this.onEnd(); - return; - } - this.nodes.forEach(d => { - if (!this.simulationStopped) { - d.update(); - } - d.setFixed(false); - }); - if (this.options.layoutOnDrag) { - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - } - if (this.simulationStopped) { - this.simulationStopped = false; - if (this.restartOnEnd !== undefined) { - this.startColaLayout(false, this.restartOnEnd); - delete this.restartOnEnd; - } - } else if (this.addingNodes) { - // One round of simulation to adjust for new nodes - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - this.forceSimulation.restart(); - } - this.onEnd && this.onEnd(); - })(); - }); - } - - protected onSimulationEnd = () => { - if (this.addingNodes) { - if (!this.options.layoutOnDrag) { - this.forceSimulation.stopSimulation(); - } - this.addingNodes = false; - } - }; - - destroy(): void { - super.destroy(); - - this.destroyed = true; - if (this.d3Cola) { - this.d3Cola.stop(); - } - } - - initDrag() { - // Set the alpha to 0 to halt any ticks that may be occurring - if (this.d3Cola) { - this.d3Cola.alpha(0); - } - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - protected getConstraints(nodes: ColaNode[], groups: ColaGroup[], edges: ColaLink[]): any[] { - return []; - } - - protected stopSimulation(): void { - if (this.simulationRunning) { - this.simulationStopped = true; - if (this.d3Cola) { - this.d3Cola.stop(); - } - } - super.stopSimulation(); - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new ColaNode(node, nodeDistance, index); - } - - protected createLayoutLink(edge: Edge, source: LayoutNode, target: LayoutNode): LayoutLink { - return new ColaLink(edge, source, target); - } - - protected createLayoutGroup(node: Node, padding: number, index: number) { - return new ColaGroup(node, padding, index); - } - - protected getFauxEdges(): LayoutLink[] { - return []; - } - - protected setupLayout(graph: Graph, nodes: LayoutNode[], edges: LayoutLink[], groups: LayoutGroup[]): void { - const { width, height } = graph.getBounds(); - this.d3Cola.size([width, height]); - - // Get any custom constraints - this.d3Cola.constraints(this.getConstraints(nodes as ColaNode[], groups as ColaGroup[], edges)); - - this.d3Cola.nodes(nodes); - this.d3Cola.links(edges); - this.d3Cola.groups(groups); - } - - protected startColaLayout(initialRun: boolean, addingNodes: boolean): void { - this.simulationRunning = true; - this.d3Cola.alpha(0.2); - this.tickCount = 0; - this.addingNodes = addingNodes; - - this.d3Cola.start( - addingNodes ? 0 : this.colaOptions.initialUnconstrainedIterations, - addingNodes ? 0 : this.colaOptions.initialUserConstraintIterations, - addingNodes ? 0 : this.colaOptions.initialAllConstraintsIterations, - addingNodes ? 0 : this.colaOptions.gridSnapIterations, - false, - !addingNodes - ); - } - - protected startLayout(graph: Graph, initialRun: boolean, addingNodes: boolean, onEnd?: () => void): void { - this.onEnd = onEnd; - if (!this.simulationStopped) { - this.startColaLayout(initialRun, addingNodes); - } else { - this.restartOnEnd = addingNodes; - } - } -} - -export { ColaLayout, ColaNode, ColaGroup, ColaLink }; diff --git a/packages/react-topology/src/layouts/ColaLink.ts b/packages/react-topology/src/layouts/ColaLink.ts deleted file mode 100644 index 8f8db93ea49..00000000000 --- a/packages/react-topology/src/layouts/ColaLink.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Edge } from '../types'; -import { LayoutLink } from './LayoutLink'; -import { LayoutNode } from './LayoutNode'; -import { ColaNode } from './ColaNode'; -import * as webcola from 'webcola'; -export class ColaLink extends LayoutLink implements webcola.Link { - constructor(edge: Edge, source: LayoutNode | number, target: LayoutNode | number) { - super(edge, source as LayoutNode, target as LayoutNode); - } -} diff --git a/packages/react-topology/src/layouts/ColaNode.ts b/packages/react-topology/src/layouts/ColaNode.ts deleted file mode 100644 index 047b4d69843..00000000000 --- a/packages/react-topology/src/layouts/ColaNode.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as webcola from 'webcola'; -import { Node } from '../types'; -import { LayoutNode } from './LayoutNode'; - -export class ColaNode extends LayoutNode implements webcola.Node { - // fixed is used by Cola during node additions: 1 for fixed - public fixed: number = 0; - constructor(node: Node, distance: number, index: number = -1) { - super(node, distance, index); - // TODO: Investigate why the issue with rectangular nodes causing the layout to become vertical - // this setting will be a problem if nodes can change size dynamically - // Cola layout has issues with non-square nodes - const maxDimension = Math.max(this.nodeWidth, this.nodeHeight); - this.nodeWidth = maxDimension; - this.nodeHeight = maxDimension; - } - setFixed(fixed: boolean): void { - super.setFixed(fixed); - this.fixed = fixed ? 1 : 0; - } -} diff --git a/packages/react-topology/src/layouts/ConcentricGroup.ts b/packages/react-topology/src/layouts/ConcentricGroup.ts deleted file mode 100644 index ace4814c6d1..00000000000 --- a/packages/react-topology/src/layouts/ConcentricGroup.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { LayoutGroup } from './LayoutGroup'; -export class ConcentricGroup extends LayoutGroup {} diff --git a/packages/react-topology/src/layouts/ConcentricLayout.ts b/packages/react-topology/src/layouts/ConcentricLayout.ts deleted file mode 100644 index 843836996a3..00000000000 --- a/packages/react-topology/src/layouts/ConcentricLayout.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Edge, Graph, Layout, Node } from '../types'; -import { BaseLayout } from './BaseLayout'; -import { LayoutOptions } from './LayoutOptions'; -import { LayoutNode } from './LayoutNode'; -import { LayoutLink } from './LayoutLink'; -import { ConcentricNode } from './ConcentricNode'; -import { ConcentricLink } from './ConcentricLink'; -import { ConcentricGroup } from './ConcentricGroup'; - -export type ConcentricLayoutOptions = LayoutOptions & { - splitLevel?: number; -}; - -export class ConcentricLayout extends BaseLayout implements Layout { - private concentricOptions: ConcentricLayoutOptions; - - constructor(graph: Graph, options?: Partial) { - super(graph, options); - this.concentricOptions = { - ...this.options, - ...options - }; - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new ConcentricNode(node, nodeDistance, index); - } - - protected createLayoutLink(edge: Edge, source: LayoutNode, target: LayoutNode, isFalse: boolean): LayoutLink { - return new ConcentricLink(edge, source, target, isFalse); - } - - protected createLayoutGroup(node: Node, padding: number, index: number) { - return new ConcentricGroup(node, padding, index); - } - - protected startLayout(graph: Graph, initialRun: boolean, addingNodes: boolean): void { - if (initialRun || addingNodes) { - const weights = {}; - this.nodes.forEach(node => { - weights[node.id] = { in: 0, out: 0, total: 0 }; - }); - this.edges.forEach(edge => { - weights[edge.target.id].in++; - weights[edge.target.id].total++; - weights[edge.source.id].out++; - weights[edge.source.id].total++; - }); - - const nodesWeight = Object.keys(weights).map(k => ({ id: k, total: weights[k].total })); - nodesWeight.sort((a: any, b: any) => b.total - a.total); - - const splitLevel = this.concentricOptions.splitLevel ? this.concentricOptions.splitLevel : 4; - const levelWidth = nodesWeight.length > 0 ? nodesWeight[0].total / splitLevel : 0; - const levels: any = [[]]; - let currentLevel = levels[0]; - nodesWeight.forEach(n => { - if (currentLevel.length > 0) { - const diff = Math.abs(currentLevel[0].total - n.total); - if (diff >= levelWidth) { - currentLevel = []; - levels.push(currentLevel); - } - } - - currentLevel.push(n); - }); - - let innerR = 0; - let maxWH = 0; - // This padding should be configurable - const padding = maxWH; - if (levels.length > 0) { - let maxWidth = 0; - let maxHeight = 0; - levels[0].forEach((n: any) => { - const node = this.nodesMap[n.id]; - if (maxWidth < node.width) { - maxWidth = node.width; - } - if (maxHeight < node.height) { - maxHeight = node.height; - } - }); - maxWH = Math.max(maxWidth, maxHeight); - innerR = Math.round((levels[0].length * maxWH) / (2 * Math.PI)); - } - const outerR = levels.length * (maxWH + padding) + innerR; - const center = { - x: outerR + maxWH, - y: outerR + maxWH - }; - - let r = innerR; - for (const level of levels) { - const theta = (2 * Math.PI) / level.length; - for (let j = 0; j < level.length; j++) { - const node = this.nodesMap[level[j].id]; - node.x = center.x + r * Math.cos(theta * j); - node.y = center.y + r * Math.sin(theta * j); - node.update(); - } - r += maxWH + padding; - } - } - } -} diff --git a/packages/react-topology/src/layouts/ConcentricLink.ts b/packages/react-topology/src/layouts/ConcentricLink.ts deleted file mode 100644 index f00a225488f..00000000000 --- a/packages/react-topology/src/layouts/ConcentricLink.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LayoutLink } from './LayoutLink'; - -export class ConcentricLink extends LayoutLink {} diff --git a/packages/react-topology/src/layouts/ConcentricNode.ts b/packages/react-topology/src/layouts/ConcentricNode.ts deleted file mode 100644 index 409c9011511..00000000000 --- a/packages/react-topology/src/layouts/ConcentricNode.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LayoutNode } from './LayoutNode'; -import { Node } from '../types'; - -export class ConcentricNode extends LayoutNode { - constructor(node: Node, distance: number, index: number = -1) { - super(node, distance, index); - } -} diff --git a/packages/react-topology/src/layouts/DagreGroup.ts b/packages/react-topology/src/layouts/DagreGroup.ts deleted file mode 100644 index aa6cd313462..00000000000 --- a/packages/react-topology/src/layouts/DagreGroup.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { LayoutGroup } from './LayoutGroup'; -export class DagreGroup extends LayoutGroup {} diff --git a/packages/react-topology/src/layouts/DagreLayout.ts b/packages/react-topology/src/layouts/DagreLayout.ts deleted file mode 100644 index ecab6c47b8f..00000000000 --- a/packages/react-topology/src/layouts/DagreLayout.ts +++ /dev/null @@ -1,93 +0,0 @@ -import * as dagre from 'dagre'; -import * as _ from 'lodash'; -import { Edge, Graph, Layout, Node } from '../types'; -import { BaseLayout, LAYOUT_DEFAULTS } from './BaseLayout'; -import { LayoutOptions } from './LayoutOptions'; -import { LayoutLink } from './LayoutLink'; -import { LayoutNode } from './LayoutNode'; -import { DagreNode } from './DagreNode'; -import { DagreGroup } from './DagreGroup'; -import { DagreLink } from './DagreLink'; - -export type DagreLayoutOptions = LayoutOptions & dagre.GraphLabel & { ignoreGroups?: boolean }; - -export class DagreLayout extends BaseLayout implements Layout { - protected dagreOptions: DagreLayoutOptions; - - constructor(graph: Graph, options?: Partial) { - super(graph, options); - this.dagreOptions = { - ...this.options, - layoutOnDrag: false, - marginx: 0, - marginy: 0, - nodesep: this.options.nodeDistance, - edgesep: this.options.linkDistance, - ranker: 'tight-tree', - rankdir: 'TB', - ...options - }; - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new DagreNode(node, nodeDistance, index); - } - - protected createLayoutLink(edge: Edge, source: LayoutNode, target: LayoutNode, isFalse: boolean): LayoutLink { - return new DagreLink(edge, source, target, isFalse); - } - - protected createLayoutGroup(node: Node, padding: number, index: number) { - return new DagreGroup(node, padding, index); - } - - protected updateEdgeBendpoints(edges: DagreLink[]): void { - _.forEach(edges, edge => { - const link = edge as DagreLink; - link.updateBendpoints(); - }); - } - - protected getFauxEdges(): LayoutLink[] { - return []; - } - - protected startLayout(graph: Graph, initialRun: boolean, addingNodes: boolean): void { - if (initialRun || addingNodes) { - const dagreGraph = new dagre.graphlib.Graph({ compound: true }); - dagreGraph.setGraph(_.omit(this.dagreOptions, Object.keys(LAYOUT_DEFAULTS))); - - if (!this.dagreOptions.ignoreGroups) { - _.forEach(this.groups, group => { - dagreGraph.setNode(group.id, group); - dagreGraph.setParent(group.id, group.element.getParent().getId()); - }); - } - - const updatedNodes: dagre.Node[] = []; - _.forEach(this.nodes, node => { - const updateNode = (node as DagreNode).getUpdatableNode(); - updatedNodes.push(updateNode); - dagreGraph.setNode(node.id, updateNode); - if (!this.dagreOptions.ignoreGroups) { - dagreGraph.setParent(node.id, node.element.getParent().getId()); - } - }); - - _.forEach(this.edges, dagreEdge => { - dagreGraph.setEdge(dagreEdge.source.id, dagreEdge.target.id, dagreEdge); - }); - - dagre.layout(dagreGraph); - this.nodes.forEach(node => { - (node as DagreNode).updateToNode(dagreGraph.node(node.id)); - }); - - this.updateEdgeBendpoints(this.edges as DagreLink[]); - } - - if (this.dagreOptions.layoutOnDrag) { - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - } - } -} diff --git a/packages/react-topology/src/layouts/DagreLink.ts b/packages/react-topology/src/layouts/DagreLink.ts deleted file mode 100644 index d33e36518b3..00000000000 --- a/packages/react-topology/src/layouts/DagreLink.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Point from '../geom/Point'; -import { LayoutLink } from './LayoutLink'; -export class DagreLink extends LayoutLink { - public points?: { x: number; y: number }[]; - updateBendpoints(): void { - if (this.points && !this.isFalse && this.points.length > 2) { - this.element.setBendpoints(this.points.slice(1, -1).map((point: any) => new Point(point.x, point.y))); - } - } -} diff --git a/packages/react-topology/src/layouts/DagreNode.ts b/packages/react-topology/src/layouts/DagreNode.ts deleted file mode 100644 index 6a92887c264..00000000000 --- a/packages/react-topology/src/layouts/DagreNode.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { LayoutNode } from './LayoutNode'; -export class DagreNode extends LayoutNode implements dagre.Node { - getUpdatableNode(): dagre.Node { - return { - id: this.id, - width: this.width, - height: this.height, - x: this.x, - y: this.y - }; - } - updateToNode(updatedNode: dagre.Node | undefined): void { - if (updatedNode) { - this.x = updatedNode.x; - this.y = updatedNode.y; - this.update(); - } - } -} diff --git a/packages/react-topology/src/layouts/ForceLayout.ts b/packages/react-topology/src/layouts/ForceLayout.ts deleted file mode 100644 index aae92b559a0..00000000000 --- a/packages/react-topology/src/layouts/ForceLayout.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Graph, Layout } from '../types'; -import { getGroupPadding } from '../utils/element-utils'; -import { ForceSimulationNode } from './ForceSimulation'; -import { BaseLayout } from '.'; -import { LayoutLink } from './LayoutLink'; -import { LayoutOptions } from './LayoutOptions'; - -export class ForceLayout extends BaseLayout implements Layout { - constructor(graph: Graph, options?: Partial) { - super(graph, { - ...options, - layoutOnDrag: true, - onSimulationEnd: () => { - this.nodes.forEach(n => n.setFixed(false)); - } - }); - } - - protected getLinkDistance = (e: LayoutLink | d3.SimulationLinkDatum) => { - let distance = this.options.linkDistance + e.source.radius + e.target.radius; - const isFalse = e instanceof LayoutLink && e.isFalse; - if (!isFalse && e.source.element.getParent() !== e.target.element.getParent()) { - // find the group padding - distance += getGroupPadding(e.source.element.getParent()); - distance += getGroupPadding(e.target.element.getParent()); - } - - return distance; - }; - - protected startLayout(graph: Graph): void { - const { width, height } = graph.getBounds(); - const cx = width / 2; - const cy = height / 2; - this.forceSimulation.forceCenter(cx, cy); - this.forceSimulation.alpha(1); - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getLinkDistance); - this.forceSimulation.restart(); - } - - protected updateLayout(): void { - this.forceSimulation.useForceSimulation(this.nodes, this.edges, this.getFixedNodeDistance); - this.forceSimulation.alpha(0.2); - this.forceSimulation.restart(); - } -} diff --git a/packages/react-topology/src/layouts/ForceSimulation.ts b/packages/react-topology/src/layouts/ForceSimulation.ts deleted file mode 100644 index a879dd58bc8..00000000000 --- a/packages/react-topology/src/layouts/ForceSimulation.ts +++ /dev/null @@ -1,112 +0,0 @@ -import * as d3 from 'd3'; -import { action } from 'mobx'; - -export interface ForceSimulationNode extends d3.SimulationNodeDatum { - id: string; - collisionRadius: number; - update(): void; -} - -interface ForceSimulationOptions { - collideDistance: number; - simulationSpeed: number; - chargeStrength: number; - onSimulationEnd?: () => void; -} - -class ForceSimulation { - private forceLink: d3.ForceLink>; - - private simulation: any; - - private options: ForceSimulationOptions; - - private destroyed = false; - - constructor(options?: Partial) { - this.options = { - ...{ - collideDistance: 0, - simulationSpeed: 10, - chargeStrength: 0 - }, - ...options - }; - - // Setup Force Simulation - this.simulation = d3.forceSimulation(); - this.simulation.force( - 'collide', - d3.forceCollide().radius(d => d.collisionRadius + this.options.collideDistance) - ); - this.simulation.force('charge', d3.forceManyBody().strength(this.options.chargeStrength)); - this.simulation.alpha(0); - this.forceLink = d3.forceLink>().id(e => e.id); - - this.simulation.force('link', this.forceLink); - this.simulation.on( - 'tick', - action(() => { - // speed up the simulation - for (let i = 0; i < this.options.simulationSpeed; i++) { - this.simulation.tick(); - } - this.simulation.nodes().forEach((d: ForceSimulationNode) => !this.destroyed && d.update()); - }) - ); - if (options.onSimulationEnd) { - this.simulation.on('end', this.options.onSimulationEnd); - } - } - - public destroy(): void { - this.destroyed = true; - this.simulation.stop(); - } - - public useForceSimulation( - nodes: ForceSimulationNode[], - links: d3.SimulationLinkDatum[], - distance: ( - link: d3.SimulationLinkDatum, - i: number, - links: d3.SimulationLinkDatum[] - ) => number - ): void { - this.forceLink.distance(distance); - - // first remove the links so that the layout doesn't error - this.forceLink.links([]); - - this.simulation.nodes([...nodes]); - this.forceLink.links([...links]); - } - - public haltForceSimulation(): void { - this.simulation.alpha(0); - this.simulation.nodes([]); - this.forceLink.links([]); - } - - public forceCenter(cx: number, cy: number): void { - this.simulation.force('center', d3.forceCenter(cx, cy)); - } - - public stopSimulation(): void { - this.simulation.stop(); - } - - public restart() { - this.simulation.restart(); - } - - public alpha(value: number) { - this.simulation.alpha(value); - } - - public alphaTarget(value: number) { - this.simulation.alphaTarget(value); - } -} - -export { ForceSimulation }; diff --git a/packages/react-topology/src/layouts/GridGroup.ts b/packages/react-topology/src/layouts/GridGroup.ts deleted file mode 100644 index 9fdae85a85e..00000000000 --- a/packages/react-topology/src/layouts/GridGroup.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { LayoutGroup } from './LayoutGroup'; -export class GridGroup extends LayoutGroup {} diff --git a/packages/react-topology/src/layouts/GridLayout.ts b/packages/react-topology/src/layouts/GridLayout.ts deleted file mode 100644 index a68d4096840..00000000000 --- a/packages/react-topology/src/layouts/GridLayout.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Edge, Graph, Layout, Node } from '../types'; -import { BaseLayout } from './BaseLayout'; -import { LayoutOptions } from './LayoutOptions'; -import { LayoutNode } from './LayoutNode'; -import { LayoutLink } from './LayoutLink'; -import { GridNode } from './GridNode'; -import { GridLink } from './GridLink'; -import { GridGroup } from './GridGroup'; - -export type GridLayoutOptions = LayoutOptions; - -export class GridLayout extends BaseLayout implements Layout { - private gridOptions: GridLayoutOptions; - - constructor(graph: Graph, options?: Partial) { - super(graph, options); - this.gridOptions = { - ...this.options, - ...options - }; - } - - protected createLayoutNode(node: Node, nodeDistance: number, index: number) { - return new GridNode(node, nodeDistance, index); - } - - protected createLayoutLink(edge: Edge, source: LayoutNode, target: LayoutNode, isFalse: boolean): LayoutLink { - return new GridLink(edge, source, target, isFalse); - } - - protected createLayoutGroup(node: Node, padding: number, index: number) { - return new GridGroup(node, padding, index); - } - - protected startLayout(graph: Graph, initialRun: boolean, addingNodes: boolean): void { - if (initialRun || addingNodes) { - this.nodes.sort((a, b) => a.id.localeCompare(b.id)); - const totalNodes = this.nodes.length; - const maxPerRow = Math.round(Math.sqrt(totalNodes)); - let x = 0; - let y = 0; - let rowI = 0; - let padX = 0; - let padY = 0; - for (let i = 0; i < totalNodes; i++) { - const node = this.nodes[i]; - if (padX < node.width) { - padX = node.width; - } - if (padY < node.height) { - padY = node.height; - } - } - for (let i = 0; i < totalNodes; i++) { - const node = this.nodes[i]; - node.x = x; - node.y = y; - node.update(); - - if (rowI < maxPerRow) { - x += padX; - rowI++; - } else { - rowI = 0; - x = 0; - y += padY; - } - } - } - } -} diff --git a/packages/react-topology/src/layouts/GridLink.ts b/packages/react-topology/src/layouts/GridLink.ts deleted file mode 100644 index 9970bb0d400..00000000000 --- a/packages/react-topology/src/layouts/GridLink.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { LayoutLink } from './LayoutLink'; - -export class GridLink extends LayoutLink {} diff --git a/packages/react-topology/src/layouts/GridNode.ts b/packages/react-topology/src/layouts/GridNode.ts deleted file mode 100644 index e092e59f2e0..00000000000 --- a/packages/react-topology/src/layouts/GridNode.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LayoutNode } from './LayoutNode'; -import { Node } from '../types'; - -export class GridNode extends LayoutNode { - constructor(node: Node, distance: number, index: number = -1) { - super(node, distance, index); - } -} diff --git a/packages/react-topology/src/layouts/LayoutGroup.ts b/packages/react-topology/src/layouts/LayoutGroup.ts deleted file mode 100644 index 20fefd66a32..00000000000 --- a/packages/react-topology/src/layouts/LayoutGroup.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Node } from '../types'; -import { LayoutNode } from './LayoutNode'; -export class LayoutGroup { - protected readonly node: Node; - public leaves: LayoutNode[] = []; - public groups: LayoutGroup[] = []; - public parent?: LayoutGroup; - public padding: number; - public index: number; - constructor(node: Node, padding: number, index: number) { - this.node = node; - this.padding = padding; - this.index = index; - } - get element(): Node { - return this.node; - } - get id(): string { - return this.node.getId(); - } -} diff --git a/packages/react-topology/src/layouts/LayoutLink.ts b/packages/react-topology/src/layouts/LayoutLink.ts deleted file mode 100644 index 48a7cfbb493..00000000000 --- a/packages/react-topology/src/layouts/LayoutLink.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Edge } from '../types'; -import { LayoutNode } from './LayoutNode'; -export class LayoutLink { - private readonly edge: Edge; - public sourceNode: LayoutNode; - public targetNode: LayoutNode; - public isFalse: boolean; - constructor(edge: Edge, source: LayoutNode, target: LayoutNode, isFalse: boolean = false) { - this.edge = edge; - this.sourceNode = source; - this.targetNode = target; - this.isFalse = isFalse; - } - get element(): Edge { - return this.edge; - } - get id(): string { - return this.edge.getId(); - } - get source(): any { - return this.sourceNode; - } - get target(): any { - return this.targetNode; - } -} diff --git a/packages/react-topology/src/layouts/LayoutNode.ts b/packages/react-topology/src/layouts/LayoutNode.ts deleted file mode 100644 index 7a4f6545999..00000000000 --- a/packages/react-topology/src/layouts/LayoutNode.ts +++ /dev/null @@ -1,93 +0,0 @@ -import * as d3 from 'd3'; -import { Node, NodeStyle } from '../types'; -import { Point, Rect } from '../geom'; -import { LayoutGroup } from './LayoutGroup'; - -export class LayoutNode implements d3.SimulationNodeDatum { - protected readonly node: Node; - protected xx?: number; - protected yy?: number; - protected nodeWidth: number; - protected nodeHeight: number; - protected nodeRadius: number; - public readonly distance: number; - public parent?: LayoutGroup; - public index: number; - // isFixed is used locally for Force simulation during drag events - public isFixed: boolean = false; - constructor(node: Node, distance: number, index: number = -1) { - this.node = node; - this.distance = distance; - this.index = index; - // Currently we support only fixed node sizes, this will need to change if/when dynamic node sizes are supported - const bounds = this.nodeBounds; - this.nodeWidth = bounds.width + this.distance * 2; - this.nodeHeight = bounds.height + this.distance * 2; - this.nodeRadius = Math.max(bounds.width, bounds.height) / 2; - } - get element(): Node { - return this.node; - } - get id(): string { - return this.node.getId(); - } - get x(): number { - return this.xx || this.node.getBounds().getCenter().x; - } - set x(x: number) { - if (!Number.isNaN(x)) { - this.xx = x; - } - } - get y(): number { - return this.yy || this.node.getBounds().getCenter().y; - } - set y(y: number) { - if (!Number.isNaN(y)) { - this.yy = y; - } - } - get fx(): number | undefined { - return this.isFixed ? this.node.getBounds().getCenter().x : undefined; - } - get fy(): number | undefined { - return this.isFixed ? this.node.getBounds().getCenter().y : undefined; - } - setPosition(x: number, y: number) { - const bounds = this.node.getBounds(); - this.node.setPosition(new Point(x - bounds.width / 2, y - bounds.height / 2)); - } - setFixed(fixed: boolean): void { - this.isFixed = fixed; - } - get nodeBounds(): Rect { - const { padding } = this.node.getStyle(); - // Currently non-group nodes do not include their padding in the bounds - if (!this.node.isGroup() && padding) { - return this.node - .getBounds() - .clone() - .padding(padding); - } - return this.node.getBounds(); - } - get width(): number { - return this.nodeWidth; - } - get height(): number { - return this.nodeHeight; - } - update() { - if (!this.isFixed && this.xx != null && this.yy != null) { - this.setPosition(this.xx, this.yy); - } - this.xx = undefined; - this.yy = undefined; - } - get radius(): number { - return this.nodeRadius; - } - get collisionRadius(): number { - return this.radius + this.distance; - } -} diff --git a/packages/react-topology/src/layouts/LayoutOptions.ts b/packages/react-topology/src/layouts/LayoutOptions.ts deleted file mode 100644 index 9027fcc6d0f..00000000000 --- a/packages/react-topology/src/layouts/LayoutOptions.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface LayoutOptions { - linkDistance: number; - nodeDistance: number; - groupDistance: number; - collideDistance: number; - simulationSpeed: number; - chargeStrength: number; - allowDrag: boolean; - layoutOnDrag: boolean; - onSimulationEnd?: () => void; -} diff --git a/packages/react-topology/src/layouts/index.ts b/packages/react-topology/src/layouts/index.ts deleted file mode 100644 index 4efa664c427..00000000000 --- a/packages/react-topology/src/layouts/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from './BaseLayout'; -export * from './BreadthFirstLayout'; -export * from './ColaLayout'; -export * from './ColaGroupsLayout'; -export * from './ConcentricLayout'; -export * from './DagreLayout'; -export * from './ForceLayout'; -export * from './GridLayout'; -export * from './LayoutNode'; -export * from './LayoutGroup'; -export * from './LayoutLink'; -export * from './LayoutOptions'; diff --git a/packages/react-topology/src/mobx-exports.ts b/packages/react-topology/src/mobx-exports.ts deleted file mode 100644 index b4e5f492c36..00000000000 --- a/packages/react-topology/src/mobx-exports.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { action } from 'mobx'; -import { observer } from 'mobx-react'; - -// re-export for ease of use externally -export { action, observer }; diff --git a/packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchor.ts b/packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchor.ts deleted file mode 100644 index a03759cc004..00000000000 --- a/packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchor.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Point } from '../../../geom'; -import { AbstractAnchor } from '../../../anchors'; -import { Node, ScaleDetailsLevel } from '../../../types'; - -export default class TaskNodeSourceAnchor extends AbstractAnchor { - private detailsLevel: ScaleDetailsLevel; - private lowDetailsStatusIconWidth = 0; - - constructor(owner: E, detailsLevel: ScaleDetailsLevel, lowDetailsStatusIconWidth: number) { - super(owner); - this.detailsLevel = detailsLevel; - this.lowDetailsStatusIconWidth = lowDetailsStatusIconWidth; - } - - getLocation(): Point { - return this.getReferencePoint(); - } - - getReferencePoint(): Point { - const bounds = this.owner.getBounds(); - if (this.detailsLevel !== ScaleDetailsLevel.high) { - const scale = this.owner.getGraph().getScale(); - return new Point(bounds.x + this.lowDetailsStatusIconWidth * (1 / scale), bounds.y + bounds.height / 2); - } - return new Point(bounds.right(), bounds.y + bounds.height / 2); - } -} diff --git a/packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchorSave.ts b/packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchorSave.ts deleted file mode 100644 index e3b0db29287..00000000000 --- a/packages/react-topology/src/pipelines/components/anchors/TaskNodeSourceAnchorSave.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Point } from '../../../geom'; -import { AbstractAnchor } from '../../../anchors'; -import { Node } from '../../../types'; - -export default class TaskNodeSourceAnchor extends AbstractAnchor { - private pillWidth = 0; - private whenOffset = 0; - - constructor(owner: E, whenOffset: number, pillWidth: number) { - super(owner); - this.whenOffset = whenOffset; - this.pillWidth = pillWidth; - } - getLocation(): Point { - return this.getReferencePoint(); - } - - getReferencePoint(): Point { - const bounds = this.owner.getBounds(); - return new Point(bounds.x + this.pillWidth + this.whenOffset, bounds.y + bounds.height / 2); - } -} diff --git a/packages/react-topology/src/pipelines/components/anchors/TaskNodeTargetAnchor.ts b/packages/react-topology/src/pipelines/components/anchors/TaskNodeTargetAnchor.ts deleted file mode 100644 index 86b624a128f..00000000000 --- a/packages/react-topology/src/pipelines/components/anchors/TaskNodeTargetAnchor.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Point } from '../../../geom'; -import { AbstractAnchor } from '../../../anchors'; -import { Node } from '../../../types'; - -export default class TaskNodeTargetAnchor extends AbstractAnchor { - private whenOffset = 0; - - constructor(owner: E, whenOffset: number) { - super(owner); - this.whenOffset = whenOffset; - } - - getLocation(): Point { - return this.getReferencePoint(); - } - - getReferencePoint(): Point { - const bounds = this.owner.getBounds(); - return new Point(bounds.x + this.whenOffset, bounds.y + bounds.height / 2); - } -} diff --git a/packages/react-topology/src/pipelines/components/anchors/index.ts b/packages/react-topology/src/pipelines/components/anchors/index.ts deleted file mode 100644 index 6151e954e2b..00000000000 --- a/packages/react-topology/src/pipelines/components/anchors/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as TaskNodeSourceAnchor } from './TaskNodeSourceAnchor'; -export { default as TaskNodeTargetAnchor } from './TaskNodeTargetAnchor'; diff --git a/packages/react-topology/src/pipelines/components/edges/TaskEdge.tsx b/packages/react-topology/src/pipelines/components/edges/TaskEdge.tsx deleted file mode 100644 index d9c66df54d8..00000000000 --- a/packages/react-topology/src/pipelines/components/edges/TaskEdge.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { Edge } from '../../../types'; -import { integralShapePath } from '../../utils'; - -interface TaskEdgeProps { - /** The graph edge element to represent */ - element: Edge; - /** Additional classes added to the edge */ - className?: string; - /** Offset for integral shape path */ - nodeSeparation?: number; -} - -const TaskEdge: React.FunctionComponent = ({ element, className, nodeSeparation }: TaskEdgeProps) => { - const startPoint = element.getStartPoint(); - const endPoint = element.getEndPoint(); - const groupClassName = css(styles.topologyEdge, className); - const startIndent: number = element.getData()?.indent || 0; - - return ( - - - - ); -}; - -export default observer(TaskEdge); diff --git a/packages/react-topology/src/pipelines/components/edges/WhenEdge.tsx b/packages/react-topology/src/pipelines/components/edges/WhenEdge.tsx deleted file mode 100644 index 9013365aabe..00000000000 --- a/packages/react-topology/src/pipelines/components/edges/WhenEdge.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import * as React from 'react'; -import { Edge, EdgeTerminalType } from '../../../types'; -import { DefaultEdge } from '../../../components'; - -const WhenEdge: React.FC<{ element: Edge }> = ({ element }) => ( - -); - -export default WhenEdge; diff --git a/packages/react-topology/src/pipelines/components/edges/index.ts b/packages/react-topology/src/pipelines/components/edges/index.ts deleted file mode 100644 index 782ddda45b0..00000000000 --- a/packages/react-topology/src/pipelines/components/edges/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as TaskEdge } from './TaskEdge'; -export { default as WhenEdge } from './WhenEdge'; diff --git a/packages/react-topology/src/pipelines/components/groups/DefaultTaskGroup.tsx b/packages/react-topology/src/pipelines/components/groups/DefaultTaskGroup.tsx deleted file mode 100644 index 369b8c3b754..00000000000 --- a/packages/react-topology/src/pipelines/components/groups/DefaultTaskGroup.tsx +++ /dev/null @@ -1,182 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import CollapseIcon from '@patternfly/react-icons/dist/esm/icons/compress-alt-icon'; -import NodeLabel from '../../../components/nodes/labels/NodeLabel'; -import { Layer } from '../../../components/layers'; -import { GROUPS_LAYER } from '../../../const'; -import { maxPadding, useCombineRefs, useHover } from '../../../utils'; -import { BadgeLocation, isGraph, LabelPosition, Node, NodeStyle } from '../../../types'; -import { - useDragNode, - WithContextMenuProps, - WithDndDropProps, - WithDragNodeProps, - WithSelectionProps -} from '../../../behavior'; -import { CollapsibleGroupProps } from '../../../components'; - -type DefaultTaskGroupProps = { - className?: string; - element: Node; - droppable?: boolean; - canDrop?: boolean; - dropTarget?: boolean; - dragging?: boolean; - hover?: boolean; - label?: string; // Defaults to element.getLabel() - secondaryLabel?: string; - showLabel?: boolean; // Defaults to true - truncateLength?: number; // Defaults to 13 - badge?: string; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; - labelOffset?: number; // Space between the label and the group - labelIconClass?: string; // Icon to show in label - labelIcon?: string; - labelIconPadding?: number; -} & Partial; - -const DefaultTaskGroup: React.FunctionComponent = ({ - className, - element, - collapsible, - selected, - onSelect, - hover, - label, - secondaryLabel, - showLabel = true, - truncateLength, - canDrop, - dropTarget, - onContextMenu, - contextMenuOpen, - dragging, - dragNodeRef, - badge, - badgeColor, - badgeTextColor, - badgeBorderColor, - badgeClassName, - badgeLocation, - labelOffset = 17, - labelIconClass, - labelIcon, - labelIconPadding, - onCollapseChange -}) => { - const [hovered, hoverRef] = useHover(); - const [labelHover, labelHoverRef] = useHover(); - const dragLabelRef = useDragNode()[1]; - const refs = useCombineRefs(hoverRef, dragNodeRef); - const isHover = hover !== undefined ? hover : hovered; - const labelPosition = element.getLabelPosition(); - - let parent = element.getParent(); - let altGroup = false; - while (!isGraph(parent)) { - altGroup = !altGroup; - parent = parent.getParent(); - } - - const children = element.getNodes().filter(c => c.isVisible()); - - // cast to number and coerce - const padding = maxPadding(element.getStyle().padding ?? 17); - - const { minX, minY, maxX, maxY } = children.reduce( - (acc, child) => { - const bounds = child.getBounds(); - return { - minX: Math.min(acc.minX, bounds.x - padding), - minY: Math.min(acc.minY, bounds.y - padding), - maxX: Math.max(acc.maxX, bounds.x + bounds.width + padding), - maxY: Math.max(acc.maxY, bounds.y + bounds.height + padding) - }; - }, - { minX: Infinity, minY: Infinity, maxX: 0, maxY: 0 } - ); - - const [labelX, labelY] = React.useMemo(() => { - if (!showLabel || !(label || element.getLabel())) { - return [0, 0]; - } - switch (labelPosition) { - case LabelPosition.right: - return [maxX + labelOffset, minY + (maxY - minY) / 2]; - case LabelPosition.bottom: - default: - return [minX + (maxX - minX) / 2, maxY + labelOffset]; - } - }, [element, label, labelOffset, labelPosition, maxX, maxY, minX, minY, showLabel]); - - if (children.length === 0) { - return null; - } - - const groupClassName = css( - styles.topologyGroup, - className, - altGroup && 'pf-m-alt-group', - canDrop && 'pf-m-highlight', - dragging && 'pf-m-dragging', - selected && 'pf-m-selected' - ); - const innerGroupClassName = css( - styles.topologyGroup, - className, - altGroup && 'pf-m-alt-group', - canDrop && 'pf-m-highlight', - dragging && 'pf-m-dragging', - selected && 'pf-m-selected', - (isHover || labelHover) && 'pf-m-hover', - canDrop && dropTarget && 'pf-m-drop-target' - ); - - return ( - - - - - - - {showLabel && (label || element.getLabel()) && ( - : undefined} - onActionIconClick={() => onCollapseChange(element, true)} - > - {label || element.getLabel()} - - )} - - ); -}; - -export default observer(DefaultTaskGroup); diff --git a/packages/react-topology/src/pipelines/components/groups/index.ts b/packages/react-topology/src/pipelines/components/groups/index.ts deleted file mode 100644 index ff1e08c3f81..00000000000 --- a/packages/react-topology/src/pipelines/components/groups/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as DefaultTaskGroup } from './DefaultTaskGroup'; diff --git a/packages/react-topology/src/pipelines/components/index.ts b/packages/react-topology/src/pipelines/components/index.ts deleted file mode 100644 index 0c85f63ba31..00000000000 --- a/packages/react-topology/src/pipelines/components/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './anchors'; -export * from './nodes'; -export * from './edges'; -export * from './groups'; diff --git a/packages/react-topology/src/pipelines/components/nodes/FinallyNode.tsx b/packages/react-topology/src/pipelines/components/nodes/FinallyNode.tsx deleted file mode 100644 index 39c32957daa..00000000000 --- a/packages/react-topology/src/pipelines/components/nodes/FinallyNode.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import TaskNode, { TaskNodeProps } from './TaskNode'; - -const FinallyNode: React.FC = props => ( - -); - -export default FinallyNode; diff --git a/packages/react-topology/src/pipelines/components/nodes/SpacerNode.tsx b/packages/react-topology/src/pipelines/components/nodes/SpacerNode.tsx deleted file mode 100644 index b0b37504a13..00000000000 --- a/packages/react-topology/src/pipelines/components/nodes/SpacerNode.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import { observer } from '../../../mobx-exports'; -import { Node } from '../../../types'; - -const SpacerNode: React.FC<{ element: Node }> = () => ; - -export default observer(SpacerNode); diff --git a/packages/react-topology/src/pipelines/components/nodes/TaskBadge.tsx b/packages/react-topology/src/pipelines/components/nodes/TaskBadge.tsx deleted file mode 100644 index 9d67bf0a68f..00000000000 --- a/packages/react-topology/src/pipelines/components/nodes/TaskBadge.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* eslint patternfly-react/import-tokens-icons: 0 */ -import * as React from 'react'; -import { css } from '@patternfly/react-styles'; -import { global_palette_blue_50 as defaultBadgeFill } from '@patternfly/react-tokens/dist/js/global_palette_blue_50'; -import { global_palette_blue_300 as defaultBadgeBorder } from '@patternfly/react-tokens/dist/js/global_palette_blue_300'; -import { global_palette_blue_300 as defaultBadgeTextColor } from '@patternfly/react-tokens/dist/js/global_palette_blue_300'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { useSize } from '../../../utils'; -import { BadgeLocation } from '../../../types'; - -interface LabelBadgeProps { - className?: string; - x: number; - y: number; - badge?: React.ReactNode; - badgeColor?: string; - badgeTextColor?: string; - badgeBorderColor?: string; - badgeClassName?: string; - badgeLocation?: BadgeLocation; -} - -const TaskBadge = React.forwardRef( - ({ badge, badgeTextColor, badgeColor, badgeBorderColor, badgeClassName, className, x, y }, iconRef) => { - const [textSize, textRef] = useSize([]); - const classes = css(styles.topologyNodeLabelBadge, badgeClassName && badgeClassName, className && className); - - let rect = null; - let paddingX = 0; - let paddingY = 0; - let width = 0; - let height = 0; - - if (textSize) { - ({ height, width } = textSize); - paddingX = height / 2; - paddingY = height / 14; - height += paddingY * 2; - rect = ( - - ); - } - return ( - - {rect} - {typeof badge === 'string' ? ( - - {badge} - - ) : ( - {badge} - )} - - ); - } -); - -export default TaskBadge; diff --git a/packages/react-topology/src/pipelines/components/nodes/TaskNode.tsx b/packages/react-topology/src/pipelines/components/nodes/TaskNode.tsx deleted file mode 100644 index 759c734c70d..00000000000 --- a/packages/react-topology/src/pipelines/components/nodes/TaskNode.tsx +++ /dev/null @@ -1,493 +0,0 @@ -import * as React from 'react'; -import { TooltipProps } from '@patternfly/react-core'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-pipelines'; -import topologyStyles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { Popover, PopoverProps, Tooltip } from '@patternfly/react-core'; -import { observer } from '../../../mobx-exports'; -import { AnchorEnd, Node, ScaleDetailsLevel } from '../../../types'; -import { RunStatus } from '../../types'; -import { OnSelect, useAnchor } from '../../../behavior'; -import { truncateMiddle } from '../../../utils/truncate-middle'; -import { createSvgIdUrl, getNodeScaleTranslation, useCombineRefs, useHover, useSize } from '../../../utils'; -import { getRunStatusModifier, nonShadowModifiers } from '../../utils'; -import StatusIcon from '../../utils/StatusIcon'; -import { TaskNodeSourceAnchor, TaskNodeTargetAnchor } from '../anchors'; -import LabelActionIcon from '../../../components/nodes/labels/LabelActionIcon'; -import LabelContextMenu from '../../../components/nodes/labels/LabelContextMenu'; -import NodeShadows, { - NODE_SHADOW_FILTER_ID_DANGER, - NODE_SHADOW_FILTER_ID_HOVER -} from '../../../components/nodes/NodeShadows'; -import LabelBadge from '../../../components/nodes/labels/LabelBadge'; -import LabelIcon from '../../../components/nodes/labels/LabelIcon'; -import useDetailsLevel from '../../../hooks/useDetailsLevel'; -import { useScaleNode } from '../../../hooks'; - -const STATUS_ICON_SIZE = 16; -const SCALE_UP_TIME = 200; - -export interface TaskNodeProps { - /** Forwarded ref */ - innerRef?: React.Ref; - /** Additional content added to the node */ - children?: React.ReactNode; - /** Additional classes added to the node */ - className?: string; - /** The graph node element to represent */ - element: Node; - /** Padding to use before and after contents */ - paddingX?: number; - /** Padding to use above and below contents */ - paddingY?: number; - /** Additional classes added to the label */ - nameLabelClass?: string; - /** RunStatus to depict */ - status?: RunStatus; - /** Size of the status icon */ - statusIconSize?: number; - /** Flag indicating the status indicator */ - showStatusState?: boolean; - /** Flag indicating the node should be scaled, best on hover of the node at lowest scale level */ - scaleNode?: boolean; - /** Flag to hide details at medium scale */ - hideDetailsAtMedium?: boolean; - /** Statuses to show at when details are hidden */ - hiddenDetailsShownStatuses?: RunStatus[]; - /** Text for the label's badge */ - badge?: string; - /** Color to use for the label's badge background */ - badgeColor?: string; - /** Color to use for the label's badge text */ - badgeTextColor?: string; - /** Color to use for the label's badge border */ - badgeBorderColor?: string; - /** Additional classes to use for the label's badge */ - badgeClassName?: string; - /** @deprecated Use badgePopoverParams instead */ - badgePopoverProps?: string; - /** Set to use a tooltip on the badge, takes precedence over the badgePopoverParams */ - badgeTooltip?: React.ReactNode; - /** Set to use a popover on the badge, ignored if the badgeTooltip parameter is set */ - badgePopoverParams?: PopoverProps; - /** Icon to show for the task */ - taskIconClass?: string; - /** Element to show for the task icon */ - taskIcon?: React.ReactNode; - /** Set to use a tooltip on the task icon */ - taskIconTooltip?: React.ReactNode; - /** Padding to use around the task icon */ - taskIconPadding?: number; - /** Flag if the user is hovering on the node */ - hover?: boolean; - /** The maximum length of the label before truncation */ - truncateLength?: number; - /** Flag if the tooltip is disabled */ - disableTooltip?: boolean; - /** Tooltip to show on node hover */ - toolTip?: React.ReactNode; - /** Tooltip properties to pass along to the node's tooltip */ - toolTipProps?: Omit; - /** Flag if the node has a 'when expression' */ - hasWhenExpression?: boolean; - /** Size of the when expression indicator */ - whenSize?: number; - /** Distance from the when expression indicator to the node */ - whenOffset?: number; - /** Icon to use for the action menu */ - actionIcon?: React.ReactElement; - /** Additional classes to use for the action icon */ - actionIconClassName?: string; - /** Callback when the action icon is clicked */ - onActionIconClick?: (e: React.MouseEvent) => void; - /** Flag if the element is selected. Part of WithSelectionProps */ - selected?: boolean; - /** Function to call when the element should become selected (or deselected). Part of WithSelectionProps */ - onSelect?: OnSelect; - /** Function to call to show a context menu for the node */ - onContextMenu?: (e: React.MouseEvent) => void; - /** Flag indicating that the context menu for the node is currently open */ - contextMenuOpen?: boolean; -} - -export const TaskNode: React.FC = ({ - innerRef, - element, - className, - paddingX = 8, - paddingY = 8, - status, - statusIconSize = STATUS_ICON_SIZE, - showStatusState = true, - scaleNode, - hideDetailsAtMedium, - hiddenDetailsShownStatuses = [RunStatus.Failed, RunStatus.FailedToStart, RunStatus.Cancelled], - badge, - badgeColor, - badgeTextColor, - badgeBorderColor, - badgeClassName = styles.topologyPipelinesPillBadge, - badgeTooltip, - badgePopoverProps, - badgePopoverParams, - taskIconClass, - taskIcon, - taskIconTooltip, - taskIconPadding = 4, - hover, - truncateLength = 14, - toolTip, - toolTipProps, - disableTooltip = false, - selected, - onSelect, - hasWhenExpression = false, - whenSize = 0, - whenOffset = 0, - onContextMenu, - contextMenuOpen, - actionIcon, - actionIconClassName, - onActionIconClick, - children -}: TaskNodeProps & { innerRef?: React.Ref }) => { - const [hovered, innerHoverRef] = useHover(); - const hoverRef = useCombineRefs(innerRef, innerHoverRef); - const isHover = hover !== undefined ? hover : hovered; - const { width } = element.getBounds(); - const label = truncateMiddle(element.getLabel(), { length: truncateLength, omission: '...' }); - const [textSize, textRef] = useSize([label, className]); - const [statusSize, statusRef] = useSize([status, showStatusState, statusIconSize]); - const [badgeSize, badgeRef] = useSize([badge]); - const [actionSize, actionRef] = useSize([actionIcon, paddingX]); - const [contextSize, contextRef] = useSize([onContextMenu, paddingX]); - const detailsLevel = useDetailsLevel(); - - if (badgePopoverProps) { - // eslint-disable-next-line no-console - console.warn('badgePopoverProps is deprecated. Use badgePopoverParams instead.'); - } - - const textWidth = textSize?.width ?? 0; - const textHeight = textSize?.height ?? 0; - useAnchor( - // Include scaleNode to cause an update when it changes - // eslint-disable-next-line react-hooks/exhaustive-deps - React.useCallback((node: Node) => new TaskNodeSourceAnchor(node, detailsLevel, statusIconSize + 4), [ - detailsLevel, - statusIconSize, - scaleNode - ]), - AnchorEnd.source - ); - useAnchor( - React.useCallback((node: Node) => new TaskNodeTargetAnchor(node, hasWhenExpression ? 0 : whenSize + whenOffset), [ - hasWhenExpression, - whenSize, - whenOffset - ]), - AnchorEnd.target - ); - - const { - height, - statusStartX, - textStartX, - actionStartX, - contextStartX, - pillWidth, - badgeStartX, - iconWidth, - iconStartX - } = React.useMemo(() => { - if (!textSize) { - return { - height: 0, - statusStartX: 0, - textStartX: 0, - actionStartX: 0, - contextStartX: 0, - pillWidth: 0, - badgeStartX: 0, - iconWidth: 0, - iconStartX: 0 - }; - } - const height: number = textHeight + 2 * paddingY; - const startX = paddingX + paddingX / 2; - - const iconWidth = taskIconClass || taskIcon ? height - taskIconPadding : 0; - const iconStartX = -(iconWidth * 0.75); - - const statusStartX = startX - statusIconSize / 4; // Adjust for icon padding - const statusSpace = status && showStatusState && statusSize ? statusSize.width + paddingX : 0; - - const textStartX = startX + statusSpace; - const textSpace = textWidth + paddingX; - - const badgeStartX = textStartX + textSpace; - const badgeSpace = badge && badgeSize ? badgeSize.width + paddingX : 0; - - const actionStartX = badgeStartX + badgeSpace; - const actionSpace = actionIcon && actionSize ? actionSize.width + paddingX : 0; - - const contextStartX = actionStartX + actionSpace; - const contextSpace = onContextMenu && contextSize ? contextSize.width + paddingX / 2 : 0; - - const pillWidth = contextStartX + contextSpace + paddingX / 2; - - return { - height, - statusStartX, - textStartX, - actionStartX, - contextStartX, - badgeStartX, - iconWidth, - iconStartX, - pillWidth - }; - }, [ - textSize, - textHeight, - textWidth, - paddingY, - paddingX, - taskIconClass, - taskIcon, - taskIconPadding, - statusIconSize, - status, - showStatusState, - statusSize, - badgeSize, - badge, - actionIcon, - actionSize, - onContextMenu, - contextSize - ]); - - React.useEffect(() => { - const sourceEdges = element.getSourceEdges(); - sourceEdges.forEach(edge => { - const data = edge.getData(); - edge.setData({ ...(data || {}), indent: detailsLevel === ScaleDetailsLevel.high ? width - pillWidth : 0 }); - }); - }, [detailsLevel, element, pillWidth, width]); - - const scale = element.getGraph().getScale(); - const nodeScale = useScaleNode(scaleNode, scale, SCALE_UP_TIME); - const { translateX, translateY } = getNodeScaleTranslation(element, nodeScale, scaleNode); - - const nameLabel = ( - - {label} - - ); - - const runStatusModifier = getRunStatusModifier(status); - const pillClasses = css( - styles.topologyPipelinesPill, - className, - isHover && styles.modifiers.hover, - runStatusModifier, - selected && styles.modifiers.selected, - onSelect && styles.modifiers.selectable - ); - - let filter: string; - if (runStatusModifier === styles.modifiers.danger) { - filter = createSvgIdUrl(NODE_SHADOW_FILTER_ID_DANGER); - } else if (isHover && !nonShadowModifiers.includes(runStatusModifier)) { - filter = createSvgIdUrl(NODE_SHADOW_FILTER_ID_HOVER); - } - - const taskIconComponent = (taskIconClass || taskIcon) && ( - - ); - - const badgeLabel = badge ? ( - - ) : null; - - let badgeComponent: React.ReactNode; - if (badgeLabel && badgeTooltip) { - badgeComponent = {badgeLabel}; - } else if (badgeLabel && badgePopoverParams) { - badgeComponent = ( - e.stopPropagation()}> - {badgeLabel} - - ); - } else { - badgeComponent = badgeLabel; - } - - const renderTask = () => { - if (showStatusState && !scaleNode && hideDetailsAtMedium && detailsLevel !== ScaleDetailsLevel.high) { - const statusBackgroundRadius = statusIconSize / 2 + 4; - const height = element.getBounds().height; - const upScale = 1 / scale; - - return ( - - - {status && (!hiddenDetailsShownStatuses || hiddenDetailsShownStatuses.includes(status)) ? ( - - - - - - ) : null} - - ); - } - return ( - - - - - {element.getLabel() !== label && !disableTooltip ? ( - - {nameLabel} - - ) : ( - nameLabel - )} - - {status && showStatusState && ( - - - - - - )} - {taskIconComponent && - (taskIconTooltip ? {taskIconComponent} : taskIconComponent)} - {badgeComponent} - {actionIcon && ( - <> - - - - )} - {textSize && onContextMenu && ( - <> - - - - )} - {children} - - ); - }; - - return ( - - {!toolTip || disableTooltip ? ( - renderTask() - ) : ( - - {renderTask()} - - )} - - ); -}; -TaskNode.displayName = 'TaskNode'; - -export default observer( - React.forwardRef((props: TaskNodeProps, ref: React.Ref) => ) -); diff --git a/packages/react-topology/src/pipelines/components/nodes/index.ts b/packages/react-topology/src/pipelines/components/nodes/index.ts deleted file mode 100644 index 3fdcc26ce9b..00000000000 --- a/packages/react-topology/src/pipelines/components/nodes/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as FinallyNode } from './FinallyNode'; -export { default as SpacerNode } from './SpacerNode'; -export { default as StatusIcon } from '../../utils/StatusIcon'; -export { default as TaskNode } from './TaskNode'; -export { default as WhenNode } from '../../decorators/WhenDecorator'; diff --git a/packages/react-topology/src/pipelines/const.ts b/packages/react-topology/src/pipelines/const.ts deleted file mode 100644 index a987c4fd7a5..00000000000 --- a/packages/react-topology/src/pipelines/const.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const NODE_SEPARATION_HORIZONTAL = 70; -export const NODE_SEPARATION_VERTICAL = 35; - -export enum DrawDesign { - INTEGRAL_SHAPE = 'integral-shape', - STRAIGHT = 'line' -} - -export const DEFAULT_TASK_NODE_TYPE = 'DEFAULT_TASK_NODE'; -export const DEFAULT_SPACER_NODE_TYPE = 'DEFAULT_SPACER_NODE'; -export const DEFAULT_EDGE_TYPE = 'DEFAULT_EDGE'; -export const DEFAULT_FINALLY_NODE_TYPE = 'DEFAULT_FINALLY_NODE'; diff --git a/packages/react-topology/src/pipelines/decorators/WhenDecorator.tsx b/packages/react-topology/src/pipelines/decorators/WhenDecorator.tsx deleted file mode 100644 index 5ba9d96d22c..00000000000 --- a/packages/react-topology/src/pipelines/decorators/WhenDecorator.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import * as React from 'react'; -import { Tooltip } from '@patternfly/react-core'; -import { css } from '@patternfly/react-styles'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-pipelines'; -import topologyStyles from '@patternfly/react-styles/css/components/Topology/topology-components'; -import { observer } from '../../mobx-exports'; -import { Node } from '../../types'; -import { WhenStatus } from '../types'; -import { OnSelect } from '../../behavior'; -import { getWhenStatusModifier } from '../utils'; - -export const DEFAULT_WHEN_SIZE = 12; -export const DEFAULT_WHEN_OFFSET = 12; - -interface WhenDecoratorProps { - /** Additional classes added to the node */ - className?: string; - /** The graph node element to represent */ - element: Node; - /** Offest distance from the start of the node area */ - leftOffset?: number; - /** Length of the edge between the when decorator and the node */ - edgeLength?: number; - /** Width of the when decorator */ - width?: number; - /** Height of the when decorator */ - height?: number; - /** Additional classes added to the label */ - nameLabelClass?: string; - /** WhenStatus to depict */ - status?: WhenStatus; - /** Flag indicating the status indicator */ - showStatusState?: boolean; - /** Flag if the tooltip is disabled */ - disableTooltip?: boolean; - /** Tooltip to show on decorator hover */ - toolTip?: React.ReactNode; - /** Flag if the element selected. Part of WithSelectionProps */ - selected?: boolean; - /** Function to call when the element should become selected (or deselected). Part of WithSelectionProps */ - onSelect?: OnSelect; -} - -export const WhenDecorator: React.FC = ({ - element, - width = DEFAULT_WHEN_SIZE, - height = DEFAULT_WHEN_SIZE, - className, - status, - leftOffset = DEFAULT_WHEN_OFFSET, - edgeLength = DEFAULT_WHEN_OFFSET, - toolTip, - disableTooltip = false -}: WhenDecoratorProps) => { - const { height: taskHeight } = element.getBounds(); - const y = taskHeight / 2 - height / 2; - const startX = -width - leftOffset; - const points = `${startX + width / 2} ${y} ${startX + width} ${y + height / 2} ${startX + width / 2} ${y + - height} ${startX} ${y + height / 2}`; - const diamondNode = ( - - - - - - ); - - return toolTip && !disableTooltip ? ( - {toolTip}}> - {diamondNode} - - ) : ( - diamondNode - ); -}; -WhenDecorator.displayName = 'WhenDecorator'; - -export default observer(WhenDecorator); diff --git a/packages/react-topology/src/pipelines/decorators/index.ts b/packages/react-topology/src/pipelines/decorators/index.ts deleted file mode 100644 index 705922d3b8a..00000000000 --- a/packages/react-topology/src/pipelines/decorators/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './WhenDecorator'; diff --git a/packages/react-topology/src/pipelines/index.ts b/packages/react-topology/src/pipelines/index.ts deleted file mode 100644 index b1e34879698..00000000000 --- a/packages/react-topology/src/pipelines/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './components'; -export * from './decorators'; -export * from './layouts'; -export * from './utils'; -export * from './const'; -export * from './types'; diff --git a/packages/react-topology/src/pipelines/layouts/PipelineDagreLayout.ts b/packages/react-topology/src/pipelines/layouts/PipelineDagreLayout.ts deleted file mode 100644 index 72999f3c057..00000000000 --- a/packages/react-topology/src/pipelines/layouts/PipelineDagreLayout.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Graph, Layout } from '../../types'; -import { NODE_SEPARATION_HORIZONTAL, NODE_SEPARATION_VERTICAL } from '../const'; -import { DagreLayout, DagreLayoutOptions } from '../../layouts/DagreLayout'; - -export class PipelineDagreLayout extends DagreLayout implements Layout { - constructor(graph: Graph, options?: Partial) { - super(graph, { - linkDistance: 0, - nodeDistance: 0, - groupDistance: 0, - collideDistance: 0, - simulationSpeed: 0, - chargeStrength: 0, - allowDrag: false, - layoutOnDrag: false, - nodesep: NODE_SEPARATION_VERTICAL, - ranksep: NODE_SEPARATION_HORIZONTAL, - edgesep: 50, - ranker: 'longest-path', - rankdir: 'LR', - marginx: 20, - marginy: 20, - ...options - }); - } - set nodesep(nodesep: number) { - this.dagreOptions.nodesep = nodesep; - } - set ranksep(ranksep: number) { - this.dagreOptions.ranksep = ranksep; - } -} diff --git a/packages/react-topology/src/pipelines/layouts/index.ts b/packages/react-topology/src/pipelines/layouts/index.ts deleted file mode 100644 index 64865e28f39..00000000000 --- a/packages/react-topology/src/pipelines/layouts/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './PipelineDagreLayout'; diff --git a/packages/react-topology/src/pipelines/types.ts b/packages/react-topology/src/pipelines/types.ts deleted file mode 100644 index fed54730cb1..00000000000 --- a/packages/react-topology/src/pipelines/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { NodeModel } from '../types'; - -export enum RunStatus { - Succeeded = 'Succeeded', - Failed = 'Failed', - Running = 'Running', - InProgress = 'InProgress', - FailedToStart = 'FailedToStart', - Skipped = 'Skipped', - Cancelled = 'Cancelled', - Pending = 'Pending', - Idle = 'Idle' -} - -export enum WhenStatus { - Met = 'Met', - Unmet = 'Unmet', - Pending = 'Pending', - InProgress = 'InProgress' -} - -export type PipelineNodeModel = NodeModel & { - runAfterTasks?: string[]; -}; diff --git a/packages/react-topology/src/pipelines/utils/StatusIcon.tsx b/packages/react-topology/src/pipelines/utils/StatusIcon.tsx deleted file mode 100644 index 0bf48d683ec..00000000000 --- a/packages/react-topology/src/pipelines/utils/StatusIcon.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import * as React from 'react'; -import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon'; -import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon'; -import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon'; -import CircleIcon from '@patternfly/react-icons/dist/esm/icons/circle-icon'; -import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; -import NotStartedIcon from '@patternfly/react-icons/dist/esm/icons/not-started-icon'; -import HourglassHalfIcon from '@patternfly/react-icons/dist/esm/icons/hourglass-half-icon'; -import SyncAltIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon'; -import InProgressIcon from '@patternfly/react-icons/dist/esm/icons/in-progress-icon'; -import { RunStatus } from '../types'; - -interface StatusIconProps { - className?: string; - status: RunStatus; - height?: number; - width?: number; -} - -const StatusIcon: React.FC = ({ status, ...props }) => { - switch (status) { - case RunStatus.InProgress: - return ; - - case RunStatus.Running: - return ; - - case RunStatus.Succeeded: - return ; - - case RunStatus.Failed: - case RunStatus.FailedToStart: - return ; - - case RunStatus.Idle: - return ; - - case RunStatus.Pending: - return ; - - case RunStatus.Cancelled: - return ; - - case RunStatus.Skipped: - return ; - - default: - return ; - } -}; - -export default StatusIcon; diff --git a/packages/react-topology/src/pipelines/utils/draw-utils.ts b/packages/react-topology/src/pipelines/utils/draw-utils.ts deleted file mode 100644 index 923f3ccab05..00000000000 --- a/packages/react-topology/src/pipelines/utils/draw-utils.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Point } from '../../geom'; -import { DrawDesign, NODE_SEPARATION_HORIZONTAL } from '../const'; - -type SingleDraw = (p: Point) => string; -type DoubleDraw = (p1: Point, p2: Point, startIndentX?: number, junctionOffset?: number) => string; -type TripleDraw = (p1: Point, p2: Point, p3: Point) => string; -type DetermineDirection = (p1: Point, p2: Point) => boolean; - -const join = (...segments: string[]) => segments.filter(seg => !!seg).join(' '); - -const leftRight: DetermineDirection = (p1, p2) => p1.x < p2.x; -const topDown: DetermineDirection = (p1, p2) => p1.y < p2.y; -const bottomUp: DetermineDirection = (p1, p2) => p1.y > p2.y; - -const point: SingleDraw = p => `${p.x},${p.y}`; -const moveTo: SingleDraw = p => `M ${point(p)}`; -const lineTo: SingleDraw = p => `L ${point(p)}`; -const quadTo: DoubleDraw = (corner, end) => `Q ${point(corner)} ${point(end)}`; - -// TODO: Try to simplify -// x should not be greater than (NODE_SEPARATION_HORIZONTAL / 2) -const CURVE_SIZE = { x: 8, y: 10 }; -const curve: TripleDraw = (fromPoint, cornerPoint, toPoint) => { - const topToBottom = topDown(fromPoint, toPoint); - if (topToBottom) { - const rightAndDown = leftRight(fromPoint, cornerPoint) && topDown(cornerPoint, toPoint); - const downAndRight = topDown(fromPoint, cornerPoint) && leftRight(cornerPoint, toPoint); - if (rightAndDown) { - return join( - lineTo(cornerPoint.clone().translate(-CURVE_SIZE.x, 0)), - quadTo(cornerPoint, cornerPoint.clone().translate(0, CURVE_SIZE.y)) - ); - } - if (downAndRight) { - return join( - lineTo(cornerPoint.clone().translate(0, -CURVE_SIZE.y)), - quadTo(cornerPoint, cornerPoint.clone().translate(CURVE_SIZE.x, 0)) - ); - } - } else { - const rightAndUp = leftRight(fromPoint, cornerPoint) && bottomUp(cornerPoint, toPoint); - const upAndRight = bottomUp(fromPoint, cornerPoint) && leftRight(cornerPoint, toPoint); - if (rightAndUp) { - return join( - lineTo(cornerPoint.clone().translate(-CURVE_SIZE.x, 0)), - quadTo(cornerPoint, cornerPoint.clone().translate(0, -CURVE_SIZE.y)) - ); - } - if (upAndRight) { - return join( - lineTo(cornerPoint.clone().translate(0, CURVE_SIZE.y)), - quadTo(cornerPoint, cornerPoint.clone().translate(CURVE_SIZE.x, 0)) - ); - } - } - - return ''; -}; - -export const straightPath: DoubleDraw = (start, finish) => join(moveTo(start), lineTo(finish)); - -export const integralShapePath: DoubleDraw = ( - start, - finish, - startIndentX = 0, - nodeSeparation = NODE_SEPARATION_HORIZONTAL -) => { - // Integral shape: ∫ - let firstCurve: string = null; - let secondCurve: string = null; - - if (start.y !== finish.y) { - const cornerX = Math.floor(start.x + nodeSeparation / 2); - const firstCorner = new Point(cornerX, start.y); - const secondCorner = new Point(cornerX, finish.y); - - firstCurve = curve(start, firstCorner, secondCorner); - secondCurve = curve(firstCorner, secondCorner, finish); - } - - const indentedStart = new Point(start.x - startIndentX, start.y); - return join(moveTo(indentedStart), firstCurve, secondCurve, lineTo(finish)); -}; - -export const path = (start: Point, finish: Point, drawDesign?: DrawDesign) => { - switch (drawDesign) { - case DrawDesign.INTEGRAL_SHAPE: - return integralShapePath(start, finish); - case DrawDesign.STRAIGHT: - default: - return straightPath(start, finish); - } -}; diff --git a/packages/react-topology/src/pipelines/utils/index.ts b/packages/react-topology/src/pipelines/utils/index.ts deleted file mode 100644 index ca202efded4..00000000000 --- a/packages/react-topology/src/pipelines/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './draw-utils'; -export * from './utils'; -export { default as StatusIcon } from './StatusIcon'; diff --git a/packages/react-topology/src/pipelines/utils/utils.ts b/packages/react-topology/src/pipelines/utils/utils.ts deleted file mode 100644 index 89692008e62..00000000000 --- a/packages/react-topology/src/pipelines/utils/utils.ts +++ /dev/null @@ -1,203 +0,0 @@ -import styles from '@patternfly/react-styles/css/components/Topology/topology-pipelines'; -import { PipelineNodeModel, RunStatus, WhenStatus } from '../types'; -import { EdgeModel } from '../../types'; -import { DEFAULT_EDGE_TYPE, DEFAULT_FINALLY_NODE_TYPE, DEFAULT_SPACER_NODE_TYPE } from '../const'; - -export const nonShadowModifiers: string[] = [ - styles.modifiers.danger, - styles.modifiers.warning, - styles.modifiers.success, - styles.modifiers.skipped, - styles.modifiers.inProgress -]; - -export const getRunStatusModifier = (status: RunStatus): string => { - switch (status) { - case RunStatus.Failed: - case RunStatus.FailedToStart: - return styles.modifiers.danger; - case RunStatus.Succeeded: - return styles.modifiers.success; - case RunStatus.Cancelled: - return styles.modifiers.warning; - case RunStatus.Skipped: - return styles.modifiers.skipped; - case RunStatus.Running: - return styles.modifiers.running; - case RunStatus.InProgress: - return styles.modifiers.inProgress; - case RunStatus.Pending: - return styles.modifiers.pending; - case RunStatus.Idle: - return styles.modifiers.idle; - default: - return ''; - } -}; - -export const getWhenStatusModifier = (status: WhenStatus): string => { - switch (status) { - case WhenStatus.Met: - return styles.modifiers.success; - case WhenStatus.Unmet: - return styles.modifiers.unmet; - case WhenStatus.InProgress: - case WhenStatus.Pending: - return styles.modifiers.inProgress; - default: - return ''; - } -}; - -const getSpacerId = (ids: string[]): string => - [...ids] - .sort((a, b) => a.localeCompare(b)) - .reduce((acc, ref) => { - if (acc) { - return `${acc}|${ref}`; - } - return ref; - }, ''); - -export const getSpacerNodes = ( - nodes: PipelineNodeModel[], - spacerNodeType = DEFAULT_SPACER_NODE_TYPE, - finallyNodeTypes: string[] = [DEFAULT_FINALLY_NODE_TYPE] -): PipelineNodeModel[] => { - interface ParallelNodeMap { - [id: string]: PipelineNodeModel[]; - } - const finallyNodes = nodes.filter(n => finallyNodeTypes.includes(n.type)); - // Collect only multiple run-afters - const multipleRunBeforeMap: ParallelNodeMap = nodes.reduce((acc, node) => { - const { runAfterTasks } = node; - if (runAfterTasks && runAfterTasks.length > 1) { - const id: string = getSpacerId(runAfterTasks); - if (!Array.isArray(acc[id])) { - acc[id] = []; - } - acc[id].push(node); - } - return acc; - }, {} as ParallelNodeMap); - - // Trim out single occurrences - const multiParallelToParallelList: ParallelNodeMap = Object.keys(multipleRunBeforeMap).reduce((acc, key) => { - if (multipleRunBeforeMap[key].length > 1) { - acc[key] = multipleRunBeforeMap[key]; - } - return acc; - }, {}); - - const spacerNodes: PipelineNodeModel[] = []; - - // Insert a spacer node between the multiple nodes on the sides of a parallel-to-parallel - Object.keys(multiParallelToParallelList).forEach(key => { - spacerNodes.push({ - id: key, - type: spacerNodeType - }); - }); - - if (finallyNodes.length > 1) { - const finallyId = getSpacerId(finallyNodes.map(n => n.id)); - spacerNodes.push({ - id: finallyId, - type: spacerNodeType, - width: 1, - height: 1 - }); - } - - return spacerNodes; -}; - -export const getEdgesFromNodes = ( - nodes: PipelineNodeModel[], - spacerNodeType = DEFAULT_SPACER_NODE_TYPE, - edgeType = DEFAULT_EDGE_TYPE, - spacerEdgeType = DEFAULT_EDGE_TYPE, - finallyNodeTypes: string[] = [DEFAULT_FINALLY_NODE_TYPE], - finallyEdgeType = DEFAULT_EDGE_TYPE -): EdgeModel[] => { - const edges: EdgeModel[] = []; - - const spacerNodes = nodes.filter(n => n.type === spacerNodeType); - const taskNodes = nodes.filter(n => n.type !== spacerNodeType); - const finallyNodes = nodes.filter(n => finallyNodeTypes.includes(n.type)); - const lastTasks = nodes - .filter(n => !finallyNodeTypes.includes(n.type)) - .filter(n => spacerNodeType !== n.type) - .filter(t => !nodes.find(n => n.runAfterTasks?.includes(t.id))); - - spacerNodes.forEach(spacer => { - const sourceIds = spacer.id.split('|'); - sourceIds.forEach(sourceId => { - const node = nodes.find(n => n.id === sourceId); - if (node && !finallyNodes.includes(node)) { - edges.push({ - id: `${sourceId}-${spacer.id}`, - type: spacerEdgeType, - source: sourceId, - target: spacer.id - }); - } - }); - }); - - taskNodes.forEach(node => { - if (node.runAfterTasks) { - const spacerId: string = getSpacerId([...node.runAfterTasks]); - const spacer = spacerNodes.find(n => n.id === spacerId); - if (spacer) { - edges.push({ - id: `${spacer.id}-${node.id}`, - type: spacerEdgeType, - source: spacer.id, - target: node.id - }); - } else if (node.runAfterTasks) { - node.runAfterTasks.forEach(afterId => { - edges.push({ - id: `${afterId}-${node.id}`, - type: edgeType, - source: afterId, - target: node.id - }); - }); - } - } - }); - - if (finallyNodes.length > 1) { - const finallyId = getSpacerId(finallyNodes.map(n => n.id)); - finallyNodes.forEach(finallyNode => { - edges.push({ - id: `${finallyId}-${finallyNode.id}`, - type: spacerEdgeType, - source: finallyId, - target: finallyNode.id - }); - }); - lastTasks.forEach(lastTaskNode => { - edges.push({ - id: `${lastTaskNode.id}-${finallyId}`, - type: spacerEdgeType, - source: lastTaskNode.id, - target: finallyId - }); - }); - } - if (finallyNodes.length === 1) { - lastTasks.forEach(lastTaskNode => { - edges.push({ - id: `finallyId-${lastTaskNode.id}-${finallyNodes[0].id}`, - type: finallyEdgeType, - source: lastTaskNode.id, - target: finallyNodes[0].id - }); - }); - } - - return edges; -}; diff --git a/packages/react-topology/src/types.ts b/packages/react-topology/src/types.ts deleted file mode 100644 index 7bf4e1bff47..00000000000 --- a/packages/react-topology/src/types.ts +++ /dev/null @@ -1,353 +0,0 @@ -import { ComponentType } from 'react'; -import Point from './geom/Point'; -import Dimensions from './geom/Dimensions'; -import Rect from './geom/Rect'; -import { Padding, Translatable } from './geom/types'; - -// x, y -export type PointTuple = [number, number]; - -export interface Layout { - layout(): void; - stop(): void; - destroy(): void; -} - -export interface Model { - graph?: GraphModel; - nodes?: NodeModel[]; - edges?: EdgeModel[]; -} - -export enum AnchorEnd { - target, - source, - both -} - -export interface NodeStyle { - padding?: Padding; -} - -export enum TopologyQuadrant { - upperLeft = 'upperLeft', - upperRight = 'upperRight', - lowerLeft = 'lowerLeft', - lowerRight = 'lowerRight' -} - -export enum NodeShape { - circle = 'circle', // backward compatibility - ellipse = 'ellipse', - rect = 'rect', - rhombus = 'rhombus', - trapezoid = 'trapezoid', - hexagon = 'hexagon', - octagon = 'octagon', - stadium = 'stadium' -} - -export enum NodeStatus { - default = 'default', - info = 'info', - success = 'success', - warning = 'warning', - danger = 'danger' -} - -export enum EdgeStyle { - default = 'default', - solid = 'solid', - dotted = 'dotted', - dashed = 'dashed', - dashedMd = 'dashedMd', - dashedLg = 'dashedLg', - dashedXl = 'dashedXl' -} - -export enum EdgeAnimationSpeed { - none = 'none', - slow = 'slow', - mediumSlow = 'mediumSlow', - medium = 'medium', - mediumFast = 'mediumFast', - fast = 'fast' -} - -export enum EdgeTerminalType { - none = 'none', - directional = 'directional', - directionalAlt = 'directionalAlt', - circle = 'circle', - square = 'square', - cross = 'cross' -} - -export enum LabelPosition { - right, - bottom -} - -export enum BadgeLocation { - inner, - below -} - -export enum ModelKind { - graph = 'graph', - node = 'node', - edge = 'edge' -} - -export interface ElementModel { - id: string; - type: string; - label?: string; - visible?: boolean; - children?: string[]; - data?: any; - style?: { [key: string]: any }; -} - -export interface NodeModel extends ElementModel { - x?: number; - y?: number; - width?: number; - height?: number; - group?: boolean; - shape?: NodeShape; - status?: NodeStatus; - collapsed?: boolean; - labelPosition?: LabelPosition; -} - -export interface EdgeModel extends ElementModel { - source?: string; - target?: string; - edgeStyle?: EdgeStyle; - animationSpeed?: EdgeAnimationSpeed; - bendpoints?: PointTuple[]; -} - -// Scale extent: [min scale, max scale] -export type ScaleExtent = [number, number]; - -export enum ScaleDetailsLevel { - high = 'high', - medium = 'medium', - low = 'low' -} - -export interface ScaleDetailsThresholds { - low: number; - medium: number; -} - -type Never = { [K in keyof Type]?: never }; -type EitherNotBoth = (TypeA & Never) | (TypeB & Never); - -interface ViewPaddingPixels { - padding: number; -} -interface ViewPaddingPercentage { - paddingPercentage: number; -} - -export type ViewPaddingSettings = EitherNotBoth; - -export interface GraphModel extends ElementModel { - layout?: string; - x?: number; - y?: number; - scale?: number; - scaleExtent?: ScaleExtent; - layers?: string[]; -} - -export interface Anchor { - getLocation(reference: Point): Point; - getReferencePoint(): Point; -} - -export interface GraphElement extends WithState { - destroy(): void; - getKind(): ModelKind; - getLabel(): string; - setLabel(label: string): void; - getOrderKey(): number[]; - hasController(): boolean; - getController(): Controller; - setController(controller?: Controller): void; - getGraph(): Graph; - getParent(): GraphElement; - hasParent(): boolean; - setParent(parent: GraphElement | undefined): void; - getId(): string; - setId(id: string): void; - getType(): string; - setType(type: string): void; - setVisible(visible: boolean): void; - isVisible(): boolean; - getData(): D | undefined; - setData(data: D | undefined): void; - getChildren(): GraphElement[]; - insertChild(child: GraphElement, index: number): void; - appendChild(child: GraphElement): void; - removeChild(child: GraphElement): void; - remove(): void; - setModel(model: E): void; - toModel(): ElementModel; - raise(): void; - getStyle(): T; - translateToAbsolute(t: Translatable): void; - translateFromAbsolute(t: Translatable): void; - translateToParent(t: Translatable): void; - translateFromParent(t: Translatable): void; -} - -export interface Node extends GraphElement { - getAnchor(end: AnchorEnd, type?: string): Anchor; - setAnchor(anchor: Anchor, end?: AnchorEnd, type?: string): void; - getNodes(): Node[]; - // TODO return an immutable bounds, position, dimensions? - getBounds(): Rect; - setBounds(bounds: Rect): void; - getPosition(): Point; - setPosition(location: Point): void; - getDimensions(): Dimensions; - setDimensions(dimensions: Dimensions): void; - isGroup(): boolean; - setGroup(group: boolean): void; - isCollapsed(): boolean; - setCollapsed(collapsed: boolean): void; - getLabelPosition(): LabelPosition; - setLabelPosition(position: LabelPosition): void; - getNodeShape(): NodeShape; - setNodeShape(shape: NodeShape): void; - getNodeStatus(): NodeStatus; - setNodeStatus(shape: NodeStatus): void; - getSourceEdges(): Edge[]; - getTargetEdges(): Edge[]; - getAllNodeChildren(): Node[]; // Return all children regardless of collapse status or child groups' collapsed status - isDimensionsInitialized(): boolean; - isPositioned(): boolean; -} - -export interface Edge extends GraphElement { - getSource(): Node; - setSource(source: Node): void; - getTarget(): Node; - getEdgeStyle(): EdgeStyle; - setEdgeStyle(edgeStyle: EdgeStyle): void; - getEdgeAnimationSpeed(): EdgeAnimationSpeed; - setEdgeAnimationSpeed(speed: EdgeAnimationSpeed): void; - setTarget(target: Node): void; - getSourceAnchorNode(): Node; - getTargetAnchorNode(): Node; - getStartPoint(): Point; - setStartPoint(x?: number, y?: number): void; - getEndPoint(): Point; - setEndPoint(x?: number, y?: number): void; - getBendpoints(): Point[]; - setBendpoints(points: Point[]): void; - removeBendpoint(point: Point | number): void; -} - -export interface Graph extends GraphElement { - getNodes(): Node[]; - getEdges(): Edge[]; - getBounds(): Rect; - setBounds(bounds: Rect): void; - getPosition(): Point; - setPosition(location: Point): void; - getDimensions(): Dimensions; - setDimensions(dimensions: Dimensions): void; - getScaleExtent(): ScaleExtent; - setScaleExtent(scaleExtent: ScaleExtent): void; - getScale(): number; - setScale(scale: number): void; - setDetailsLevelThresholds(settings: ScaleDetailsThresholds | undefined): void; - getDetailsLevelThresholds(): Readonly | undefined; - getDetailsLevel(): ScaleDetailsLevel; - getLayout(): string | undefined; - setLayout(type: string | undefined): void; - layout(): void; - getLayers(): string[]; - setLayers(layers: string[]): void; - - // viewport operations - reset(): void; - scaleBy(scale: number, location?: Point): void; - fit(padding?: number): void; - panIntoView(element: Node, options?: { offset?: number; minimumVisible?: number }): void; - isNodeInView(element: Node, options?: { padding: number }): boolean; -} - -export const isGraph = (element: GraphElement): element is Graph => element && element.getKind() === ModelKind.graph; - -export const isNode = (element: GraphElement): element is Node => element && element.getKind() === ModelKind.node; - -export const isEdge = (element: GraphElement): element is Edge => element && element.getKind() === ModelKind.edge; - -export type EventListener = (...args: Args) => void; - -export interface State { - [key: string]: any; -} - -export interface WithState { - getState(): S; - setState(state: State): void; -} - -export type LayoutFactory = (type: string, graph: Graph) => Layout | undefined; - -export type ComponentFactory = (kind: ModelKind, type: string) => ComponentType<{ element: GraphElement }> | undefined; - -export type ElementFactory = (kind: ModelKind, type: string) => GraphElement | undefined; - -export interface Controller extends WithState { - getStore(): S; - fromModel(model: Model, merge?: boolean): void; - toModel(): Model; - hasGraph(): boolean; - getGraph(): Graph; - setGraph(graph: Graph): void; - getLayout(type: string | undefined): Layout | undefined; - setFitToScreenOnLayout(fitToScreen: boolean, padding?: number): void; - getElementById(id: string): GraphElement | undefined; - getNodeById(id: string): Node | undefined; - getEdgeById(id: string): Edge | undefined; - addElement(element: GraphElement): void; - removeElement(element: GraphElement): void; - getComponent(kind: ModelKind, type: string): ComponentType<{ element: GraphElement }>; - registerLayoutFactory(factory: LayoutFactory): void; - registerComponentFactory(factory: ComponentFactory): void; - registerElementFactory(factory: ElementFactory): void; - addEventListener(type: string, listener: L): Controller; - removeEventListener(type: string, listener: EventListener): Controller; - fireEvent(type: string, ...args: any): void; - getElements(): GraphElement[]; - setRenderConstraint(constrained: boolean, viewPadding?: ViewPaddingSettings): void; - shouldRenderNode(node: Node): boolean; -} - -export interface ElementEvent { - target: GraphElement; -} -export type ElementVisibilityChangeEvent = ElementEvent & { visible: boolean }; - -export type ElementChildEventListener = EventListener<[ElementEvent & { child: GraphElement }]>; -export type ElementVisibilityChangeEventListener = EventListener<[ElementVisibilityChangeEvent]>; - -export type NodeCollapseChangeEventListener = EventListener<[{ node: Node }]>; - -export type GraphLayoutEndEventListener = EventListener<[{ graph: Graph }]>; - -export const ADD_CHILD_EVENT = 'element-add-child'; -export const ELEMENT_VISIBILITY_CHANGE_EVENT = 'element-visibility-change'; -export const REMOVE_CHILD_EVENT = 'element-remove-child'; -export const NODE_COLLAPSE_CHANGE_EVENT = 'node-collapse-change'; -export const NODE_POSITIONED_EVENT = 'node-positioned'; -export const GRAPH_LAYOUT_END_EVENT = 'graph-layout-end'; -export const GRAPH_POSITION_CHANGE_EVENT = 'graph-position-change'; diff --git a/packages/react-topology/src/utils/ControllerContext.ts b/packages/react-topology/src/utils/ControllerContext.ts deleted file mode 100644 index 388efb9d992..00000000000 --- a/packages/react-topology/src/utils/ControllerContext.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createContext } from 'react'; -import { Controller } from '../types'; - -const ControllerContext = createContext(undefined as any); - -export default ControllerContext; diff --git a/packages/react-topology/src/utils/ElementContext.ts b/packages/react-topology/src/utils/ElementContext.ts deleted file mode 100644 index 081569f8af7..00000000000 --- a/packages/react-topology/src/utils/ElementContext.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createContext } from 'react'; -import { GraphElement } from '../types'; - -const ElementContext = createContext(undefined as any); - -export default ElementContext; diff --git a/packages/react-topology/src/utils/Stateful.ts b/packages/react-topology/src/utils/Stateful.ts deleted file mode 100644 index fd85c85a830..00000000000 --- a/packages/react-topology/src/utils/Stateful.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { action, observable } from 'mobx'; -import { WithState, State } from '../types'; - -export default class Stateful implements WithState { - @observable.shallow - private state: State = {}; - - getState(): S { - return this.state as S; - } - - @action - setState(state: State): void { - if (state) { - Object.assign(this.state, state); - } - } -} diff --git a/packages/react-topology/src/utils/__tests__/svg-utils.spec.ts b/packages/react-topology/src/utils/__tests__/svg-utils.spec.ts deleted file mode 100644 index 223ec375be1..00000000000 --- a/packages/react-topology/src/utils/__tests__/svg-utils.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createSvgIdUrl } from '../svg-utils'; - -export const mockLocation = (location?: { - hash?: string; - port?: number; - pathname?: string; - search?: string; - origin?: string; -}) => { - const windowLocation = JSON.stringify(window.location); - delete window.location; - Object.defineProperty(window, 'location', { - configurable: true, - writable: true, - value: JSON.parse(windowLocation), - }); - if (location) { - Object.assign(window.location, location); - } -}; - -describe('svg-utils#createSvgIdUrl', () => { - it('should return absolute url based on pathname and search', () => { - mockLocation({ - pathname: '/foo/bar', - search: '?key=value', - }); - expect(createSvgIdUrl('testid')).toBe('url(/foo/bar?key=value#testid)'); - }); -}); diff --git a/packages/react-topology/src/utils/anchor-utils.ts b/packages/react-topology/src/utils/anchor-utils.ts deleted file mode 100644 index 9c22fd7ee38..00000000000 --- a/packages/react-topology/src/utils/anchor-utils.ts +++ /dev/null @@ -1,179 +0,0 @@ -import Point from '../geom/Point'; - -const getEllipseAnchorPoint = (center: Point, width: number, height: number, reference: Point): Point => { - const { x, y } = reference; - if (width === 0 || height === 0 || (center.x === x && center.y === y)) { - return center; - } - - const dispX = (center.x - x) / (width / 2); - const dispY = (center.y - y) / (height / 2); - - const len = Math.sqrt(dispX * dispX + dispY * dispY); - - const newLength = len - 1; - - const lenProportion = newLength / len; - - return new Point((center.x - x) * lenProportion + x, (center.y - y) * lenProportion + y); -}; - -const getRectAnchorPoint = (center: Point, width: number, height: number, reference: Point): Point => { - let dx = reference.x - center.x; - let dy = reference.y - center.y; - - if ((dx === 0 && dy === 0) || (width === 0 && height === 0)) { - return center; - } - - const scale = 0.5 / Math.max(width === 0 ? 0 : Math.abs(dx) / width, height === 0 ? 0 : Math.abs(dy) / height); - - dx *= scale; - dy *= scale; - - return center.clone().translate(dx, dy); -}; - -const svgPointToPoint = (p: SVGPoint): Point => new Point(p.x, p.y); - -export const distanceToPoint = (p: Point, reference: Point): number => { - const dx = p.x - reference.x; - const dy = p.y - reference.y; - - return dx * dx + dy * dy; -}; - -const isBetween = (a: number, b1: number, b2: number): boolean => - Math.ceil(a) >= Math.min(b1, b2) && Math.floor(a) <= Math.max(b1, b2); - -export const getLinesIntersection = (line1: [Point, Point], line2: [Point, Point]): Point | null => { - const line1xDelta = line1[0].x - line1[1].x; - const line1yDelta = line1[0].y - line1[1].y; - const line2xDelta = line2[0].x - line2[1].x; - const line2yDelta = line2[0].y - line2[1].y; - - const denominator = line1xDelta * line2yDelta - line1yDelta * line2xDelta; - if (denominator === 0) { - // parallel lines do not intersect - return null; - } - - const d1 = line1[0].x * line1[1].y - line1[0].y * line1[1].x; - const d2 = line2[0].x * line2[1].y - line2[0].y * line2[1].x; - const xValue = d1 * line2xDelta - line1xDelta * d2; - const yValue = d1 * line2yDelta - d2 * line1yDelta; - const intersection: Point = new Point(xValue / denominator, yValue / denominator); - - if ( - !isBetween(intersection.x, line1[0].x, line1[1].x) || - !isBetween(intersection.y, line1[0].y, line1[1].y) || - !isBetween(intersection.x, line2[0].x, line2[1].x) || - !isBetween(intersection.y, line2[0].y, line2[1].y) - ) { - // intersection is not in range - return null; - } - - return intersection; -}; - -const getPathIntersectionPoint = (pathNode: SVGPathElement, line: [Point, Point]): Point => { - const pathLength = pathNode.getTotalLength(); - const numSegments = Math.min(Math.round(pathLength / 5), 100); - for (let i = 0; i < numSegments; i++) { - const pos1 = pathNode.getPointAtLength((pathLength * i) / numSegments); - const pos2 = pathNode.getPointAtLength((pathLength * (i + 1)) / numSegments); - const intersectPoint = getLinesIntersection([svgPointToPoint(pos1), svgPointToPoint(pos2)], line); - if (intersectPoint) { - return intersectPoint; - } - } - - // No intersection found, return the center point - const pathBox = pathNode.getBBox(); - return new Point(pathBox.x + pathBox.width / 2, pathBox.y + pathBox.height / 2); -}; - -const getPathClosestPoint = (pathNode: SVGPathElement, reference: Point) => { - const pathLength = pathNode.getTotalLength(); - let precision = 8; - let best: SVGPoint = pathNode.getPointAtLength(0); - let bestLength = 0; - let bestDistance = Infinity; - - // linear scan for coarse approximation - for (let scanLength = 0; scanLength <= pathLength; scanLength += precision) { - const scan: SVGPoint = pathNode.getPointAtLength(scanLength); - const scanDistance: number = distanceToPoint(svgPointToPoint(scan), reference); - if (scanDistance < bestDistance) { - best = scan; - bestLength = scanLength; - bestDistance = scanDistance; - } - } - - // binary search for precise estimate - precision /= 2; - while (precision > 0.5) { - const beforeLength: number = bestLength - precision; - - const before: SVGPoint = pathNode.getPointAtLength(beforeLength); - const beforeDistance: number = distanceToPoint(svgPointToPoint(before), reference); - - if (beforeLength >= 0 && beforeDistance < bestDistance) { - best = before; - bestLength = beforeLength; - bestDistance = beforeDistance; - } else { - const afterLength: number = bestLength + precision; - const after: SVGPoint = pathNode.getPointAtLength(afterLength); - const afterDistance: number = distanceToPoint(svgPointToPoint(after), reference); - - if (afterLength <= pathLength && afterDistance < bestDistance) { - best = after; - bestLength = afterLength; - bestDistance = afterDistance; - } else { - precision /= 2; - } - } - } - - return svgPointToPoint(best); -}; - -const getPathAnchorPoint = (pathNode: SVGPathElement, reference: Point, useClosestPathPoint: boolean = false) => { - if (useClosestPathPoint) { - return getPathClosestPoint(pathNode, reference); - } - - const pathBox = pathNode.getBBox(); - const pathCenter = new Point(pathBox.x + pathBox.width / 2, pathBox.y + pathBox.height / 2); - return getPathIntersectionPoint(pathNode, [reference, pathCenter]); -}; - -const getPolygonAnchorPoint = (polygonNode: SVGPolygonElement, reference: Point) => { - const polygonBox = polygonNode.getBBox(); - const polygonCenter = new Point(polygonBox.x + polygonBox.width / 2, polygonBox.y + polygonBox.height / 2); - const { points } = polygonNode; - let bestPoint: Point = polygonCenter; - let bestDistance = Infinity; - - for (let i = 0; i < points.length; i++) { - const intersectPoint: Point | null = getLinesIntersection( - [svgPointToPoint(points[i]), svgPointToPoint(points[i === points.length - 1 ? 0 : i + 1])], - [polygonCenter, reference] - ); - if (intersectPoint) { - const intersectDistance: number = distanceToPoint(intersectPoint, reference); - if (intersectDistance < bestDistance) { - bestPoint = intersectPoint; - bestDistance = intersectDistance; - } - } - } - - return bestPoint; -}; - -export { getEllipseAnchorPoint, getRectAnchorPoint, getPathAnchorPoint, getPolygonAnchorPoint }; diff --git a/packages/react-topology/src/utils/createAggregateEdges.ts b/packages/react-topology/src/utils/createAggregateEdges.ts deleted file mode 100644 index 35e7155c395..00000000000 --- a/packages/react-topology/src/utils/createAggregateEdges.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as lodash from 'lodash'; -import { EdgeModel, NodeModel } from '../types'; - -const getNodeParent = (nodeId: string, nodes: NodeModel[]): NodeModel | undefined => - nodes.find(n => (n.children ? n.children.includes(nodeId) : null)); - -const getDisplayedNodeForNode = (nodeId: string | undefined, nodes: NodeModel[] | undefined): string => { - if (!nodeId || !nodes) { - return ''; - } - - let displayedNode = nodes && nodes.find(n => n.id === nodeId); - let parent = displayedNode ? getNodeParent(displayedNode.id, nodes) : null; - while (parent) { - if (parent.collapsed) { - displayedNode = parent; - } - parent = getNodeParent(parent.id, nodes); - } - return displayedNode ? displayedNode.id : ''; -}; - -const createAggregateEdges = ( - aggregateEdgeType: string, - edges: EdgeModel[] | undefined, - nodes: NodeModel[] | undefined -): EdgeModel[] => { - const aggregateEdges: EdgeModel[] = []; - - return lodash.reduce( - edges, - (newEdges: EdgeModel[], edge: EdgeModel) => { - const source = getDisplayedNodeForNode(edge.source, nodes); - const target = getDisplayedNodeForNode(edge.target, nodes); - - // Make sure visible is defined so that changes override what could already be in the element - edge.visible = 'visible' in edge ? edge.visible : true; - - if (source !== edge.source || target !== edge.target) { - if (source !== target) { - const existing = aggregateEdges.find( - e => (e.source === source || e.source === target) && (e.target === target || e.target === source) - ); - - if (existing) { - // At least one other edge, add this edge and add the aggregate edge to the edges - - // Add this edge to the aggregate and set it not visible - existing.children && existing.children.push(edge.id); - edge.visible = false; - - // Hide edges that are depicted by this aggregate edge - lodash.forEach(existing.children, existingChild => { - const updateEdge = newEdges.find(newEdge => newEdge.id === existingChild); - if (updateEdge) { - updateEdge.visible = false; - } - }); - - // Update the aggregate edges bidirectional flag - existing.data.bidirectional = existing.data.bidirectional || existing.source !== edge.source; - - // Check if this edge has already been added - if ( - !newEdges.find( - e => (e.source === source || e.source === target) && (e.target === target || e.target === source) - ) - ) { - newEdges.push(existing); - } - } else { - const newEdge: EdgeModel = { - data: { bidirectional: false }, - children: [edge.id], - source, - target, - id: `aggregate_${source}_${target}`, - type: aggregateEdgeType - }; - aggregateEdges.push(newEdge); - } - } else { - // Hide edges that connect to a non-visible node to its ancestor - edge.visible = false; - } - } - newEdges.push(edge); - return newEdges; - }, - [] as EdgeModel[] - ); -}; - -export { createAggregateEdges }; diff --git a/packages/react-topology/src/utils/element-utils.ts b/packages/react-topology/src/utils/element-utils.ts deleted file mode 100644 index 6248d182c21..00000000000 --- a/packages/react-topology/src/utils/element-utils.ts +++ /dev/null @@ -1,122 +0,0 @@ -import * as _ from 'lodash'; -import { GraphElement, Node, isNode, isGraph, NodeStyle } from '../types'; - -const groupNodeElements = (nodes: GraphElement[]): Node[] => { - if (!_.size(nodes)) { - return []; - } - const groupNodes: Node[] = []; - _.forEach(nodes, nextNode => { - if (isNode(nextNode) && nextNode.isGroup() && !nextNode.isCollapsed()) { - groupNodes.push(nextNode); - groupNodes.push(...groupNodeElements(nextNode.getChildren())); - } - }); - return groupNodes; -}; - -const leafNodeElements = (nodeElements: Node | Node[] | null): Node[] => { - const nodes: Node[] = []; - - if (!nodeElements) { - return nodes; - } - - if (Array.isArray(nodeElements)) { - _.forEach(nodeElements, (nodeElement: Node) => { - nodes.push(...leafNodeElements(nodeElement)); - }); - return nodes; - } - - if (nodeElements.isGroup() && !nodeElements.isCollapsed()) { - const leafNodes: Node[] = []; - const children: GraphElement[] = nodeElements.getChildren(); - if (_.size(children)) { - _.forEach( - children.filter(e => isNode(e)), - element => { - leafNodes.push(...leafNodeElements(element as Node)); - } - ); - } - return leafNodes; - } - - return [nodeElements]; -}; - -const getTopCollapsedParent = (node: Node): Node => { - let returnNode: Node = node; - try { - let parent = !isGraph(node) && node.getParent(); - while (parent && !isGraph(parent)) { - if ((parent as Node).isCollapsed()) { - returnNode = parent as Node; - } - parent = parent.getParent(); - } - // eslint-disable-next-line no-empty - } catch (e) {} - return returnNode; -}; - -const getClosestVisibleParent = (node: Node): Node | null => { - if (!node) { - return null; - } - - let returnNode = null; - try { - let parent = node.getParent(); - while (parent) { - if (!parent.isVisible()) { - // parent isn't visible so no descendant could be visible - returnNode = null; - } else if ((parent as Node).isCollapsed() || !returnNode) { - // parent is collapsed, no descendant is visible, but parent is - returnNode = parent as Node; - } - parent = parent.getParent(); - } - // eslint-disable-next-line no-empty - } catch (e) {} - return returnNode; -}; - -const getElementPadding = (element: GraphElement): number => { - const stylePadding = element.getStyle().padding; - if (!stylePadding) { - return 0; - } - - if (Array.isArray(stylePadding)) { - // For a padding that is not consistent on all sides, use the max padding - return stylePadding.reduce((val, current) => Math.max(val, current), 0); - } - - return stylePadding as number; -}; - -const getGroupPadding = (element: GraphElement, padding = 0): number => { - if (isGraph(element)) { - return padding; - } - let newPadding = padding; - if (isNode(element) && element.isGroup() && !element.isCollapsed()) { - newPadding += getElementPadding(element); - } - if (element.getParent()) { - return getGroupPadding(element.getParent(), newPadding); - } - return newPadding; -}; - -export { - groupNodeElements, - leafNodeElements, - getTopCollapsedParent, - getClosestVisibleParent, - getElementPadding, - getGroupPadding -}; diff --git a/packages/react-topology/src/utils/geom-utils.ts b/packages/react-topology/src/utils/geom-utils.ts deleted file mode 100644 index a79ee581886..00000000000 --- a/packages/react-topology/src/utils/geom-utils.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Padding } from '../geom/types'; - -export const maxPadding = (padding?: Padding): number => { - if (typeof padding === 'number') { - return +padding; - } - if (Array.isArray(padding)) { - return padding.reduce((max, p) => Math.max(max, p), 0); - } - return 0; -}; diff --git a/packages/react-topology/src/utils/getNodeScaleTranslation.ts b/packages/react-topology/src/utils/getNodeScaleTranslation.ts deleted file mode 100644 index 507bead3fc0..00000000000 --- a/packages/react-topology/src/utils/getNodeScaleTranslation.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Node } from '../types'; - -export const getNodeScaleTranslation = ( - element: Node, - nodeScale: number, - scaleNode: boolean -): { translateX: number; translateY: number } => { - if (!scaleNode) { - return { translateX: 0, translateY: 0 }; - } - const bounds = element.getBounds(); - const translateX = bounds.width / 2 - (bounds.width / 2) * nodeScale; - const translateY = bounds.height / 2 - (bounds.height / 2) * nodeScale; - - return { translateX, translateY }; -}; diff --git a/packages/react-topology/src/utils/index.ts b/packages/react-topology/src/utils/index.ts deleted file mode 100644 index 674d598be87..00000000000 --- a/packages/react-topology/src/utils/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export * from './anchor-utils'; -export { default as ControllerContext } from './ControllerContext'; -export { default as ElementContext } from './ElementContext'; -export * from './element-utils'; -export * from './geom-utils'; -export * from './svg-utils'; -export * from './style-utils'; -export * from './getNodeScaleTranslation'; -export { default as useCallbackRef } from './useCallbackRef'; -export { default as useCombineRefs } from './useCombineRefs'; -export { default as useHover } from './useHover'; -export * from './useSize'; -export * from './createAggregateEdges'; diff --git a/packages/react-topology/src/utils/style-utils.ts b/packages/react-topology/src/utils/style-utils.ts deleted file mode 100644 index 8b06103ca27..00000000000 --- a/packages/react-topology/src/utils/style-utils.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { EdgeAnimationSpeed, EdgeStyle, NodeStatus } from '../types'; -import styles from '@patternfly/react-styles/css/components/Topology/topology-components'; - -export const StatusModifier = { - [NodeStatus.default]: '', - [NodeStatus.info]: styles.modifiers.info, - [NodeStatus.success]: styles.modifiers.success, - [NodeStatus.warning]: styles.modifiers.warning, - [NodeStatus.danger]: styles.modifiers.danger -}; - -export const getEdgeStyleClassModifier = (edgeType: EdgeStyle): string => { - switch (edgeType) { - case EdgeStyle.solid: - return 'pf-m-solid'; - case EdgeStyle.dotted: - return 'pf-m-dotted'; - case EdgeStyle.dashed: - return 'pf-m-dashed'; - case EdgeStyle.dashedMd: - return 'pf-m-dashed-md'; - case EdgeStyle.dashedLg: - return 'pf-m-dashed-lg'; - case EdgeStyle.dashedXl: - return 'pf-m-dashed-xl'; - default: - return ''; - } -}; - -export const getEdgeAnimationDuration = (speed: EdgeAnimationSpeed): number => { - switch (speed) { - case EdgeAnimationSpeed.slow: - return 1.25; - case EdgeAnimationSpeed.mediumSlow: - return 1; - case EdgeAnimationSpeed.medium: - return 0.75; - case EdgeAnimationSpeed.mediumFast: - return 0.5; - case EdgeAnimationSpeed.fast: - return 0.25; - default: - return 0; - } -}; diff --git a/packages/react-topology/src/utils/svg-utils.ts b/packages/react-topology/src/utils/svg-utils.ts deleted file mode 100644 index 59026823e61..00000000000 --- a/packages/react-topology/src/utils/svg-utils.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { PointTuple } from '../types'; - -/** - * @param id - */ -export function createSvgIdUrl(id: string): string { - return `url(${`${window.location.pathname}${window.location.search}`}#${id})`; -} - -export type HullPaddingGetter = (point: PointTuple) => number; - -// Returns the vector 'v' scaled by 'scale'. -/** - * @param scale - * @param v - */ -export function vecScale(scale: number, v: PointTuple): PointTuple { - return [scale * v[0], scale * v[1]]; -} - -// Returns the sum of two vectors, or a combination of a point and a vector. -/** - * @param pv1 - * @param pv2 - */ -export function vecSum(pv1: PointTuple, pv2: PointTuple): PointTuple { - return [pv1[0] + pv2[0], pv1[1] + pv2[1]]; -} - -// Returns the unit normal to the line segment from p0 to p1. -/** - * @param p0 - * @param p1 - */ -export function unitNormal(p0: PointTuple, p1: PointTuple): PointTuple { - const n = [p0[1] - p1[1], p1[0] - p0[0]]; - const nLength = Math.sqrt(n[0] * n[0] + n[1] * n[1]); - return nLength > 0 ? [n[0] / nLength, n[1] / nLength] : [0, 0]; -} - -// Returns the path for a rounded hull around a single point (a circle). -/** - * @param polyPoints - * @param hp - */ -function roundedHull1(polyPoints: PointTuple[], hp: HullPaddingGetter): string { - const padding = hp(polyPoints[0]); - const p1 = [polyPoints[0][0], polyPoints[0][1] - padding]; - const p2 = [polyPoints[0][0], polyPoints[0][1] + padding]; - - return `M ${p1} A ${padding},${padding},0,0,0,${p2} A ${padding},${padding},0,0,0,${p1}`; -} - -// Returns the path for a rounded hull around two points (a "capsule" shape). -/** - * @param startPoint - * @param endPoint - * @param padding - */ -export function boundingBoxForLine( - startPoint: PointTuple, - endPoint: PointTuple, - padding: number | HullPaddingGetter = 0 -): [PointTuple, PointTuple, PointTuple, PointTuple] { - const hp = typeof padding === 'number' ? () => padding : padding; - const offsetVector1 = vecScale(hp(startPoint), unitNormal(startPoint, endPoint)); - const invOffsetVector1 = vecScale(-1, offsetVector1); - - const offsetVector2 = vecScale(hp(endPoint), unitNormal(startPoint, endPoint)); - const invOffsetVector2 = vecScale(-1, offsetVector2); - - const p0 = vecSum(startPoint, offsetVector1); - const p1 = vecSum(endPoint, offsetVector2); - const p2 = vecSum(endPoint, invOffsetVector2); - const p3 = vecSum(startPoint, invOffsetVector1); - - return [p0, p1, p2, p3]; -} - -// Returns the path for a rounded hull around two points (a "capsule" shape). -/** - * @param polyPoints - * @param hp - */ -function roundedHull2(polyPoints: PointTuple[], hp: HullPaddingGetter): string { - const points = boundingBoxForLine(polyPoints[0], polyPoints[1], hp); - - return `M ${points[0]} L ${points[1]} A ${hp(polyPoints[1])},${hp(polyPoints[1])},0,0,0,${points[2]} ${' '} - L ${points[3]} A ${hp(polyPoints[0])},${hp(polyPoints[0])},0,0,0,${points[0]}`; -} - -export const pointTuplesToPath = (segments: PointTuple[]): string => { - const pathSegments = segments.map( - (segment, index) => `${index === 0 ? 'M' : 'L'} ${segments[index][0]} ${segments[index][1]}` - ); - pathSegments.push(`L ${segments[0][0]} ${segments[0][1]}`); - return pathSegments.join(' '); -}; - -// Returns the SVG path data string representing the polygon, expanded and rounded. -/** - * @param polyPoints - * @param hullPadding - */ -export function hullPath(polyPoints: PointTuple[], hullPadding: number | HullPaddingGetter = 0): string { - const hp = typeof hullPadding === 'number' ? () => hullPadding : hullPadding; - - // Handle special cases - if (!polyPoints || polyPoints.length < 1) { - return ''; - } - if (polyPoints.length === 1) { - return roundedHull1(polyPoints, hp); - } - if (polyPoints.length === 2) { - return roundedHull2(polyPoints, hp); - } - - const segments: PointTuple[][] = new Array(polyPoints.length); - - // Calculate each offset (outwards) segment of the convex hull. - for (let segmentIndex = 0; segmentIndex < segments.length; ++segmentIndex) { - const p0 = segmentIndex === 0 ? polyPoints[polyPoints.length - 1] : polyPoints[segmentIndex - 1]; - const p1 = polyPoints[segmentIndex]; - - // Compute the offset vector for the line segment, with length = hullPadding. - // const offset = vecScale(hullPadding, unitNormal(p0, p1)); - segments[segmentIndex] = [ - vecSum(p0, vecScale(hp(p0), unitNormal(p0, p1))), - vecSum(p1, vecScale(hp(p1), unitNormal(p0, p1))) - ]; - } - - return segments - .map((segment, index) => { - const p0 = index === 0 ? polyPoints[polyPoints.length - 1] : polyPoints[index - 1]; - return `${index === 0 ? `M ${segments[segments.length - 1][1]} ` : ''}A ${hp(p0)},${hp(p0)},0,0,0,${ - segment[0] - } L ${segment[1]}`; - }) - .join(' '); -} diff --git a/packages/react-topology/src/utils/truncate-middle.ts b/packages/react-topology/src/utils/truncate-middle.ts deleted file mode 100644 index c6dd33addb5..00000000000 --- a/packages/react-topology/src/utils/truncate-middle.ts +++ /dev/null @@ -1,49 +0,0 @@ -export interface TruncateOptions { - length?: number; // Length to truncate text to - truncateEnd?: boolean; // Flag to alternatively truncate at the end - omission?: string; // Truncation text used to denote the truncation (ellipsis) - minTruncateChars?: number; // Minimum number of characters to truncate -} - -const DEFAULT_OPTIONS: TruncateOptions = { - length: 20, - truncateEnd: false, - omission: '\u2026', // ellipsis character - minTruncateChars: 3 -}; - -// Truncates a string down to `maxLength` characters when the length -// is greater than the `maxLength` + `minTruncateChars` values. -// By default the middle is truncated, set the options.truncateEnd to true to truncate at the end. -// Truncated text is replaced with the provided omission option (ellipsis character by default); -export const truncateMiddle = (text: string, options: TruncateOptions = {}): string => { - const { length, truncateEnd, omission, minTruncateChars } = { ...DEFAULT_OPTIONS, ...options }; - if (!text) { - return text; - } - - // Do not truncate less than the minimum truncate characters - if (text.length <= length + minTruncateChars) { - return text; - } - - if (length <= omission.length) { - return omission; - } - - if (truncateEnd) { - return `${text.substr(0, length - 1)}${omission}`; - } - - const startLength = Math.ceil((length - omission.length) / 2); - const endLength = length - startLength - omission.length; - const startFragment = text.substr(0, startLength); - const endFragment = text.substr(text.length - endLength); - return `${startFragment}${omission}${endFragment}`; -}; - -export const shouldTruncate = (text: string, options: TruncateOptions = {}): boolean => { - const { length, minTruncateChars } = { ...DEFAULT_OPTIONS, ...options }; - - return text.length > length + minTruncateChars; -}; diff --git a/packages/react-topology/src/utils/useCallbackRef.ts b/packages/react-topology/src/utils/useCallbackRef.ts deleted file mode 100644 index 99b7f898cdc..00000000000 --- a/packages/react-topology/src/utils/useCallbackRef.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useRef, useCallback } from 'react'; - -/** - * @param rawCallback - */ -export default function useCallbackRef any>(rawCallback: T) { - const cleanupRef = useRef<(() => any) | null>(null); - const callback = useCallback( - (node => { - if (cleanupRef.current) { - cleanupRef.current(); - cleanupRef.current = null; - } - if (node) { - cleanupRef.current = rawCallback(node); - } - }) as T, - [rawCallback] - ); - - return callback; -} diff --git a/packages/react-topology/src/utils/useCombineRefs.tsx b/packages/react-topology/src/utils/useCombineRefs.tsx deleted file mode 100644 index aa283cea280..00000000000 --- a/packages/react-topology/src/utils/useCombineRefs.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; - -const useCombineRefs = (...refs: (React.Ref | undefined)[]) => - React.useCallback( - (element: RefType | null): void => - refs.forEach(ref => { - if (ref) { - if (typeof ref === 'function') { - ref(element); - } else { - (ref as React.MutableRefObject).current = element; - } - } - }), - // eslint-disable-next-line react-hooks/exhaustive-deps - refs - ); -export default useCombineRefs; diff --git a/packages/react-topology/src/utils/useHover.ts b/packages/react-topology/src/utils/useHover.ts deleted file mode 100644 index 315485dd478..00000000000 --- a/packages/react-topology/src/utils/useHover.ts +++ /dev/null @@ -1,80 +0,0 @@ -import * as React from 'react'; -import useCallbackRef from './useCallbackRef'; - -const useHover = ( - delayIn: number = 200, - delayOut: number = 200 -): [boolean, (node: T) => (() => void) | undefined] => { - const [hover, setHover] = React.useState(false); - const mountRef = React.useRef(true); - - // need to ensure we do not start the unset timer on unmount - React.useEffect( - () => () => { - mountRef.current = false; - }, - [] - ); - - // The unset handle needs to be referred by listeners in different closures. - const unsetHandle = React.useRef(); - - const callbackRef = useCallbackRef( - React.useCallback( - (node: T) => { - if (node) { - // store locally instead of a ref because it only needs to be referred by inner closures - let delayHandle: any; - - const delayedStateChange = (newState: boolean, delay: number) => { - clearTimeout(unsetHandle.current); - clearTimeout(delayHandle); - - if (delay != null) { - delayHandle = window.setTimeout(() => { - clearTimeout(unsetHandle.current); - setHover(newState); - }, delay); - } else { - setHover(newState); - } - }; - - const onMouseEnter = () => { - delayedStateChange(true, delayIn); - }; - - const onMouseLeave = () => { - delayedStateChange(false, delayOut); - }; - - node.addEventListener('mouseenter', onMouseEnter); - node.addEventListener('mouseleave', onMouseLeave); - - return () => { - node.removeEventListener('mouseenter', onMouseEnter); - node.removeEventListener('mouseleave', onMouseLeave); - clearTimeout(delayHandle); - if (mountRef.current) { - // Queue the unset in case reattaching to a new node in the same location. - // This can happen with layers. Rendering a node to a new layer will unmount the old node - // and remount a new node at the same location. This will prevent flickering and getting - // stuck in a hover state. - unsetHandle.current = window.setTimeout(() => { - if (mountRef.current) { - setHover(false); - } - }, Math.max(delayIn, delayOut)); - } - }; - } - return undefined; - }, - [delayIn, delayOut] - ) - ); - - return [hover, callbackRef]; -}; - -export default useHover; diff --git a/packages/react-topology/src/utils/useSize.ts b/packages/react-topology/src/utils/useSize.ts deleted file mode 100644 index d92eed330cc..00000000000 --- a/packages/react-topology/src/utils/useSize.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from 'react'; - -interface Size { - width: number; - height: number; -} - -const EMPTY: any[] = []; - -export const useSize = (dependencies: any[] = EMPTY): [Size | undefined, (node: SVGGraphicsElement) => void] => { - const [size, setSize] = React.useState(); - const sizeRef = React.useRef(); - sizeRef.current = size; - - const callbackRef = React.useCallback((node: SVGGraphicsElement): void => { - if (node != null) { - const bb = node.getBBox(); - if (!sizeRef.current || sizeRef.current.width !== bb.width || sizeRef.current.height !== bb.height) { - setSize({ width: bb.width, height: bb.height }); - } - } - // dynamic dependencies - // eslint-disable-next-line react-hooks/exhaustive-deps - }, dependencies); - return [size, callbackRef]; -}; diff --git a/packages/react-topology/tsconfig.cjs.json b/packages/react-topology/tsconfig.cjs.json deleted file mode 100644 index 578d46af9d3..00000000000 --- a/packages/react-topology/tsconfig.cjs.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./dist/js", - "module": "commonjs", - "tsBuildInfoFile": "dist/cjs.tsbuildinfo" - } -} diff --git a/packages/react-topology/tsconfig.json b/packages/react-topology/tsconfig.json deleted file mode 100644 index 2b936822461..00000000000 --- a/packages/react-topology/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "compilerOptions": { - "rootDir": "./src", - "outDir": "./dist/esm", - "tsBuildInfoFile": "dist/esm.tsbuildinfo", - "experimentalDecorators": true, - "suppressImplicitAnyIndexErrors": true, - "noImplicitReturns": true, - }, - "include": [ - "./src/*", - "./src/**/*" - ], - "references": [ - { - "path": "../react-core" - } - ] -} diff --git a/packages/tsconfig.cjs.json b/packages/tsconfig.cjs.json index 2f14f82c1d1..fce5536ebec 100644 --- a/packages/tsconfig.cjs.json +++ b/packages/tsconfig.cjs.json @@ -22,9 +22,6 @@ { "path": "./react-table/tsconfig.cjs.json" }, - { - "path": "./react-topology/tsconfig.cjs.json" - }, { "path": "./react-virtualized-extension/tsconfig.cjs.json" }, diff --git a/packages/tsconfig.json b/packages/tsconfig.json index 634f308252e..29797c5ca39 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -22,9 +22,6 @@ { "path": "./react-table" }, - { - "path": "./react-topology" - }, { "path": "./react-virtualized-extension" } diff --git a/yarn.lock b/yarn.lock index 0428daed500..aab66343ff5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2097,12 +2097,6 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.2.0": - version "7.9.2" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz" - dependencies: - regenerator-runtime "^0.13.4" - "@babel/runtime@^7.4.5", "@babel/runtime@^7.8.7": version "7.11.2" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz" @@ -3869,103 +3863,20 @@ dependencies: "@types/node" "*" -"@types/d3-array@*": - version "2.0.0" - resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-2.0.0.tgz" - -"@types/d3-array@^1": - version "1.2.7" - resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-1.2.7.tgz" - "@types/d3-array@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac" integrity sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ== -"@types/d3-axis@*": - version "1.0.12" - resolved "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-1.0.12.tgz" - dependencies: - "@types/d3-selection" "*" - -"@types/d3-brush@*": - version "1.1.1" - resolved "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-1.1.1.tgz" - dependencies: - "@types/d3-selection" "*" - -"@types/d3-chord@*": - version "1.0.9" - resolved "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-1.0.9.tgz" - -"@types/d3-collection@*": - version "1.0.8" - resolved "https://registry.npmjs.org/@types/d3-collection/-/d3-collection-1.0.8.tgz" - "@types/d3-color@*": version "1.2.2" resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.2.2.tgz" -"@types/d3-contour@*": - version "1.3.0" - resolved "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-1.3.0.tgz" - dependencies: - "@types/d3-array" "*" - "@types/geojson" "*" - -"@types/d3-dispatch@*": - version "1.0.8" - resolved "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-1.0.8.tgz" - -"@types/d3-drag@*": - version "1.2.3" - resolved "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-1.2.3.tgz" - dependencies: - "@types/d3-selection" "*" - -"@types/d3-dsv@*": - version "1.0.36" - resolved "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-1.0.36.tgz" - -"@types/d3-ease@*": - version "1.0.9" - resolved "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-1.0.9.tgz" - "@types/d3-ease@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.0.tgz#c29926f8b596f9dadaeca062a32a45365681eae0" integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA== -"@types/d3-fetch@*": - version "1.1.5" - resolved "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-1.1.5.tgz" - dependencies: - "@types/d3-dsv" "*" - -"@types/d3-force@*", "@types/d3-force@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@types/d3-force/-/d3-force-1.2.1.tgz" - -"@types/d3-format@*": - version "1.3.1" - resolved "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.3.1.tgz" - -"@types/d3-geo@*": - version "1.11.1" - resolved "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-1.11.1.tgz" - dependencies: - "@types/geojson" "*" - -"@types/d3-hierarchy@*": - version "1.1.6" - resolved "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-1.1.6.tgz" - -"@types/d3-interpolate@*": - version "1.3.1" - resolved "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-1.3.1.tgz" - dependencies: - "@types/d3-color" "*" - "@types/d3-interpolate@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc" @@ -3977,28 +3888,6 @@ version "1.0.8" resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.8.tgz" -"@types/d3-polygon@*": - version "1.0.7" - resolved "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-1.0.7.tgz" - -"@types/d3-quadtree@*": - version "1.0.7" - resolved "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-1.0.7.tgz" - -"@types/d3-random@*": - version "1.1.2" - resolved "https://registry.npmjs.org/@types/d3-random/-/d3-random-1.1.2.tgz" - -"@types/d3-scale-chromatic@*": - version "1.5.0" - resolved "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz" - -"@types/d3-scale@*": - version "2.2.0" - resolved "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-2.2.0.tgz" - dependencies: - "@types/d3-time" "*" - "@types/d3-scale@^4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69" @@ -4006,16 +3895,6 @@ dependencies: "@types/d3-time" "*" -"@types/d3-selection@*": - version "1.4.2" - resolved "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-1.4.2.tgz" - -"@types/d3-shape@*": - version "1.3.2" - resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.2.tgz" - dependencies: - "@types/d3-path" "*" - "@types/d3-shape@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.0.tgz#1d87a6ddcf28285ef1e5c278ca4bdbc0658f3505" @@ -4023,10 +3902,6 @@ dependencies: "@types/d3-path" "*" -"@types/d3-time-format@*": - version "2.1.1" - resolved "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-2.1.1.tgz" - "@types/d3-time@*": version "1.0.10" resolved "https://registry.npmjs.org/@types/d3-time/-/d3-time-1.0.10.tgz" @@ -4036,72 +3911,11 @@ resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819" integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg== -"@types/d3-timer@*": - version "1.0.9" - resolved "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.9.tgz" - "@types/d3-timer@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.0.tgz#e2505f1c21ec08bda8915238e397fb71d2fc54ce" integrity sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g== -"@types/d3-transition@*": - version "1.1.6" - resolved "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-1.1.6.tgz" - dependencies: - "@types/d3-selection" "*" - -"@types/d3-voronoi@*": - version "1.1.9" - resolved "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.9.tgz" - -"@types/d3-zoom@*": - version "1.7.4" - resolved "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-1.7.4.tgz" - dependencies: - "@types/d3-interpolate" "*" - "@types/d3-selection" "*" - -"@types/d3@^5.7.2": - version "5.7.2" - resolved "https://registry.npmjs.org/@types/d3/-/d3-5.7.2.tgz" - dependencies: - "@types/d3-array" "^1" - "@types/d3-axis" "*" - "@types/d3-brush" "*" - "@types/d3-chord" "*" - "@types/d3-collection" "*" - "@types/d3-color" "*" - "@types/d3-contour" "*" - "@types/d3-dispatch" "*" - "@types/d3-drag" "*" - "@types/d3-dsv" "*" - "@types/d3-ease" "*" - "@types/d3-fetch" "*" - "@types/d3-force" "*" - "@types/d3-format" "*" - "@types/d3-geo" "*" - "@types/d3-hierarchy" "*" - "@types/d3-interpolate" "*" - "@types/d3-path" "*" - "@types/d3-polygon" "*" - "@types/d3-quadtree" "*" - "@types/d3-random" "*" - "@types/d3-scale" "*" - "@types/d3-scale-chromatic" "*" - "@types/d3-selection" "*" - "@types/d3-shape" "*" - "@types/d3-time" "*" - "@types/d3-time-format" "*" - "@types/d3-timer" "*" - "@types/d3-transition" "*" - "@types/d3-voronoi" "*" - "@types/d3-zoom" "*" - -"@types/dagre@0.7.42": - version "0.7.42" - resolved "https://registry.npmjs.org/@types/dagre/-/dagre-0.7.42.tgz" - "@types/dom-helpers@^3.4.1": version "3.4.1" resolved "https://registry.npmjs.org/@types/dom-helpers/-/dom-helpers-3.4.1.tgz" @@ -4167,10 +3981,6 @@ version "1.1.2" resolved "https://registry.npmjs.org/@types/fined/-/fined-1.1.2.tgz" -"@types/geojson@*": - version "7946.0.7" - resolved "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz" - "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz" @@ -4344,12 +4154,6 @@ dependencies: "@types/react" "*" -"@types/react-measure@^2.0.6": - version "2.0.6" - resolved "https://registry.npmjs.org/@types/react-measure/-/react-measure-2.0.6.tgz" - dependencies: - "@types/react" "*" - "@types/react-router-dom@^5.3.3": version "5.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" @@ -4472,12 +4276,6 @@ version "2.0.3" resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz" -"@types/webcola@3.2.0": - version "3.2.0" - resolved "https://registry.npmjs.org/@types/webcola/-/webcola-3.2.0.tgz" - dependencies: - webcola "*" - "@types/webpack-sources@*": version "1.4.2" resolved "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-1.4.2.tgz" @@ -6806,14 +6604,14 @@ command-line-usage@^5.0.5: table-layout "^0.4.3" typical "^2.6.1" -commander@2, commander@^2.11.0, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: - version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" - commander@4.1.1, commander@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" +commander@^2.11.0, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + commander@^5.1.0: version "5.1.0" resolved "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" @@ -7452,10 +7250,6 @@ cypress@^8.0.0: url "^0.11.0" yauzl "^2.10.0" -d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0: - version "1.2.4" - resolved "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz" - "d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: version "3.2.0" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.0.tgz#15bf96cd9b7333e02eb8de8053d78962eafcff14" @@ -7463,114 +7257,21 @@ d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0: dependencies: internmap "1 - 2" -d3-axis@1: - version "1.0.12" - resolved "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz" - -d3-brush@1: - version "1.1.6" - resolved "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz" - dependencies: - d3-dispatch "1" - d3-drag "1" - d3-interpolate "1" - d3-selection "1" - d3-transition "1" - -d3-chord@1: - version "1.0.6" - resolved "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz" - dependencies: - d3-array "1" - d3-path "1" - -d3-collection@1: - version "1.0.7" - resolved "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz" - -d3-color@1: - version "1.4.1" - resolved "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz" - "d3-color@1 - 3": version "3.1.0" resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== -d3-contour@1: - version "1.3.2" - resolved "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz" - dependencies: - d3-array "^1.1.1" - -d3-dispatch@1, d3-dispatch@^1.0.3: - version "1.0.6" - resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz" - -d3-drag@1, d3-drag@^1.0.4: - version "1.2.5" - resolved "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz" - dependencies: - d3-dispatch "1" - d3-selection "1" - -d3-dsv@1: - version "1.2.0" - resolved "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz" - dependencies: - commander "2" - iconv-lite "0.4" - rw "1" - -d3-ease@1: - version "1.0.7" - resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz" - d3-ease@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== -d3-fetch@1: - version "1.2.0" - resolved "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz" - dependencies: - d3-dsv "1" - -d3-force@1: - version "1.2.1" - resolved "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz" - dependencies: - d3-collection "1" - d3-dispatch "1" - d3-quadtree "1" - d3-timer "1" - -d3-format@1: - version "1.4.5" - resolved "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz" - "d3-format@1 - 3": version "3.1.0" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== -d3-geo@1: - version "1.12.1" - resolved "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz" - dependencies: - d3-array "1" - -d3-hierarchy@1: - version "1.1.9" - resolved "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz" - -d3-interpolate@1: - version "1.4.0" - resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz" - dependencies: - d3-color "1" - "d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" @@ -7578,45 +7279,11 @@ d3-interpolate@1: dependencies: d3-color "1 - 3" -d3-path@1: - version "1.0.9" - resolved "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz" - "d3-path@1 - 3": version "3.0.1" resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e" integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w== -d3-polygon@1: - version "1.0.6" - resolved "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz" - -d3-quadtree@1: - version "1.0.7" - resolved "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz" - -d3-random@1: - version "1.1.2" - resolved "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz" - -d3-scale-chromatic@1: - version "1.5.0" - resolved "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz" - dependencies: - d3-color "1" - d3-interpolate "1" - -d3-scale@2: - version "2.2.2" - resolved "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz" - dependencies: - d3-array "^1.2.0" - d3-collection "1" - d3-format "1" - d3-interpolate "1" - d3-time "1" - d3-time-format "2" - d3-scale@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" @@ -7628,16 +7295,6 @@ d3-scale@^4.0.2: d3-time "2.1.1 - 3" d3-time-format "2 - 4" -d3-selection@1, d3-selection@^1.1.0: - version "1.4.2" - resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz" - -d3-shape@1, d3-shape@^1.3.5: - version "1.3.7" - resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz" - dependencies: - d3-path "1" - d3-shape@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556" @@ -7645,12 +7302,6 @@ d3-shape@^3.1.0: dependencies: d3-path "1 - 3" -d3-time-format@2: - version "2.3.0" - resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz" - dependencies: - d3-time "1" - "d3-time-format@2 - 4": version "4.1.0" resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" @@ -7658,10 +7309,6 @@ d3-time-format@2: dependencies: d3-time "1 - 3" -d3-time@1: - version "1.1.0" - resolved "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz" - "d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975" @@ -7669,84 +7316,11 @@ d3-time@1: dependencies: d3-array "2 - 3" -d3-timer@1, d3-timer@^1.0.5: - version "1.0.10" - resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz" - d3-timer@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== -d3-transition@1: - version "1.3.2" - resolved "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz" - dependencies: - d3-color "1" - d3-dispatch "1" - d3-ease "1" - d3-interpolate "1" - d3-selection "^1.1.0" - d3-timer "1" - -d3-voronoi@1: - version "1.1.4" - resolved "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz" - -d3-zoom@1: - version "1.8.3" - resolved "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz" - dependencies: - d3-dispatch "1" - d3-drag "1" - d3-interpolate "1" - d3-selection "1" - d3-transition "1" - -d3@^5.16.0: - version "5.16.0" - resolved "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz" - dependencies: - d3-array "1" - d3-axis "1" - d3-brush "1" - d3-chord "1" - d3-collection "1" - d3-color "1" - d3-contour "1" - d3-dispatch "1" - d3-drag "1" - d3-dsv "1" - d3-ease "1" - d3-fetch "1" - d3-force "1" - d3-format "1" - d3-geo "1" - d3-hierarchy "1" - d3-interpolate "1" - d3-path "1" - d3-polygon "1" - d3-quadtree "1" - d3-random "1" - d3-scale "2" - d3-scale-chromatic "1" - d3-selection "1" - d3-shape "1" - d3-time "1" - d3-time-format "2" - d3-timer "1" - d3-transition "1" - d3-voronoi "1" - d3-zoom "1" - -dagre@0.8.2: - version "0.8.2" - resolved "https://registry.npmjs.org/dagre/-/dagre-0.8.2.tgz#755b79f4d5499d63cf74c3368fb08add93eceafe" - integrity sha512-TEOOGZOkCOgCG7AoUIq64sJ3d21SMv8tyoqteLpX+UsUsS9Qw8iap4hhogXY4oB3r0bbZuAjO0atAilgCmsE0Q== - dependencies: - graphlib "^2.1.5" - lodash "^4.17.4" - damerau-levenshtein@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz" @@ -9802,10 +9376,6 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.3" -get-node-dimensions@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz" - get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" @@ -10167,13 +9737,6 @@ graceful-fs@^4.2.6, graceful-fs@^4.2.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graphlib@^2.1.5: - version "2.1.8" - resolved "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" - integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== - dependencies: - lodash "^4.17.15" - gud@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz" @@ -10671,7 +10234,7 @@ husky@^4.3.0: slash "^3.0.0" which-pm-runs "^1.0.0" -iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" dependencies: @@ -12597,7 +12160,7 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5, lodash@^4.2.1: version "4.17.20" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" @@ -13345,20 +12908,6 @@ mkdirp@*, mkdirp@^1.0.3, mkdirp@^1.0.4: dependencies: minimist "^1.2.5" -mobx-react-lite@>=2.2.0: - version "2.2.1" - resolved "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-2.2.1.tgz" - -mobx-react@^6.2.0: - version "6.3.0" - resolved "https://registry.npmjs.org/mobx-react/-/mobx-react-6.3.0.tgz" - dependencies: - mobx-react-lite ">=2.2.0" - -mobx@^5.15.4: - version "5.15.6" - resolved "https://registry.npmjs.org/mobx/-/mobx-5.15.6.tgz" - modify-values@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz" @@ -14660,11 +14209,7 @@ pn@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz" -point-in-svg-path@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/point-in-svg-path/-/point-in-svg-path-1.0.1.tgz" - -popper.js@^1.16.0, popper.js@^1.16.1: +popper.js@^1.16.0: version "1.16.1" resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz" @@ -15247,15 +14792,6 @@ react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" -react-measure@^2.3.0: - version "2.5.0" - resolved "https://registry.npmjs.org/react-measure/-/react-measure-2.5.0.tgz" - dependencies: - "@babel/runtime" "^7.2.0" - get-node-dimensions "^1.2.1" - prop-types "^15.6.2" - resize-observer-polyfill "^1.5.0" - react-monaco-editor@0.48.0: version "0.48.0" resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.48.0.tgz#f2b547c619f0ba3b49d3c8a0e0168ff9d0aa70dc" @@ -15881,10 +15417,6 @@ requires-port@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" -resize-observer-polyfill@^1.5.0: - version "1.5.1" - resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz" - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz" @@ -16075,10 +15607,6 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rw@1: - version "1.3.3" - resolved "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz" - rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.6.0, rxjs@^6.6.2: version "6.6.3" resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz" @@ -18642,15 +18170,6 @@ web-namespaces@^1.0.0: version "1.1.3" resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.3.tgz" -webcola@*, webcola@3.4.0: - version "3.4.0" - resolved "https://registry.npmjs.org/webcola/-/webcola-3.4.0.tgz" - dependencies: - d3-dispatch "^1.0.3" - d3-drag "^1.0.4" - d3-shape "^1.3.5" - d3-timer "^1.0.5" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"