Repository: maxGraph/maxGraph
Pull request #513 (2024-08-18 13:59:29)

docs: integrate mxGraph manual content into documentation
Integrate most of the content into 3 new pages.
Warn readers that content still needs to be updated to match maxGraph implementation.

Create a new “known issues” page and reference mxGraph issues.
Update the existing “intro” page to better integrate it with the new manual.

### Notes

Covers #345



Patch:
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index d361ad350..313e62df5 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -18,6 +18,7 @@ limitations under the License.
 import './view/mixins/_graph-mixins-types';
 
 export { Graph } from './view/Graph';
+export * from './view/plugins';
 
 export { GraphDataModel } from './view/GraphDataModel';
 export { GraphView } from './view/GraphView';
diff --git a/packages/core/src/view/Graph.ts b/packages/core/src/view/Graph.ts
index ed8c9d283..e06860b08 100644
--- a/packages/core/src/view/Graph.ts
+++ b/packages/core/src/view/Graph.ts
@@ -21,16 +21,10 @@ import EventObject from './event/EventObject';
 import EventSource from './event/EventSource';
 import InternalEvent from './event/InternalEvent';
 import Rectangle from './geometry/Rectangle';
-import TooltipHandler from './handler/TooltipHandler';
 import Client from '../Client';
-import SelectionCellsHandler from './handler/SelectionCellsHandler';
-import ConnectionHandler from './handler/ConnectionHandler';
-import SelectionHandler from './handler/SelectionHandler';
-import PanningHandler from './handler/PanningHandler';
-import PopupMenuHandler from './handler/PopupMenuHandler';
+import type PanningHandler from './handler/PanningHandler';
 import GraphView from './GraphView';
 import CellRenderer from './cell/CellRenderer';
-import CellEditorHandler from './handler/CellEditorHandler';
 import Point from './geometry/Point';
 import { getCurrentStyle, hasScrollbars, parseCssNumber } from '../util/styleUtils';
 import Cell from './cell/Cell';
@@ -65,16 +59,7 @@ import { registerDefaultShapes } from './cell/register-shapes';
 import { registerDefaultEdgeMarkers } from './geometry/edge/MarkerShape';
 import { registerDefaultStyleElements } from './style/register';
 import { applyGraphMixins } from './mixins/_graph-mixins-apply';
-
-export const defaultPlugins: GraphPluginConstructor[] = [
-  CellEditorHandler,
-  TooltipHandler,
-  SelectionCellsHandler,
-  PopupMenuHandler,
-  ConnectionHandler,
-  SelectionHandler,
-  PanningHandler,
-];
+import { getDefaultPlugins } from './plugins';
 
 /**
  * Extends {@link EventSource} to implement a graph component for the browser. This is the main class of the package.
@@ -500,7 +485,7 @@ class Graph extends EventSource {
   constructor(
     container: HTMLElement,
     model?: GraphDataModel,
-    plugins: GraphPluginConstructor[] = defaultPlugins,
+    plugins: GraphPluginConstructor[] = getDefaultPlugins(),
     stylesheet: Stylesheet | null = null
   ) {
     super();
@@ -528,9 +513,7 @@ class Graph extends EventSource {
     this.setSelectionModel(this.createSelectionModel());
 
     // Initializes plugins
-    plugins.forEach((p: GraphPluginConstructor) => {
-      this.plugins[p.pluginId] = new p(this);
-    });
+    plugins.forEach((p) => (this.plugins[p.pluginId] = new p(this)));
 
     this.view.revalidate();
   }
diff --git a/packages/core/src/view/GraphView.ts b/packages/core/src/view/GraphView.ts
index 0cd0a3a98..f5958a51b 100644
--- a/packages/core/src/view/GraphView.ts
+++ b/packages/core/src/view/GraphView.ts
@@ -43,7 +43,7 @@ import { getClientX, getClientY, getSource, isConsumed } from '../util/EventUtil
 import { clone } from '../util/cloneUtils';
 import type { Graph } from './Graph';
 import StyleRegistry from './style/StyleRegistry';
-import TooltipHandler from './handler/TooltipHandler';
+import type TooltipHandler from './handler/TooltipHandler';
 import type { EdgeStyleFunction, MouseEventListener } from '../types';
 
 /**
@@ -2167,7 +2167,7 @@ export class GraphView extends EventSource {
     });
 
     this.moveHandler = (evt: MouseEvent) => {
-      const tooltipHandler = graph.getPlugin('TooltipHandler') as TooltipHandler;
+      const tooltipHandler = graph.getPlugin<TooltipHandler>('TooltipHandler');
 
       // Hides the tooltip if mouse is outside container
       if (tooltipHandler && tooltipHandler.isHideOnHover()) {
diff --git a/packages/core/src/view/handler/CellEditorHandler.ts b/packages/core/src/view/handler/CellEditorHandler.ts
index 2e35908e0..86bdf2a34 100644
--- a/packages/core/src/view/handler/CellEditorHandler.ts
+++ b/packages/core/src/view/handler/CellEditorHandler.ts
@@ -153,11 +153,7 @@ import TooltipHandler from './TooltipHandler';
  * };
  * ```
  *
- * Constructor: mxCellEditor
- *
- * Constructs a new in-place editor for the specified graph.
- *
- * @param graph Reference to the enclosing {@link Graph}.
+ * @category Plugin
  */
 class CellEditorHandler implements GraphPlugin {
   static pluginId = 'CellEditorHandler';
diff --git a/packages/core/src/view/handler/ConnectionHandler.ts b/packages/core/src/view/handler/ConnectionHandler.ts
index d5f392817..05528b103 100644
--- a/packages/core/src/view/handler/ConnectionHandler.ts
+++ b/packages/core/src/view/handler/ConnectionHandler.ts
@@ -203,19 +203,7 @@ type FactoryMethod = (
  *
  * Fires when the <reset> method is invoked.
  *
- * Constructor: mxConnectionHandler
- *
- * Constructs an event handler that connects vertices using the specified
- * factory method to create the new edges. Modify
- * {@link Constants#ACTIVE_REGION} to setup the region on a cell which triggers
- * the creation of a new connection or use connect icons as explained
- * above.
- *
- * @param graph Reference to the enclosing {@link Graph}.
- * @param factoryMethod Optional function to create the edge. The function takes
- * the source and target <Cell> as the first and second argument and an
- * optional cell style from the preview as the third argument. It returns
- * the <Cell> that represents the new edge.
+ * @category Plugin
  */
 class ConnectionHandler extends EventSource implements GraphPlugin {
   static pluginId = 'ConnectionHandler';
@@ -394,6 +382,16 @@ class ConnectionHandler extends EventSource implements GraphPlugin {
 
   escapeHandler: () => void;
 
+  /**
+   * Constructs an event handler that connects vertices using the specified
+   * factory method to create the new edges.
+   *
+   * @param graph Reference to the enclosing {@link Graph}.
+   * @param factoryMethod Optional function to create the edge. The function takes
+   * the source and target {@link Cell} as the first and second argument and an
+   * optional cell style from the preview as the third argument. It returns
+   * the {@link Cell} that represents the new edge.
+   */
   constructor(graph: Graph, factoryMethod: FactoryMethod | null = null) {
     super();
 
diff --git a/packages/core/src/view/handler/PanningHandler.ts b/packages/core/src/view/handler/PanningHandler.ts
index dd90ff512..1f2eae3b7 100644
--- a/packages/core/src/view/handler/PanningHandler.ts
+++ b/packages/core/src/view/handler/PanningHandler.ts
@@ -36,15 +36,11 @@ import type { Graph } from '../Graph';
 
 /**
  * Event handler that pans and creates popupmenus. To use the left
- * mousebutton for panning without interfering with cell moving and
+ * mouse button for panning without interfering with cell moving and
  * resizing, use <isUseLeftButton> and <isIgnoreCell>. For grid size
- * steps while panning, use <useGrid>. This handler is built-into
- * {@link Graph#panningHandler} and enabled using {@link Graph#setPanning}.
+ * steps while panning, use <useGrid>.
  *
- * Constructor: mxPanningHandler
- *
- * Constructs an event handler that creates a {@link PopupMenu}
- * and pans the graph.
+ * When registered in the {@link Graph.constructor} plugins list, it can be enabled using {@link Graph.setPanning}.
  *
  * Event: mxEvent.PAN_START
  *
@@ -60,6 +56,8 @@ import type { Graph } from '../Graph';
  *
  * Fires when the panning handler changes its <active> state to false. The
  * <code>event</code> property contains the corresponding {@link MouseEvent}.
+ *
+ * @category Plugin
  */
 class PanningHandler extends EventSource implements GraphPlugin {
   static pluginId = 'PanningHandler';
diff --git a/packages/core/src/view/handler/PopupMenuHandler.ts b/packages/core/src/view/handler/PopupMenuHandler.ts
index ae7d5aff2..cd51f3df3 100644
--- a/packages/core/src/view/handler/PopupMenuHandler.ts
+++ b/packages/core/src/view/handler/PopupMenuHandler.ts
@@ -30,9 +30,9 @@ import EventObject from '../event/EventObject';
 /**
  * Event handler that creates popupmenus.
  *
- * Constructor: mxPopupMenuHandler
+ * Relates to {@link MaxPopupMenu}.
  *
- * Constructs an event handler that creates a {@link PopupMenu}.
+ * @category Plugin
  */
 class PopupMenuHandler extends MaxPopupMenu implements GraphPlugin {
   static pluginId = 'PopupMenuHandler';
diff --git a/packages/core/src/view/handler/RubberBandHandler.ts b/packages/core/src/view/handler/RubberBandHandler.ts
index bf7c5dcaf..5bd1948e1 100644
--- a/packages/core/src/view/handler/RubberBandHandler.ts
+++ b/packages/core/src/view/handler/RubberBandHandler.ts
@@ -37,8 +37,25 @@ import EventSource from '../event/EventSource';
 
 /**
  * Event handler that selects rectangular regions.
- * This is not built-into [mxGraph].
+ *
+ * **IMPORTANT**: This is not built-into `maxGraph` i.e. this plugin is not in the `maxGraph` default plugins, see {@link getDefaultPlugins}.
+ *
  * To enable rubberband selection in a graph, use the following code.
+ *
+ * ```javascript
+ * const plugins = [
+ *   ...getDefaultPlugins(), // or any other plugins you want
+ *   RubberBandHandler,
+ * ];
+ *
+ * // Creates the graph with the custom plugins
+ * const graph = new Graph(container, undefined, plugins);
+ * ```
+ *
+ * **IMPORTANT**: the RubberBandHandler requires CSS styles in order to work properly.
+ * See the CSS rules in the `css/common.css` file provided within the npm package. They relate to the `.mxRubberband` class.
+ *
+ * @category Plugin
  */
 class RubberBandHandler implements GraphPlugin {
   static pluginId = 'RubberBandHandler';
diff --git a/packages/core/src/view/handler/SelectionCellsHandler.ts b/packages/core/src/view/handler/SelectionCellsHandler.ts
index 7be7733e0..fffc2f146 100644
--- a/packages/core/src/view/handler/SelectionCellsHandler.ts
+++ b/packages/core/src/view/handler/SelectionCellsHandler.ts
@@ -45,7 +45,7 @@ import InternalMouseEvent from '../event/InternalMouseEvent';
  * Fires if a cell has been remove from the selection. The <code>state</code>
  * property contains the <CellState> that has been removed.
  *
- * @param graph Reference to the enclosing {@link Graph}.
+ * @category Plugin
  */
 class SelectionCellsHandler extends EventSource implements GraphPlugin {
   static pluginId = 'SelectionCellsHandler';
diff --git a/packages/core/src/view/handler/SelectionHandler.ts b/packages/core/src/view/handler/SelectionHandler.ts
index 3b27bd544..6271e7370 100644
--- a/packages/core/src/view/handler/SelectionHandler.ts
+++ b/packages/core/src/view/handler/SelectionHandler.ts
@@ -63,13 +63,16 @@ import type { ColorValue, GraphPlugin } from '../../types';
  *
  * To avoid the container to scroll a moved cell into view, set {@link scrollOnMove} to `false`.
  *
- * Constructs an event handler that creates handles for the selection cells.
- *
- * @param graph Reference to the enclosing {@link Graph}.
+ * @category Plugin
  */
 class SelectionHandler implements GraphPlugin {
   static pluginId = 'SelectionHandler';
 
+  /**
+   * Constructs an event handler that creates handles for the selection cells.
+   *
+   * @param graph Reference to the enclosing {@link Graph}.
+   */
   constructor(graph: Graph) {
     this.graph = graph;
     this.graph.addMouseListener(this);
diff --git a/packages/core/src/view/handler/TooltipHandler.ts b/packages/core/src/view/handler/TooltipHandler.ts
index ceffb398c..47ec21923 100644
--- a/packages/core/src/view/handler/TooltipHandler.ts
+++ b/packages/core/src/view/handler/TooltipHandler.ts
@@ -35,6 +35,8 @@ import EventSource from '../event/EventSource';
  * {@link Graph#getTooltip} is used to get the tooltip for a cell or handle.
  *
  * This handler is generally enabled using {@link Graph#setTooltips}.
+ *
+ * @category Plugin
  */
 class TooltipHandler implements GraphPlugin {
   static pluginId = 'TooltipHandler';
diff --git a/packages/core/src/view/mixins/ConnectionsMixin.ts b/packages/core/src/view/mixins/ConnectionsMixin.ts
index ff68b232c..e04f061fe 100644
--- a/packages/core/src/view/mixins/ConnectionsMixin.ts
+++ b/packages/core/src/view/mixins/ConnectionsMixin.ts
@@ -23,7 +23,7 @@ import EventObject from '../event/EventObject';
 import InternalEvent from '../event/InternalEvent';
 import Dictionary from '../../util/Dictionary';
 import type { Graph } from '../Graph';
-import ConnectionHandler from '../handler/ConnectionHandler';
+import type ConnectionHandler from '../handler/ConnectionHandler';
 
 type PartialGraph = Pick<Graph, 'getView' | 'getDataModel' | 'isPortsEnabled'>;
 type PartialConnections = Pick<
@@ -511,12 +511,12 @@ export const ConnectionsMixin: PartialType = {
   },
 
   setConnectable(connectable) {
-    const connectionHandler = this.getPlugin('ConnectionHandler') as ConnectionHandler;
+    const connectionHandler = this.getPlugin<ConnectionHandler>('ConnectionHandler');
     connectionHandler?.setEnabled(connectable);
   },
 
   isConnectable() {
-    const connectionHandler = this.getPlugin('ConnectionHandler') as ConnectionHandler;
+    const connectionHandler = this.getPlugin<ConnectionHandler>('ConnectionHandler');
     return connectionHandler?.isEnabled() ?? false;
   },
 };
diff --git a/packages/core/src/view/mixins/EditingMixin.ts b/packages/core/src/view/mixins/EditingMixin.ts
index 4cbb6f869..aa2b4c6d8 100644
--- a/packages/core/src/view/mixins/EditingMixin.ts
+++ b/packages/core/src/view/mixins/EditingMixin.ts
@@ -74,9 +74,7 @@ export const EditingMixin: PartialType = {
           new EventObject(InternalEvent.START_EDITING, { cell, event: evt })
         );
 
-        const cellEditorHandler = this.getPlugin(
-          'CellEditorHandler'
-        ) as CellEditorHandler;
+        const cellEditorHandler = this.getPlugin<CellEditorHandler>('CellEditorHandler');
         cellEditorHandler?.startEditing(cell, evt);
 
         this.fireEvent(
@@ -91,7 +89,7 @@ export const EditingMixin: PartialType = {
   },
 
   stopEditing(cancel = false) {
-    const cellEditorHandler = this.getPlugin('CellEditorHandler') as CellEditorHandler;
+    const cellEditorHandler = this.getPlugin<CellEditorHandler>('CellEditorHandler');
     cellEditorHandler?.stopEditing(cancel);
     this.fireEvent(new EventObject(InternalEvent.EDITING_STOPPED, { cancel }));
   },
@@ -127,7 +125,7 @@ export const EditingMixin: PartialType = {
    *****************************************************************************/
 
   isEditing(cell = null) {
-    const cellEditorHandler = this.getPlugin('CellEditorHandler') as CellEditorHandler;
+    const cellEditorHandler = this.getPlugin<CellEditorHandler>('CellEditorHandler');
     const editingCell = cellEditorHandler?.getEditingCell();
     return !cell ? !!editingCell : cell === editingCell;
   },
diff --git a/packages/core/src/view/mixins/EventsMixin.ts b/packages/core/src/view/mixins/EventsMixin.ts
index 265912248..a38f1246e 100644
--- a/packages/core/src/view/mixins/EventsMixin.ts
+++ b/packages/core/src/view/mixins/EventsMixin.ts
@@ -34,15 +34,15 @@ import {
 } from '../../util/EventUtils';
 import CellState from '../cell/CellState';
 import Cell from '../cell/Cell';
-import PanningHandler from '../handler/PanningHandler';
-import ConnectionHandler from '../handler/ConnectionHandler';
+import type PanningHandler from '../handler/PanningHandler';
+import type ConnectionHandler from '../handler/ConnectionHandler';
 import Point from '../geometry/Point';
 import { convertPoint } from '../../util/styleUtils';
 import { NONE } from '../../util/Constants';
 import Client from '../../Client';
-import CellEditorHandler from '../handler/CellEditorHandler';
+import type CellEditorHandler from '../handler/CellEditorHandler';
 import type { Graph } from '../Graph';
-import TooltipHandler from '../handler/TooltipHandler';
+import type TooltipHandler from '../handler/TooltipHandler';
 
 type PartialGraph = Pick<
   Graph,
@@ -338,8 +338,8 @@ export const EventsMixin: PartialType = {
       cell: me.getCell(),
     });
 
-    const panningHandler = this.getPlugin('PanningHandler') as PanningHandler;
-    const connectionHandler = this.getPlugin('ConnectionHandler') as ConnectionHandler;
+    const panningHandler = this.getPlugin<PanningHandler>('PanningHandler');
+    const connectionHandler = this.getPlugin<ConnectionHandler>('ConnectionHandler');
 
     // LATER: Check if event should be consumed if me is consumed
     this.fireEvent(mxe);
@@ -576,7 +576,7 @@ export const EventsMixin: PartialType = {
     sender = sender ?? (this as Graph);
 
     if (this.isEventSourceIgnored(evtName, me)) {
-      const tooltipHandler = this.getPlugin('TooltipHandler') as TooltipHandler;
+      const tooltipHandler = this.getPlugin<TooltipHandler>('TooltipHandler');
       if (tooltipHandler) {
         tooltipHandler.hide();
       }
@@ -758,7 +758,7 @@ export const EventsMixin: PartialType = {
           Math.abs(this.initialTouchY - me.getGraphY()) < this.tolerance;
       }
 
-      const cellEditorHandler = this.getPlugin('CellEditorHandler') as CellEditorHandler;
+      const cellEditorHandler = this.getPlugin<CellEditorHandler>('CellEditorHandler');
 
       // Stops editing for all events other than from cellEditorHandler
       if (
diff --git a/packages/core/src/view/mixins/PanningMixin.ts b/packages/core/src/view/mixins/PanningMixin.ts
index e3859eb36..1e0683a14 100644
--- a/packages/core/src/view/mixins/PanningMixin.ts
+++ b/packages/core/src/view/mixins/PanningMixin.ts
@@ -17,11 +17,11 @@ limitations under the License.
 import { hasScrollbars } from '../../util/styleUtils';
 import EventObject from '../event/EventObject';
 import InternalEvent from '../event/InternalEvent';
-import PanningHandler from '../handler/PanningHandler';
+import type PanningHandler from '../handler/PanningHandler';
 import { Graph } from '../Graph';
 import Rectangle from '../geometry/Rectangle';
 import Point from '../geometry/Point';
-import SelectionCellsHandler from '../handler/SelectionCellsHandler';
+import type SelectionCellsHandler from '../handler/SelectionCellsHandler';
 
 type PartialGraph = Pick<Graph, 'getContainer' | 'getView' | 'getPlugin' | 'fireEvent'>;
 type PartialPanning = Pick<
@@ -292,9 +292,9 @@ export const PanningMixin: PartialType = {
       if (isChanged) {
         this.getView().refresh();
 
-        const selectionCellsHandler = this.getPlugin(
+        const selectionCellsHandler = this.getPlugin<SelectionCellsHandler>(
           'SelectionCellsHandler'
-        ) as SelectionCellsHandler;
+        );
 
         // Repaints selection marker (ticket 18)
         if (selectionCellsHandler) {
@@ -307,7 +307,7 @@ export const PanningMixin: PartialType = {
   },
 
   setPanning(enabled) {
-    const panningHandler = this.getPlugin('PanningHandler') as PanningHandler;
+    const panningHandler = this.getPlugin<PanningHandler>('PanningHandler');
     panningHandler && (panningHandler.panningEnabled = enabled);
   },
 };
diff --git a/packages/core/src/view/mixins/PanningMixin.type.ts b/packages/core/src/view/mixins/PanningMixin.type.ts
index 4b1472d9e..f16a28c64 100644
--- a/packages/core/src/view/mixins/PanningMixin.type.ts
+++ b/packages/core/src/view/mixins/PanningMixin.type.ts
@@ -109,6 +109,8 @@ declare module '../Graph' {
     /**
      * Specifies if panning should be enabled. This implementation updates {@link PanningHandler.panningEnabled}.
      *
+     **IMPORTANT**: only has an effect if the {@link PanningHandler} plugin is available.
+     *
      * @param enabled Boolean indicating if panning should be enabled.
      */
     setPanning: (enabled: boolean) => void;
diff --git a/packages/core/src/view/mixins/TooltipMixin.ts b/packages/core/src/view/mixins/TooltipMixin.ts
index 49296a2d3..744cb358e 100644
--- a/packages/core/src/view/mixins/TooltipMixin.ts
+++ b/packages/core/src/view/mixins/TooltipMixin.ts
@@ -53,9 +53,9 @@ export const TooltipMixin: PartialType = {
     }
 
     if (!tip) {
-      const selectionCellsHandler = this.getPlugin(
+      const selectionCellsHandler = this.getPlugin<SelectionCellsHandler>(
         'SelectionCellsHandler'
-      ) as SelectionCellsHandler;
+      );
 
       const handler = selectionCellsHandler?.getHandler(state.cell);
 
@@ -89,7 +89,7 @@ export const TooltipMixin: PartialType = {
   },
 
   setTooltips(enabled: boolean) {
-    const tooltipHandler = this.getPlugin('TooltipHandler') as TooltipHandler;
+    const tooltipHandler = this.getPlugin<TooltipHandler>('TooltipHandler');
     tooltipHandler?.setEnabled(enabled);
   },
 };
diff --git a/packages/core/src/view/mixins/TooltipMixin.type.ts b/packages/core/src/view/mixins/TooltipMixin.type.ts
index 2f4f4e6bd..bd655a557 100644
--- a/packages/core/src/view/mixins/TooltipMixin.type.ts
+++ b/packages/core/src/view/mixins/TooltipMixin.type.ts
@@ -57,7 +57,7 @@ declare module '../Graph' {
      *
      * Replaces all tooltips with the string Hello, World!
      *
-     * @param cell {@link mxCell} whose tooltip should be returned.
+     * @param cell {@link Cell} whose tooltip should be returned.
      */
     getTooltipForCell: (cell: Cell) => HTMLElement | string;
 
@@ -66,6 +66,8 @@ declare module '../Graph' {
      *
      * This implementation updates {@link TooltipHandler.enabled}.
      *
+     * **IMPORTANT**: only has an effect if the {@link TooltipHandler} plugin is available.
+     *
      * @param enabled Boolean indicating if tooltips should be enabled.
      */
     setTooltips: (enabled: boolean) => void;
diff --git a/packages/core/src/view/other/Outline.ts b/packages/core/src/view/other/Outline.ts
index 739f8bd22..be72f393a 100644
--- a/packages/core/src/view/other/Outline.ts
+++ b/packages/core/src/view/other/Outline.ts
@@ -27,7 +27,7 @@ import {
 import Point from '../geometry/Point';
 import Rectangle from '../geometry/Rectangle';
 import RectangleShape from '../geometry/node/RectangleShape';
-import { Graph, defaultPlugins } from '../Graph';
+import { Graph } from '../Graph';
 import ImageShape from '../geometry/node/ImageShape';
 import InternalEvent from '../event/InternalEvent';
 import Image from '../image/ImageBox';
@@ -36,6 +36,7 @@ import { getSource, isMouseEvent } from '../../util/EventUtils';
 import EventSource from '../event/EventSource';
 import { hasScrollbars } from '../../util/styleUtils';
 import { Listenable } from '../../types';
+import { getDefaultPlugins } from '../plugins';
 
 /**
  * @class Outline
@@ -322,7 +323,10 @@ class Outline {
     const graph = new Graph(
       container,
       this.source.getDataModel(),
-      defaultPlugins,
+      // TODO review the list of plugins for the Graph of an Outline
+      // we could pass an empty array or a selection of plugins
+      // it may be necessary to make the plugins array configurable to allow custom plugins and improve tree-shaking
+      getDefaultPlugins(),
       this.source.getStylesheet()
     );
     graph.options.foldingEnabled = false;
diff --git a/packages/core/src/view/plugins/index.ts b/packages/core/src/view/plugins/index.ts
new file mode 100644
index 000000000..3ab8935fa
--- /dev/null
+++ b/packages/core/src/view/plugins/index.ts
@@ -0,0 +1,41 @@
+/*
+Copyright 2024-present The maxGraph project Contributors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import type { GraphPluginConstructor } from '../../types';
+import CellEditorHandler from '../handler/CellEditorHandler';
+import TooltipHandler from '../handler/TooltipHandler';
+import SelectionCellsHandler from '../handler/SelectionCellsHandler';
+import PopupMenuHandler from '../handler/PopupMenuHandler';
+import ConnectionHandler from '../handler/ConnectionHandler';
+import SelectionHandler from '../handler/SelectionHandler';
+import PanningHandler from '../handler/PanningHandler';
+
+/**
+ * Returns the list of plugins used by default in `maxGraph`.
+ *
+ * The function returns a new array each time it is called.
+ *
+ * @category Plugin
+ */
+export const getDefaultPlugins = (): GraphPluginConstructor[] => [
+  CellEditorHandler,
+  TooltipHandler,
+  SelectionCellsHandler,
+  PopupMenuHandler,
+  ConnectionHandler,
+  SelectionHandler,
+  PanningHandler,
+];
diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json
index 0d76c5d03..ee22cdcf5 100644
--- a/packages/core/tsconfig.json
+++ b/packages/core/tsconfig.json
@@ -24,6 +24,7 @@
       "Vertex Shapes",
       "Layout",
       "Perimeter",
+      "Plugin",
       "Serialization with Codecs",
       "*"
     ],
diff --git a/packages/html/stories/Anchors.stories.ts b/packages/html/stories/Anchors.stories.ts
index ff89352ab..31f8547ba 100644
--- a/packages/html/stories/Anchors.stories.ts
+++ b/packages/html/stories/Anchors.stories.ts
@@ -22,6 +22,7 @@ import {
   ConnectionConstraint,
   Geometry,
   Graph,
+  type GraphPluginConstructor,
   InternalMouseEvent,
   Point,
   RubberBandHandler,
@@ -63,19 +64,19 @@ const Template = ({ label, ...args }: Record<string, string>) => {
     }
   }
 
+  // Use a dedicated set of plugins to use MyCustomConnectionHandler and to not use extra plugins not needed here
+  const plugins: GraphPluginConstructor[] = [
+    CellEditorHandler,
+    SelectionCellsHandler,
+    MyCustomConnectionHandler,
+    SelectionHandler,
+  ];
+  // Enables rubberband selection
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   class MyCustomGraph extends Graph {
     constructor(container: HTMLElement) {
-      super(
-        container,
-        undefined,
-        // Use a dedicated set of plugins to use MyCustomConnectionHandler and to not use extra plugins not needed here
-        [
-          CellEditorHandler,
-          SelectionCellsHandler,
-          MyCustomConnectionHandler,
-          SelectionHandler,
-        ]
-      );
+      super(container, undefined, plugins);
     }
     getAllConnectionConstraints = (terminal: CellState | null, _source: boolean) => {
       // Overridden to define per-geometry connection points
@@ -111,9 +112,6 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   // Specifies the default edge style
   graph.getStylesheet().getDefaultEdgeStyle().edgeStyle = 'orthogonalEdgeStyle';
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/ContextIcons.stories.ts b/packages/html/stories/ContextIcons.stories.ts
index 48fbd9de6..73eacd412 100644
--- a/packages/html/stories/ContextIcons.stories.ts
+++ b/packages/html/stories/ContextIcons.stories.ts
@@ -27,6 +27,8 @@ import {
   type CellState,
   type ConnectionHandler,
   type SelectionHandler,
+  getDefaultPlugins,
+  type GraphPluginConstructor,
 } from '@maxgraph/core';
 
 import {
@@ -180,6 +182,10 @@ const Template = ({ label, ...args }: Record<string, any>) => {
   }
 
   class MyCustomGraph extends Graph {
+    constructor(container: HTMLElement, plugins: GraphPluginConstructor[]) {
+      super(container, undefined, plugins);
+    }
+
     createHandler(state: CellState) {
       if (state != null && state.cell.isVertex()) {
         return new CustomVertexToolHandler(state);
@@ -188,8 +194,12 @@ const Template = ({ label, ...args }: Record<string, any>) => {
     }
   }
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   // Creates the graph inside the given container
-  const graph = new MyCustomGraph(container);
+  const graph = new MyCustomGraph(container, plugins);
   graph.setConnectable(true);
 
   const connectionHandler = graph.getPlugin<ConnectionHandler>('ConnectionHandler');
@@ -199,9 +209,6 @@ const Template = ({ label, ...args }: Record<string, any>) => {
   // to fit the size of the graph
   // graph.setResizeContainer(true);
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/DynamicToolbar.stories.ts b/packages/html/stories/DynamicToolbar.stories.ts
index 73d7d3112..1d611d9c0 100644
--- a/packages/html/stories/DynamicToolbar.stories.ts
+++ b/packages/html/stories/DynamicToolbar.stories.ts
@@ -16,21 +16,22 @@ limitations under the License.
 */
 
 import {
+  Cell,
+  cellArrayUtils,
   type CellStyle,
+  Client,
+  type ConnectionHandler,
+  Geometry,
+  gestureUtils,
+  getDefaultPlugins,
   Graph,
+  GraphDataModel,
   type HTMLImageElementWithProps,
-  RubberBandHandler,
-  type ConnectionHandler,
   ImageBox,
-  MaxToolbar,
-  GraphDataModel,
-  Cell,
-  Geometry,
   InternalEvent,
+  MaxToolbar,
+  RubberBandHandler,
   styleUtils,
-  gestureUtils,
-  Client,
-  cellArrayUtils,
 } from '@maxgraph/core';
 import {
   globalTypes,
@@ -77,10 +78,12 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   const container = createGraphContainer(args);
   div.appendChild(container);
 
-  // Creates the model and the graph inside the container
-  // using the fastest rendering available on the browser
-  const model = new GraphDataModel();
-  const graph = new Graph(container, model);
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
+  // Creates the model and the graph inside the container using the fastest rendering available on the browser
+  const graph = new Graph(container, new GraphDataModel(), plugins);
 
   // Defines an icon for creating new connections in the connection handler.
   // This will automatically disable the highlighting of the source vertex.
@@ -98,8 +101,6 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   // Stops editing on enter or escape keypress (TODO not working, do we want to keep this here?)
   // const keyHandler = new KeyHandler(graph);
 
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   addVertex('images/rectangle.gif', 100, 40, {});
   addVertex('images/rounded.gif', 100, 40, { rounded: true });
   addVertex('images/ellipse.gif', 40, 40, {
diff --git a/packages/html/stories/Handles.stories.ts b/packages/html/stories/Handles.stories.ts
index 8b874563f..fa1012977 100644
--- a/packages/html/stories/Handles.stories.ts
+++ b/packages/html/stories/Handles.stories.ts
@@ -31,6 +31,8 @@ import {
   type CellState,
   type CellStateStyle,
   VertexHandlerConfig,
+  getDefaultPlugins,
+  type GraphPluginConstructor,
 } from '@maxgraph/core';
 
 import {
@@ -234,6 +236,10 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   }
 
   class MyCustomGraph extends Graph {
+    constructor(container: HTMLElement, plugins: GraphPluginConstructor[]) {
+      super(container, undefined, plugins);
+    }
+
     createVertexHandler(state: CellState) {
       return new MyCustomVertexHandler(state);
     }
@@ -242,16 +248,17 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   // Disables the built-in context menu
   if (!args.contextMenu) InternalEvent.disableContextMenu(container);
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   // Creates the graph inside the given container
-  const graph = new MyCustomGraph(container);
+  const graph = new MyCustomGraph(container, plugins);
   graph.setCellsCloneable(true);
   graph.setHtmlLabels(true);
   graph.setPanning(true);
   graph.centerZoom = false;
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/HelloPort.stories.ts b/packages/html/stories/HelloPort.stories.ts
index e687e3c2c..4696966db 100644
--- a/packages/html/stories/HelloPort.stories.ts
+++ b/packages/html/stories/HelloPort.stories.ts
@@ -18,6 +18,7 @@ limitations under the License.
 import {
   DomHelpers,
   EdgeStyle,
+  getDefaultPlugins,
   Graph,
   ModelXmlSerializer,
   Point,
@@ -53,8 +54,12 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   const container = createGraphContainer(args);
   div.appendChild(container);
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   // Creates the graph inside the given container
-  const graph = new Graph(container);
+  const graph = new Graph(container, undefined, plugins);
   graph.setConnectable(true);
   graph.setTooltips(true);
 
@@ -88,9 +93,6 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   // Removes the folding icon and disables any folding
   graph.isCellFoldable = (_cell) => false;
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/HierarchicalLayout.stories.ts b/packages/html/stories/HierarchicalLayout.stories.ts
index 27ae34432..ab79e0b0f 100644
--- a/packages/html/stories/HierarchicalLayout.stories.ts
+++ b/packages/html/stories/HierarchicalLayout.stories.ts
@@ -18,6 +18,7 @@ limitations under the License.
 import {
   DomHelpers,
   FastOrganicLayout,
+  getDefaultPlugins,
   Graph,
   HierarchicalLayout,
   InternalEvent,
@@ -52,11 +53,12 @@ const Template = ({ label, ...args }: Record<string, any>) => {
 
   InternalEvent.disableContextMenu(container);
 
-  // Creates the graph inside the given container
-  const graph = new Graph(container);
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
 
-  // Adds rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
+  // Creates the graph inside the given container
+  const graph = new Graph(container, undefined, plugins);
 
   // Changes the default vertex style in-place
   let style = graph.getStylesheet().getDefaultVertexStyle();
diff --git a/packages/html/stories/JsonData.stories.ts b/packages/html/stories/JsonData.stories.ts
index 6aa2d0d93..ddd16a548 100644
--- a/packages/html/stories/JsonData.stories.ts
+++ b/packages/html/stories/JsonData.stories.ts
@@ -26,6 +26,7 @@ import {
   RubberBandHandler,
   ModelXmlSerializer,
   type Cell,
+  getDefaultPlugins,
 } from '@maxgraph/core';
 import {
   globalTypes,
@@ -79,11 +80,12 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   // Disables the built-in context menu
   if (!args.contextMenu) InternalEvent.disableContextMenu(container);
 
-  // Creates the graph inside the given container
-  const graph = new Graph(container);
-
   // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
+  // Creates the graph inside the given container
+  const graph = new Graph(container, undefined, plugins);
 
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
diff --git a/packages/html/stories/Merge.stories.ts b/packages/html/stories/Merge.stories.ts
index 285ce4487..04efe8026 100644
--- a/packages/html/stories/Merge.stories.ts
+++ b/packages/html/stories/Merge.stories.ts
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import { Graph, Perimeter, RubberBandHandler } from '@maxgraph/core';
+import { getDefaultPlugins, Graph, Perimeter, RubberBandHandler } from '@maxgraph/core';
 import {
   globalTypes,
   globalValues,
@@ -44,8 +44,12 @@ const Template = ({ label, ...args }: Record<string, any>) => {
   // Should we allow overriding constants?
   // constants.SHADOWCOLOR = '#c0c0c0';
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   // Creates the graph inside the given container
-  const graph = new Graph(container);
+  const graph = new Graph(container, undefined, plugins);
 
   // No size handles, please...
   graph.setCellsResizable(false);
@@ -67,9 +71,6 @@ const Template = ({ label, ...args }: Record<string, any>) => {
   style.fontColor = 'black';
   style.strokeWidth = 2;
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/PerimeterOnLabelBounds.stories.ts b/packages/html/stories/PerimeterOnLabelBounds.stories.ts
index deda7253d..6b73f991f 100644
--- a/packages/html/stories/PerimeterOnLabelBounds.stories.ts
+++ b/packages/html/stories/PerimeterOnLabelBounds.stories.ts
@@ -17,6 +17,7 @@ limitations under the License.
 
 import {
   type CellState,
+  getDefaultPlugins,
   Graph,
   GraphView,
   InternalEvent,
@@ -82,9 +83,13 @@ const Template = ({ label, ...args }: Record<string, any>) => {
     }
   }
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   class MyCustomGraph extends Graph {
     constructor(container: HTMLElement) {
-      super(container);
+      super(container, undefined, plugins);
     }
 
     createGraphView(): GraphView {
@@ -100,9 +105,6 @@ const Template = ({ label, ...args }: Record<string, any>) => {
   // Uncomment the following if you want the container to fit the size of the graph
   // graph.setResizeContainer(true);
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This is normally the first child of the root (i.e. layer 0).
   const parent = graph.getDefaultParent();
 
diff --git a/packages/html/stories/PerimeterVariousImplementations.stories.ts b/packages/html/stories/PerimeterVariousImplementations.stories.ts
index acd243507..0f733c625 100644
--- a/packages/html/stories/PerimeterVariousImplementations.stories.ts
+++ b/packages/html/stories/PerimeterVariousImplementations.stories.ts
@@ -16,6 +16,7 @@ limitations under the License.
 
 import {
   type CellStateStyle,
+  getDefaultPlugins,
   Graph,
   InternalEvent,
   RubberBandHandler,
@@ -54,11 +55,12 @@ const Template = ({ label, ...args }: Record<string, any>) => {
 
   InternalEvent.disableContextMenu(container);
 
-  // Creates the graph inside the given container
-  const graph: Graph = new Graph(container);
-
   // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
+  // Creates the graph inside the given container
+  const graph = new Graph(container, undefined, plugins);
 
   // Gets the default parent for inserting new cells. This is normally the first child of the root (i.e. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/RadialTreeLayout.stories.ts b/packages/html/stories/RadialTreeLayout.stories.ts
index 215a11c72..b5b924b30 100644
--- a/packages/html/stories/RadialTreeLayout.stories.ts
+++ b/packages/html/stories/RadialTreeLayout.stories.ts
@@ -15,7 +15,12 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import { Graph, RubberBandHandler, RadialTreeLayout } from '@maxgraph/core';
+import {
+  getDefaultPlugins,
+  Graph,
+  RubberBandHandler,
+  RadialTreeLayout,
+} from '@maxgraph/core';
 import {
   globalTypes,
   globalValues,
@@ -41,11 +46,12 @@ export default {
 const Template = ({ label, ...args }: Record<string, any>) => {
   const container = createGraphContainer(args);
 
-  // Creates the graph inside the given container
-  const graph = new Graph(container);
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
 
-  // Adds rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
+  // Creates the graph inside the given container
+  const graph = new Graph(container, undefined, plugins);
 
   // Changes the default vertex style in-place
   let style = graph.getStylesheet().getDefaultVertexStyle();
diff --git a/packages/html/stories/Stencils.stories.ts b/packages/html/stories/Stencils.stories.ts
index b8e5932bd..1ea9f8c39 100644
--- a/packages/html/stories/Stencils.stories.ts
+++ b/packages/html/stories/Stencils.stories.ts
@@ -24,6 +24,7 @@ import {
   constants,
   DomHelpers,
   EdgeHandler,
+  getDefaultPlugins,
   Graph,
   InternalEvent,
   load,
@@ -111,11 +112,15 @@ const Template = ({ label, ...args }: Record<string, string>) => {
       return shape;
     }
   }
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
 
   class CustomGraph extends Graph {
     constructor(container: HTMLElement) {
-      super(container);
+      super(container, undefined, plugins);
     }
+
     createVertexHandler(state: CellState) {
       return new CustomVertexHandler(state);
     }
@@ -194,9 +199,6 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   style.gradientColor = '#7d85df';
   style.shadow = true;
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   // Gets the default parent for inserting new cells. This
   // is normally the first child of the root (ie. layer 0).
   const parent = graph.getDefaultParent();
diff --git a/packages/html/stories/Toolbar.stories.ts b/packages/html/stories/Toolbar.stories.ts
index 1bfec5cd6..c122dfa93 100644
--- a/packages/html/stories/Toolbar.stories.ts
+++ b/packages/html/stories/Toolbar.stories.ts
@@ -31,6 +31,7 @@ import {
   Point,
   RubberBandHandler,
   cellArrayUtils,
+  getDefaultPlugins,
 } from '@maxgraph/core';
 import {
   globalTypes,
@@ -84,8 +85,13 @@ const Template = ({ label, ...args }: { [p: string]: any }) => {
   const container = createGraphContainer(args);
   toolbarAndGraphParentContainer.appendChild(container);
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
+  // Creates the graph inside the given container
   const model = new GraphDataModel();
-  const graph = new Graph(container, model);
+  const graph = new Graph(container, model, plugins);
   configureExpandedAndCollapsedImages(graph);
   graph.dropEnabled = true;
 
@@ -119,8 +125,6 @@ const Template = ({ label, ...args }: { [p: string]: any }) => {
   // Stops editing on enter or escape keypress (TODO not working, do we want to keep this here?)
   // const keyHandler = new KeyHandler(graph);
 
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   function addCell(
     isVertex: boolean,
     icon: string,
diff --git a/packages/html/stories/UserObject.stories.ts b/packages/html/stories/UserObject.stories.ts
index 6b0e9c750..e2d0dea58 100644
--- a/packages/html/stories/UserObject.stories.ts
+++ b/packages/html/stories/UserObject.stories.ts
@@ -31,6 +31,7 @@ import {
   ModelXmlSerializer,
   popup,
   type Cell,
+  getDefaultPlugins,
 } from '@maxgraph/core';
 import {
   globalTypes,
@@ -87,8 +88,12 @@ const Template = ({ label, ...args }: Record<string, string>) => {
   const relation = doc.createElement('Knows');
   relation.setAttribute('since', '1985');
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   // Creates the graph inside the given container
-  const graph = new Graph(container);
+  const graph = new Graph(container, undefined, plugins);
 
   // Optional disabling of sizing
   graph.setCellsResizable(false);
@@ -172,9 +177,6 @@ const Template = ({ label, ...args }: Record<string, string>) => {
     return getTooltipForCell.apply(this, [cell]);
   };
 
-  // Enables rubberband selection
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   const buttons = document.createElement('div');
   mainDiv.appendChild(buttons);
 
diff --git a/packages/html/stories/Window.stories.ts b/packages/html/stories/Window.stories.ts
index 05dae776e..196f0c73c 100644
--- a/packages/html/stories/Window.stories.ts
+++ b/packages/html/stories/Window.stories.ts
@@ -25,6 +25,7 @@ import {
   domUtils,
   GlobalConfig,
   MaxLogAsLogger,
+  getDefaultPlugins,
 } from '@maxgraph/core';
 import {
   contextMenuTypes,
@@ -71,15 +72,17 @@ const Template = ({ label, ...args }: Record<string, string>) => {
     true
   );
 
+  // Enables rubberband selection
+  const plugins = getDefaultPlugins();
+  if (args.rubberBand) plugins.push(RubberBandHandler);
+
   // Creates the graph inside the given container
-  const graph = new Graph(container);
+  const graph = new Graph(container, undefined, plugins);
 
   // Adds rubberband selection and keystrokes
   graph.setTooltips(true);
   graph.setPanning(true);
 
-  if (args.rubberBand) new RubberBandHandler(graph);
-
   new KeyHandler(graph);
 
   if (!args.contextMenu) InternalEvent.disableContextMenu(container);
diff --git a/packages/js-example/src/index.js b/packages/js-example/src/index.js
index f7a6dabd3..9a85d621c 100644
--- a/packages/js-example/src/index.js
+++ b/packages/js-example/src/index.js
@@ -19,6 +19,7 @@ import './style.css';
 import {
   Client,
   DomHelpers,
+  getDefaultPlugins,
   Graph,
   InternalEvent,
   ModelXmlSerializer,
@@ -59,9 +60,11 @@ const initializeGraph = (container) => {
   // Disables the built-in context menu
   InternalEvent.disableContextMenu(container);
 
-  const graph = new Graph(container);
+  const graph = new Graph(container, undefined, [
+    ...getDefaultPlugins(),
+    RubberBandHandler, // Enables rubber band selection
+  ]);
   graph.setPanning(true); // Use mouse right button for panning
-  new RubberBandHandler(graph); // Enables rubber band selection
 
   const modelXmlSerializer = new ModelXmlSerializer(graph.model);
   modelXmlSerializer.import(xmlWithVerticesAndEdges);
diff --git a/packages/ts-example/src/main.ts b/packages/ts-example/src/main.ts
index dec7898a2..295cfcdac 100644
--- a/packages/ts-example/src/main.ts
+++ b/packages/ts-example/src/main.ts
@@ -19,6 +19,7 @@ import './style.css';
 import {
   Client,
   constants,
+  getDefaultPlugins,
   Graph,
   InternalEvent,
   Perimeter,
@@ -30,9 +31,11 @@ const initializeGraph = (container: HTMLElement) => {
   // Disables the built-in context menu
   InternalEvent.disableContextMenu(container);
 
-  const graph = new Graph(container);
+  const graph = new Graph(container, undefined, [
+    ...getDefaultPlugins(),
+    RubberBandHandler, // Enables rubber band selection
+  ]);
   graph.setPanning(true); // Use mouse right button for panning
-  new RubberBandHandler(graph); // Enables rubber band selection
 
   // shapes and styles
   registerCustomShapes();
diff --git a/packages/website/docs/intro.md b/packages/website/docs/intro.md
index 0a256b5e4..49b53a71a 100644
--- a/packages/website/docs/intro.md
+++ b/packages/website/docs/intro.md
@@ -39,13 +39,15 @@ To visualize the documentation for a specific version (and the corresponding dem
 :::
 
 
-## Getting Started
+## Quick Start
 
 Please check the maxGraph repository **README**:
 - [installation](https://github.com/maxGraph/maxGraph#install)
 - [getting started](https://github.com/maxGraph/maxGraph#getting-started)
 
 
-## Usage
+## Next Steps
 
-Let's continue with the [Usage](/docs/category/usage) documentation.
+Let's continue with the [Manual](/docs/category/manual) to understand the `maxGraph` concepts.
+
+For more information on how to use specific features, please refer to the [Usage](/docs/category/usage) documentation.
diff --git a/packages/website/docs/known-issues.md b/packages/website/docs/known-issues.md
new file mode 100644
index 000000000..aabfde7fb
--- /dev/null
+++ b/packages/website/docs/known-issues.md
@@ -0,0 +1,26 @@
+---
+sidebar_position: 10
+---
+
+# Known Issues
+
+Issues are tracked in the [maxGraph GitHub Issues](https://github.com/maxGraph/maxGraph/issues).
+
+For fixed bugs, the maxGraph version including the fix can be known by checking the "Milestone" property of the issue (the Milestone name matches maxGraph versions perfectly).
+
+If you detect a new problem, please report it to the [maxGraph GitHub Issues](https://github.com/maxGraph/maxGraph/issues).
+
+
+## Original mxGraph Known Issues
+
+Historically, _mxGraph_ listed known issues on the [mxGraph Known Issues](https://github.com/jgraph/mxgraph/blob/v4.2.2/docs/known-issues.html) page.
+
+This document is probably completely outdated and most of the information is no longer relevant.
+It was last updated on _2017-04-12_ for _mxGraph_ version 3.7.2.
+
+In addition, _mxGraph_ tracked issues on the [mxGraph GitHub Issues](https://github.com/jgraph/mxgraph/issues). When the mxGraph repository was archived, all issues were closed whereas they weren't fixed.
+You can find the [issues closed when the mxGraph development stopped](https://github.com/jgraph/mxgraph/issues?page=3&q=is%3Aissue+is%3Aclosed+closed%3A%3E%3D2020-11-09) on _2020-11-09_.
+
+:::tip
+If you think some of the _mxGraph_ issues (from the GitHub repository or from the "known issues" page) are still relevant, please report them in the [maxGraph GitHub Issues](https://github.com/maxGraph/maxGraph/issues) page.
+:::
diff --git a/packages/website/docs/manual/_category_.json b/packages/website/docs/manual/_category_.json
new file mode 100644
index 000000000..158565327
--- /dev/null
+++ b/packages/website/docs/manual/_category_.json
@@ -0,0 +1,8 @@
+{
+  "label": "Manual",
+  "position": 1,
+  "link": {
+    "type": "generated-index",
+    "description": "An introduction to the concepts used in maxGraph."
+  }
+}
diff --git a/packages/website/old-mxgraph/images/mx_man_graph_analysis.jpg b/packages/website/docs/manual/assets/intro/graph_analysis.jpg
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_graph_analysis.jpg
rename to packages/website/docs/manual/assets/intro/graph_analysis.jpg
diff --git a/packages/website/old-mxgraph/images/mx_man_graph_interaction.png b/packages/website/docs/manual/assets/intro/graph_interaction.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_graph_interaction.png
rename to packages/website/docs/manual/assets/intro/graph_interaction.png
diff --git a/packages/website/old-mxgraph/images/mx_man_graph_layout.png b/packages/website/docs/manual/assets/intro/graph_layout.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_graph_layout.png
rename to packages/website/docs/manual/assets/intro/graph_layout.png
diff --git a/packages/website/old-mxgraph/images/mx_man_simple_graph.png b/packages/website/docs/manual/assets/intro/graph_simple.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_simple_graph.png
rename to packages/website/docs/manual/assets/intro/graph_simple.png
diff --git a/packages/website/old-mxgraph/images/mx_man_graph_vis.png b/packages/website/docs/manual/assets/intro/graph_visualization.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_graph_vis.png
rename to packages/website/docs/manual/assets/intro/graph_visualization.png
diff --git a/packages/website/old-mxgraph/images/mx_man_edge_routing.png b/packages/website/docs/manual/assets/model/edge_routing.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_edge_routing.png
rename to packages/website/docs/manual/assets/model/edge_routing.png
diff --git a/packages/website/old-mxgraph/images/mx_man_drill_down.png b/packages/website/docs/manual/assets/model/mx_man_drill_down.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_drill_down.png
rename to packages/website/docs/manual/assets/model/mx_man_drill_down.png
diff --git a/packages/website/old-mxgraph/images/mx_man_drilling.png b/packages/website/docs/manual/assets/model/mx_man_drilling.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_drilling.png
rename to packages/website/docs/manual/assets/model/mx_man_drilling.png
diff --git a/packages/website/old-mxgraph/images/mx_man_hello_struct.png b/packages/website/docs/manual/assets/model/mx_man_hello_struct.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_hello_struct.png
rename to packages/website/docs/manual/assets/model/mx_man_hello_struct.png
diff --git a/packages/website/old-mxgraph/images/mx_man_log_group_struct.png b/packages/website/docs/manual/assets/model/mx_man_log_group_struct.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_log_group_struct.png
rename to packages/website/docs/manual/assets/model/mx_man_log_group_struct.png
diff --git a/packages/website/old-mxgraph/images/mx_man_overlap.png b/packages/website/docs/manual/assets/model/mx_man_overlap.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_overlap.png
rename to packages/website/docs/manual/assets/model/mx_man_overlap.png
diff --git a/packages/website/old-mxgraph/images/mx_man_simple_workflow.png b/packages/website/docs/manual/assets/model/mx_man_simple_workflow.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_simple_workflow.png
rename to packages/website/docs/manual/assets/model/mx_man_simple_workflow.png
diff --git a/packages/website/old-mxgraph/images/mx_man_top_level.png b/packages/website/docs/manual/assets/model/mx_man_top_level.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_top_level.png
rename to packages/website/docs/manual/assets/model/mx_man_top_level.png
diff --git a/packages/website/old-mxgraph/images/mx_man_vertex_props.png b/packages/website/docs/manual/assets/model/mx_man_vertex_props.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_vertex_props.png
rename to packages/website/docs/manual/assets/model/mx_man_vertex_props.png
diff --git a/packages/website/old-mxgraph/images/mx_man_non_realtive_edge_pos.png b/packages/website/docs/manual/assets/model/non_relative_positioning_edge.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_non_realtive_edge_pos.png
rename to packages/website/docs/manual/assets/model/non_relative_positioning_edge.png
diff --git a/packages/website/old-mxgraph/images/mx_man_non_relative_pos.png b/packages/website/docs/manual/assets/model/non_relative_positioning_vertex.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_non_relative_pos.png
rename to packages/website/docs/manual/assets/model/non_relative_positioning_vertex.png
diff --git a/packages/website/old-mxgraph/images/mx_man_rel_vert_pos.png b/packages/website/docs/manual/assets/model/relative_positioning_vertex.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_rel_vert_pos.png
rename to packages/website/docs/manual/assets/model/relative_positioning_vertex.png
diff --git a/packages/website/old-mxgraph/images/mx_man_styles.png b/packages/website/docs/manual/assets/model/styles.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_styles.png
rename to packages/website/docs/manual/assets/model/styles.png
diff --git a/packages/website/old-mxgraph/images/mx_man_collapse_swim.png b/packages/website/docs/manual/assets/model/swimlane_collapsed.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_collapse_swim.png
rename to packages/website/docs/manual/assets/model/swimlane_collapsed.png
diff --git a/packages/website/old-mxgraph/images/mx_man_expand_swim.png b/packages/website/docs/manual/assets/model/swimlane_expanded.png
similarity index 100%
rename from packages/website/old-mxgraph/images/mx_man_expand_swim.png
rename to packages/website/docs/manual/assets/model/swimlane_expanded.png
diff --git a/packages/website/docs/manual/getting-started.md b/packages/website/docs/manual/getting-started.md
new file mode 100644
index 000000000..b7ade0691
--- /dev/null
+++ b/packages/website/docs/manual/getting-started.md
@@ -0,0 +1,37 @@
+---
+sidebar_position: 2
+description: Getting started with maxGraph.
+---
+# Getting Started
+
+:::warning
+
+The content of this page is a work in progress. The original `mxGraph` manual is progressively migrated here.
+
+Original documentation: [Getting Started (mxGraph)](https://jgraph.github.io/mxgraph/docs/manual.html#2)
+
+:::
+
+
+:::note
+
+This manual is licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). \
+It is adapted from the original [mxGraph manual](https://github.com/jgraph/mxgraph/blob/v4.2.2/docs/manual.html).
+
+> Copyright 2021-present The maxGraph project Contributors \
+Copyright (c) JGraph Ltd 2006-2020
+
+:::
+
+
+## The `maxGraph` Package
+
+### Obtaining `maxGraph`
+
+`maxGraph` is available from the <a href="https://github.com/maxGraph/maxGraph">GitHub project</a>.
+Released versions are tagged "va.b.c", where a, b and c are version number parts following
+[semantic versioning](https://semver.org/).
+
+The content of each release is documented on the [maxGraph' releases](https://github.com/jgraph/mxgraph/releases) GitHub page.
+
+[//]: # (TODO some mxGraph content has not been migrated yet, decide what to do with it. )
diff --git a/packages/website/docs/manual/index.md b/packages/website/docs/manual/index.md
new file mode 100644
index 000000000..3711d84c3
--- /dev/null
+++ b/packages/website/docs/manual/index.md
@@ -0,0 +1,281 @@
+---
+sidebar_position: 1
+description: maxGraph at a glance.
+---
+
+# Introduction
+
+:::warning
+
+The content of this page is a work in progress. The original `mxGraph` manual is progressively migrated here.
+
+Original documentation: [Introduction (mxGraph)](https://jgraph.github.io/mxgraph/docs/manual.html#1)
+
+:::
+
+
+:::note
+
+This manual is licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). \
+It is adapted from the original [mxGraph manual](https://github.com/jgraph/mxgraph/blob/v4.2.2/docs/manual.html).
+
+> Copyright 2021-present The maxGraph project Contributors \
+Copyright (c) JGraph Ltd 2006-2020
+
+:::
+
+
+## Product Introduction
+
+`maxGraph` is a JavaScript component that provides features aimed at applications that display
+interactive <a href="http://en.wikipedia.org/wiki/Diagram">diagrams</a>
+and graphs. Note by graphs we mean <a
+	href="http://en.wikipedia.org/wiki/Graph_(mathematics)">mathematical
+graphs</a>, not necessarily <a href="http://en.wikipedia.org/wiki/Charts">charts</a>
+(although some charts are graphs). See later section &ldquo;What is a
+Graph?&rdquo; for more details.
+
+Being a developer library, `maxGraph` is not designed specifically
+to provide a ready to use application, although many of the examples are
+close to being usable applications. `maxGraph` provides all the commonly
+required functionality to draw, interact with and associate a context
+with a diagram. `maxGraph` comes with a number of examples that help explain how a
+basic application is put together and showcases
+individual features of the library.
+
+[//]: # (TODO link for bellow)
+Developers integrating the library in their application should
+read the section
+&ldquo;Pre-requisites&rdquo; below. Given that `maxGraph` is a component
+part of your application, you must understand how JavaScript web
+applications are constructed at an architectural level, and how to program
+both in JavaScript, as well as any server-side languages used.
+
+[//]: # (TODO review this paragraph)
+`maxGraph` mainly comprises one JavaScript
+file that contains all the `maxGraph` functionality. This is loaded into
+a HTML web page in a JavaScript section and executes in an HTML
+container in the browser. This is an incredibly simple architecture that
+only requires a web server capable of serving html pages and a
+JavaScript enabled web browser.
+
+The key advantages of this technology are:
+- That no third-party plug-ins are required. This removes
+plug-in vendor dependence.
+- The technologies involved are open and there are many open
+implementations, no one vendor can remove a product or technology that
+leaves your application unworkable in practise.
+- Standardized technologies, meaning your application is
+deployable to the maximum number of browser users without need for
+additional configuration or installation at the client computer. Large
+corporate environments often dislike allowing individuals to install
+browser plug-ins and do not like to change the standard build rolled
+out to all machines.
+
+<a id="mxgraph_applications"></a>
+## What Applications can `maxGraph` be used for?
+
+Example applications for a graph visualization library include:
+process diagrams, workflow and BPM visualization, flowcharts, traffic or
+water flow, database and WWW visualization, networks and
+telecommunications displays, mapping applications and GIS, UML diagrams,
+electronic circuits, VLSI, CAD, financial and social networks, data
+mining, biochemistry, ecological cycles, entity and cause-effect
+relationships and organisational charts.
+
+[//]: # ()
+[//]: # (<h2><a id="mxgraph_deployment"></a>How is `maxGraph` deployed?</h2>)
+
+[//]: # ()
+[//]: # (<p>In the typical thin-client environment, `maxGraph` is split into the)
+
+[//]: # (client-side JavaScript library and a server-side library in one of the)
+
+[//]: # (two supported languages, .NET and Java. The JavaScript library is)
+
+[//]: # (contained as part of a larger web application that is delivered to the)
+
+[//]: # (browser using a standard web server. All the browser needs is the)
+
+[//]: # (ability to run JavaScript to be enabled.</p>)
+
+[//]: # ()
+[//]: # (<p>In the third part of this manual, you will see an example of an)
+
+[//]: # (html page that embeds the `maxGraph` library, as well as a simple)
+
+[//]: # (application to invoke the library's functionality.</p>)
+
+
+## `maxGraph` Technologies
+
+
+`maxGraph` uses JavaScript for the client-side functionality on the 
+browser. The JavaScript code in turn uses the underlying vector graphics
+language on the active browser to render the displayed diagram, currently SVG
+for all supported browsers.
+
+[//]: # (`maxGraph` also includes the feature to render entirely)
+
+[//]: # (using html, this limits the range of functionality available, but is)
+
+[//]: # (suitable for more simple diagrams.</p>)
+
+
+As a developer you are not exposed to browser specific features.
+As mentioned, the vector graphics language varies by browser, so `maxGraph`
+abstracts their features into a common class. Similarly, for event
+handling and DOMs. Browsers differ in their implementation of these two
+major browser functionalities, `maxGraph` exposes a constant API over all
+browsers and adapts to the inconsistencies behind the scenes.
+
+## Licensing
+
+`maxGraph` is licensed under the 
+<a href="https://www.apache.org/licenses/LICENSE-2.0"> Apache
+2.0 license</a>. For detailed licensing questions you are always advised to
+consult a legal professional.
+
+
+## What is a Graph?
+
+
+Graph visualization is based on the mathematical theory of
+networks, graph theory. If you're seeking JavaScript bar <em>charts</em>,
+pie <em>charts</em>, Gantt <em>charts</em>, have a look at the <a
+	href="http://code.google.com/apis/chart/">Google Charts</a> project
+instead, or similar.
+
+A graph consists of vertices, also called nodes, and of edges
+(the connecting lines between the nodes). Exactly how a graph appears
+visually is not defined in graph theory. The term <em>cell</em> will be
+used throughout this manual to describe an element of a graph, either
+edges, vertices or groups.
+
+![image](assets/intro/graph_simple.png)
+
+_A simple Graph_
+
+<br/>
+
+
+[//]: # (TODO need to add a link to appendices)
+There are additional definitions in graph theory that provide
+useful background when dealing with graphs, they are listed in the
+Appendices if of interest to you.
+
+### Graph Visualization
+
+
+Visualization is the process of creating a useful visual
+representation of a graph. The scope of visualization functionality is
+one of `maxGraph`s' main strength. `maxGraph` supports a wide range of
+features to enable the display of cells to only be limited by the skill
+of the developer and the platform functionality available. Vertices may
+be shapes, images, vector drawing, animations, virtually any graphical
+operations available in browsers. You can also use HTML mark-up in both
+vertices and edges.
+
+![Graph Visualization](assets/intro/graph_visualization.png)
+
+_Graph Visualization of a transport system. (c) Tourizm Maps 2003, http://www.world-maps.co.uk_
+
+### Graph Interaction
+
+Interaction is the way in which an application using `maxGraph` can
+alter the graph model through the web application GUI. `maxGraph` supports
+dragging and cloning cells, re-sizing and re-shaping, connecting and
+disconnecting, dragging and dropping from external sources, editing cell
+labels in-place and more. One of the key benefits of `maxGraph` is the
+flexibility of how interaction can be programmed.
+
+Many complex graphical web applications rely on a round-trip to
+the server in order to form the display, not only the base display but
+also the interaction events. Although this is often given the title of
+AJAX functionality, such server reliance is not appropriate for
+interaction events. Visual feedback taking longer than about 0.2 seconds
+in an application generally seriously impacts the usability. By placing
+all of the interaction on the client, `maxGraph` provides the true feel of
+an application, rather than seeming like a dumb remote terminal. It also
+allows the possibility of off-line use.
+
+![Graph Interaction](assets/intro/graph_interaction.png)
+
+_Selection shading while selecting an area through mouse drag_
+
+
+
+### Graph Layouts
+
+Graph cells can be drawn anywhere in a simple application,
+including on top of one another. Certain applications need to present
+their information in a generally ordered, or specifically ordered
+structure. This might involve ensuring cells do not overlap and stay at
+least a certain distance from one another, or that cells appear in
+specific positions relative to other cells, usually the cells they are
+connected to by edges. This activity, called the layout application, can
+be used in a number of ways to assist users in setting out their graph.
+For non-editable graphs, layout application is the process of applying a
+layout algorithm to the cells. For interactive graphs, meaning those
+that can be edited through the UI, layout application might involve only
+allowing users to make changes to certain cells in certain positions, to
+re-apply the layout algorithm after each change to the graph, or to
+apply the layout when editing is complete.
+
+![Graph Layout](assets/intro/graph_layout.png)
+
+_Layout of a workflow using a horizontal hierarchical layout_
+
+
+`maxGraph` supports a range of tree, force-directed and hierarchical
+layouts which will fit most layout needs. See the later section on using
+the layouts for more information.
+
+
+[//]: # (TODO decide if we need to keep this section)
+[//]: # (<p>In a client-server architecture there are two options for how)
+
+[//]: # (layouts can be run. The Javascript versions provide the ability to run)
+
+[//]: # (the layouting entirely on the client, while the same layout)
+
+[//]: # (implementation in Java on the server-side enables the option to offload)
+
+[//]: # (some processing to the server, if required.</p>)
+
+
+### Graph Analysis
+
+Analysis of graphs involves the application of algorithms
+determining certain details about the graph structure, for example,
+determining all routes or the shortest path between two cells. There are
+more complex graph analysis algorithms, these being often applied in
+domain specific tasks. Techniques such as clustering, decomposition, and
+optimization tend to be targeted at certain fields of science and have
+not been implemented in the core `maxGraph` packages at the current time of
+writing.
+
+![Graph Analysis: shortest path analysis](assets/intro/graph_analysis.jpg)
+
+_Shortest Path Analysis_
+
+
+## About this Manual
+
+### Pre-requisites for `maxGraph`
+
+To benefit fully from this manual you will need to have a
+reasonable understanding of web applications and of the server
+technology you wish to deploy using. Deployment examples are available
+for each of the server technologies supported, some familiarity with
+that server technology is obviously required.
+
+Basic XML knowledge is useful for changing the editor
+configuration files that describe the visual and behavioural aspects of
+the editor. You will need to understand and implement Javascript coding
+and be familiar with object orientated programming principles and modern
+software design.
+
+You do not need knowledge of the underlying vector graphics
+language that the browser uses, such as SVG or HTML canvas. `maxGraph`
+abstracts the description of the visual component into one API.
diff --git a/packages/website/docs/manual/model-and-cells.md b/packages/website/docs/manual/model-and-cells.md
new file mode 100644
index 000000000..9c013f7f8
--- /dev/null
+++ b/packages/website/docs/manual/model-and-cells.md
@@ -0,0 +1,852 @@
+---
+sidebar_position: 3
+description: An overview of the maxGraph model and cell concept.
+toc_max_heading_level: 6
+#
+#  TODO this page is very large, split it in multiple pages
+#
+---
+
+# Model and Cells
+
+:::warning
+
+The content of this page is a work in progress. The original `mxGraph` manual is progressively migrated here.
+
+Original documentation: [Model and Cells (mxGraph)](https://jgraph.github.io/mxgraph/docs/manual.html#3)
+
+:::
+
+
+:::note
+
+This manual is licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). \
+It is adapted from the original [mxGraph manual](https://github.com/jgraph/mxgraph/blob/v4.2.2/docs/manual.html).
+
+> Copyright 2021-present The maxGraph project Contributors \
+Copyright (c) JGraph Ltd 2006-2020
+
+:::
+
+
+[//]: # (TODO this header is useless, remove it &#40;it comes from mxgraph&#41;. We have a single h2 here without text)
+
+## Core `maxGraph` architecture
+
+### The `maxGraph` Model
+
+The mxGraph model is the core model that describes the structure
+of the graph, the class is called GraphModel and is found within the
+model package. Additions, changes and removals to and from the graph
+structure take place through the graph model API. The model also
+provides methods to determine the structure of the graph, as well as
+offering methods to set visual states such as visibility, grouping and
+style.
+
+However, although the transactions to the model are stored on the
+model, mxGraph is designed in such a way that the main public API is
+through the mxGraph class. The concept of "add this cell to the
+graph" is a more natural description of the action than "add
+this cell to the model of the graph". Where it is intuitive,
+functions available on the model and cells are duplicated on the graph
+and those methods on the graph class are considered the main public API.
+Throughout the rest of this manual these key API methods are given a pink background:
+
+[//]: # (TODO there is no pink background in the markdown, nor in the mxGraph manual)
+
+```javascript
+anExampleCoreAPIMethod()
+```
+
+<p>So, though many of the main API calls are through the mxGraph
+class, keep in mind that GraphModel is the underlying object that
+stores the data structure of your graph.</p>
+
+mxGraph uses a transactional system for making changes to the
+model. In the HelloWorld example we saw this code:
+
+[//]: # (TODO use the new insertVertex method)
+```javascript
+// Adds cells to the model in a single step
+graph.getModel().beginUpdate();
+try {
+   const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);
+   const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
+   graph.insertEdge(parent, null, '', v1, v2);
+}
+finally {
+   // Updates the display
+   graph.getModel().endUpdate();
+}
+```
+
+to perform the insertion of the 2 vertices and 1 edge. For each
+change to the model you make a call to beginUpdate(), make the
+appropriate calls to change the model, then call endUpdate() to finalize
+the changes and have the change event notifications sent out.
+
+**Key API Methods:**
+  - **GraphModel.beginUpdate()** - starts a new transaction or a sub-transaction.
+  - **GraphModel.endUpdate()** - completes a transaction or a sub-transaction.
+  - **Graph.addVertex()** - Adds a new vertex to the specified parent cell.
+  - **Graph.addEdge()** - Adds a new edge to the specified parent cell.
+
+
+**Note** - Technically you do not have to
+surround your changes with the _begin_ and _end_ update calls. Changes made
+outside of this update scope take immediate effect and send out the
+notifications immediately. In fact, changes within the update scope
+enact on the model straight away, the update scope is there to control
+the timing and concatenation of event notifications. Unless the update
+wrapping causes code aesthetic issues, it is worth using it by habit to
+avoid possible problems with event and undo granularity.
+
+Note the way in which the model changes are wrapped in a try
+block and the `endUpdate()` in a "finally" block. This ensures the update is
+completed, even if there is an error in the model changes. You should
+use this pattern wherever you perform model changes for ease of
+debugging.
+
+Ignore the reference to the `parent` cell for now, that will be
+explained later in this chapter.
+
+
+### The Transaction Model
+
+<p>The sub-transaction in the blue block above refers to the fact
+that transactions can be nested. That is, there is a counter in the
+model that increments for every <em>beginUpdate</em> call and decrements
+for every <em>endUpdate</em> call. After increasing to at least 1, when
+this count reaches 0 again, the model transaction is considered complete
+and the event notifications of the model change are fired.</p>
+
+<p>This means that every sub-contained section of code can (and
+should) be surrounded by the begin/end combination. This provide the
+ability in mxGraph to create separate transactions that be used as
+&ldquo;library transactions&rdquo;, the ability to create compound
+changes and for one set of events to be fired for all the changes and
+only one undo created. Automatic layouting is a good example of where
+the functionality is required.</p>
+
+<p>In automatic layouting, the user makes changes to the graph,
+usually through the user interface, and the application automatically
+positions the result according to some rules. The automatic positioning,
+the layouting, is a self-contained algorithm between begin/end update
+calls that has no knowledge of the specifics of the change. Because all
+changes within the begin/end update are made directly to the graph
+model, the layout can act upon the state of the model as the change is
+in progress.</p>
+
+<p>It is important to distinguish between functionality that acts on
+the graph model as part of a compound change and functionality that
+reacts to atomic graph change events. In the first case, such as for
+automatic layouting, the functionality takes the model as-is and acts
+upon it. This method should only be used for parts of compound model
+changes. All other parts of the application should only react to model
+change events.</p>
+
+<p>Model change events are fired when the last endUpdate call
+reduces the counter back down to 0 and indicate that at least one atomic
+graph change has occurred. The change event contains complete
+information as to what has altered (see later section on <strong>Events</strong>
+for more details).</p>
+
+
+#### The Model Change Methods
+
+<p>Below is a list of the methods that alter the graph model and
+should be placed, directly or indirectly, with the scope of an update:</p>
+
+<ul>
+	<li>add(parent, child, index)</li>
+	<li>remove(cell)</li>
+	<li>setCollapsed(cell, collapsed)</li>
+	<li>setGeometry(cell, geometry)</li>
+	<li>setRoot(root)</li>
+	<li>setStyle(cell, style)</li>
+	<li>setTerminal(cell, terminal, isSource)</li>
+	<li>setTerminals(edge,source,target)</li>
+	<li>setValue(cell, value)</li>
+	<li>setVisible(cell, visible)</li>
+</ul>
+
+<p>Initially, we will just concern ourselves with the add and
+remove, as well as the geometry and style editing methods. Note that
+these are not core API methods, as usual these methods are on the
+mxGraph class, where appropriate, and they perform the update
+encapsulation for you.</p>
+
+<p><em>Design Background</em> - Some people are confused by the
+presence of visual information being stored by the model. These
+attributes comprise cell positioning, visibility and collapsed state.
+The model stores the default state of these attributes, providing a
+common place to set them on a per-cell basis, whereas, views can
+override the values on a per-view basis. The model is simply the first
+common place in the architecture where these attributes can be set on a
+global basis. Remember, this is a graph <em>visualization</em> library,
+the visualization part is the core functionality.</p>
+
+
+##### Inserting Cells
+
+<p>The three graph cells created in the <code>HelloWorld</code>
+application are two vertices and one edge connecting the vertices. If
+you are not familiar with basic graph theory and its terminology, please
+see the <a href="http://en.wikipedia.org/wiki/Graph_theory">wikipedia
+entry</a>.</p>
+
+<p>You can add vertices and edges using the add() method on the
+model. However, for the purposes of general usage of this library, learn
+that mxGraph.insertVertex() and mxGraph.insertEdge() are the core public
+API for adding cells. The function of the model requires that the cell
+to be added is already created, whereas the mxGraph.insertVertex()
+creates the cell for you.</p>
+
+<p><strong>Core API functions:</strong></p>
+
+<ul>
+	<li><strong>mxGraph.insertVertex(</strong><strong>parent,
+	id, value, x, y, width, height, style</strong><strong>)</strong> &ndash; creates
+	and inserts a new vertex into the model, within a begin/end update
+	call.</li>
+	<li><strong>mxGraph.insertEdge(</strong><strong>parent,
+	id, value, source, target, style</strong><strong>)</strong><strong>
+	&ndash; </strong>creates and inserts a new edge into the model, within a
+	begin/end update call.</li>
+</ul>
+
+<p><code>mxGraph.insertVertex()</code> will create an `Cell` object
+and return it from the method used. The parameters of the function are:</p>
+
+<ul>
+<li><strong>parent</strong> &ndash; the cell which is the immediate
+parent of the new cell in the group structure. We will address the
+group structure shortly, but for now use <code>graph.getDefaultParent();</code>
+as your default parent, as used in the HelloWorld example.</li>
+
+<li><strong>id</strong> &ndash; this is a global unique identifier
+that describes the cell, it is always a string. This is primarily for
+referencing the cells in the persistent output externally. If you do not
+wish to maintain ids yourself, pass null into this parameter and ensure
+that mxGraphModel.isCreateIds() returns true. This way the model will
+manage the ids and ensure they are unique.</li>
+
+<li><strong>value</strong> &ndash; this is the user object of the
+cell. User object are simply that, just objects, but form the objects
+that allow you to associate the business logic of an application with
+the visual representation of mxGraph. They will be described in more
+detail later in this manual, however, to start with if you use a string
+as the user object, this will be displayed as the label on the vertex or
+edge.</li>
+
+<li><strong>x, y, width, height</strong> &ndash; as the names
+suggest, these are the x and y position of the top left corner of the
+vertex and its width and height.</li>
+
+<li><strong>style</strong> &ndash; the style description to be
+applied to this vertex. Styles will be described in more detail shortly,
+but at a simple level this parameter is a string that follows a
+particular format. In the string appears zero or more style names and
+some number of key/value pairs that override the global style or set a
+new style. Until we create custom styles, we will just use those
+currently available.</li>
+</ul>
+
+<p>With the edge addition method, the identically named parameters
+perform the same function as in the vertex addition method. The source
+and target parameters define the vertices to which the edge is
+connected. Note that the source and target vertices should already have
+been inserted into the model.</p>
+
+
+### Cell
+
+`Cell` is the cell object for both vertices and edges. `Cell`
+duplicates many of the functions available in the model. The key
+difference in usage is that using the model methods creates the
+appropriate event notifications and undo, using the cell makes the
+change but there is no record of the change. This can be useful for
+temporary visual effects such as animations or changes on a mouse over,
+for example. As a general rule though, use the model editing API unless
+you encounter a specific problem with this mechanism.
+
+When creating a new cell, three things are required in the
+constructor, a value (user object), a geometry and a style. We will now
+explore these 3 concepts before returning to the cell.
+
+
+#### Styles
+
+:::warning
+The following section is a direct copy of the mxGraph manual.
+The style mechanism has changed in maxGraph (style is now an object, and no longer a string) and this section is not up-to-date.
+:::
+
+The concept of styles and stylesheets in conceptually similar to
+CSS stylesheets, though note that CSS are actually used in mxGraph, but
+only to affect global styles in the DOM of the HTML page. Open up the
+util.mxConstants.js file in your editor and search for the first match
+on &ldquo;STYLE_&rdquo;. If you scroll down you will see a large number
+of strings defined for all the various styles available with this
+prefix. Some of styles apply to vertices, some to edges and some to
+both. As you can see, these define visual attributes on the element they
+act upon.
+
+The `Stylesheet` holds one object, styles, which is a hashtable
+mapping style names to an array of styles:
+
+![](./assets/model/styles.png)
+
+_Style arrays within the styles collection_
+
+
+In the above image the blue box represents the styles hashtable
+in mxStyleSheet. The string 'defaultVertex' is the key to an array of
+string/value pairs, which are the actual styles. Note that mxGraph
+creates two default styles, one for vertices and one for edges. If you
+look back to the helloworld example, no style was passed into the
+optional style parameter of insertVertex or insertEdge. In this case the
+default style would be used for those cells.
+
+<h5><a id="setting_cell_style"></a>Setting the Style of a Cell</h5>
+
+<p>If you wanted to specify a style other than the default for a
+cell, you must pass that new style either to the cell when it is created
+(mxGraph's insertVertex and insertEdge both have an optional parameter
+for this) or pass that style to the cell using model.setStyle().</p>
+
+<p>The style that you pass has the form stylename. ,note that the
+stylenames and key/value pairs may be in any order. Below are examples
+to demonstrate this concept, adapting the insertVertex call we saw in
+helloworld:</p>
+
+<ol>
+	<li>
+	<p>A new style called 'ROUNDED' has been created, to apply this to
+	a vertex:</p>
+	<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'ROUNDED');</pre>
+	</li>
+
+	<li>
+	<p>To create a new vertex with the ROUNDED style, overriding the
+	stroke and fill colors:</p>
+	<pre>var v1 = graph.insertVertex(parent, null, 'Hello',  20, 20, 80, 30, 'ROUNDED;strokeColor=red;fillColor=green');</pre>
+	</li>
+
+	<li>
+	<p>To create a new vertex with no global style, but with local
+	stroke and fill colors:</p>
+	<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, ';strokeColor=red;fillColor=green');</pre>
+	</li>
+	<li>
+	<p>To create a vertex that uses the defaultVertex style, but a
+	local value of the fill color:</p>
+	<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'defaultVertex;fillColor=blue');</pre>
+	</li>
+</ol>
+
+<br/>
+<p>Note that default style must be explicitly named in this case,
+missing the style out sets no global style on the cell when the
+semi-colon starts the string. If the string starts with no semi-colon,
+the default style is used.</p>
+
+<p>Again, the mxGraph class provides utility functions that form the
+core API for accessing and changing the styles of cells:</p>
+
+<p><strong>Core API functions:</strong></p>
+
+<ul>
+<li>
+<strong>mxGraph.setCellStyle(style, cells)</strong> &ndash; Sets
+the style for the array of cells, encapsulated in a begin/end update.
+</li>
+<li>
+<strong>mxGraph.getCellStyle(cell)</strong> &ndash; Returns the
+style for the specified cell, merging the styles from any local style
+and the default style for that cell type.
+</li>
+</ul>
+
+
+##### Creating a New Global Style
+
+<p>To create the ROUNDED global style described above, you can
+follow this template to create a style and register it with
+mxStyleSheet:</p>
+
+<pre>
+let style = {};
+style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
+style[mxConstants.STYLE_OPACITY] = 50;
+style[mxConstants.STYLE_FONTCOLOR]= '#774400';
+graph.getStylesheet().putCellStyle('ROUNDED',style);
+</pre>
+
+
+#### Geometry
+
+<p>In the helloworld example we saw the position and size of the
+vertices passed into the insertVertex function. The coordinate system in
+JavaScript is x is positive to the right and y is positive downwards,
+and in terms of the graph, the positioning is absolute to the container
+within which the mxGraph is placed.</p>
+
+<p>The reason for a separate mxGeometry class, as opposed to simply
+having the mxRectangle class store this information, is that the edges
+also have geometry information.</p>
+
+<p>The width and height values are ignored for edges and the x and y
+values relate to the positioning of the edge label. In addition, edges
+have the concept of control points. These are intermediate points along
+the edge that the edge is drawn as passing through. The use of control
+points is sometimes referred to as <strong>edge routing</strong>.</p>
+
+![Edge Routing](./assets/model/edge_routing.png)
+
+_An edge routed by 2 control points_
+
+<p>There are two more important additional concepts in geometry,
+relative positioning and offsets</p>
+
+
+##### Relative Positioning
+
+<p>By default, the x and y position of a vertex is the offset of the
+top left point of the bounding rectangle of the parent to the top left
+point of the bounding rectangle of the cell itself. The concept of
+parents and groups is discussed later in this chapter, but without going
+into too much detail, if a cell does not have cell parent, the graph
+container is its parent for positioning purposes.</p>
+
+
+![Non relative vertex positioning](./assets/model/non_relative_positioning_vertex.png)
+
+_Non-relative vertex positioning_
+
+
+<p>For an edge, in non-relative mode, which is the default mode, the
+edge label position is the absolute offset from the graph origin.</p>
+
+![Non relative edge positioning](./assets/model/non_relative_positioning_edge.png)
+
+_Non-relative edge label positioning_
+
+
+<p>For vertices in relative mode, (x,y) is the proportion along the
+parent cell's (width, height) where the cell's origin lies. (0,0) is the
+same origin as the parent, (1,1) places the origin at the bottom right
+corner of the parent. The same relative positioning extends below 0 and
+above 1 for both dimensions. This positioning is useful for keeping
+child cells fixed relative to the overall parent cell size.</p>
+
+![](./assets/model/relative_positioning_vertex.png)
+
+_Relative vertex positions_
+
+<p>Lastly, edge labels in relative mode are placed based on the
+positioning from the center of the edge. The x-coordinate is the
+relative distance from the source end of the edge, at -1, to the target
+end of the edge, at 1. The y co-ordinate is the pixel offset orthogonal
+from the edge. The diagram below shows the values of x,y for various
+edge labels in relative mode. Note that for a straight edge, the
+calculations are simple. For edges with multiple control points, the
+edge has to be traced along its segments (a segment being the line
+between end points and/or control points) to find the correct distance
+along the edge. The y value is the orthogonal offset from that segment.</p>
+
+<p>Switching relative positioning on for edge labels is a common
+preference for applications. Navigate to the mxGraph.insertEdge()
+function in mxGraph, you will see this calls createEdge(). In
+createEdge() the geometry is set relative for every edge created using
+this prototype. This is partly the reason for the amount of helper
+functions in mxGraph, they enable easy changing of the default
+behaviour. You should try to use the mxGraph class API as much as
+possible to provide this benefit in your applications.</p>
+
+
+##### Offsets
+
+The offset field in mxGeometry is an absolute x,y offset applied
+to the cell <strong>label</strong>. In the case of edge labels, the
+offset is always applied after the edge label has been calculated
+according to the relative flag in the above section.
+
+**Core API functions:**
+
+- **mxGraph.resizeCell(cell, bounds)** - Resizes the specified cell to the specified bounds, within a begin/end update call.
+- **mxGraph.resizeCells(cells, bounds)** - Resizes each of the cells in the cells array to the corresponding entry
+in the bounds array, within a begin/end update call.
+
+
+#### User Objects
+
+<p>The User object is what gives mxGraph diagrams a context, it
+stores the business logic associated with a visual cell. In the
+HelloWorld example the user object has just been a string, in this case
+it simply represents the label that will be displayed for that cell. In
+more complex applications, these user objects will be objects instead.
+Some attribute of that object will generally be the label that the
+visual cell will display, the rest of the object describes logic
+relating to the application domain.</p>
+
+<p>Using the example of a simple workflow or process application,
+say we have the graph below (<a
+	href="http://www.jgraph.com/demo/mxgraph/editors/workfloweditor.html">this
+example is available online</a>, select the Swimlanes example from the tasks
+window):</p>
+
+
+![](./assets/model/mx_man_simple_workflow.png)
+
+_A simple workflow_
+
+
+<p>Typically, this workflow will exist on some application server
+and/or database. The browser user connects to that server, or some
+front-end server linked to the application server and the user's web
+application requests the &ldquo;order&rdquo; workflow. The server
+obtains the data of that workflow and transmits it to the client.</p>
+
+<p>mxGraph supports the process of populating the model on the
+server-side and transmitting to the client, and back again. See the
+later chapter on &ldquo;I/O and Server Communication&rdquo;.</p>
+
+<p>The data transmitted will be both the visual model (the diagram)
+as well as the business logic (mostly contained in the user objects).
+The client will initially show the diagram above. If the user has
+permission to edit this workflow they will normally be able to do two
+things, 1) edit the diagram, add and remove vertices, as well as
+changing the connections, and 2) edit the user objects of the cells
+(vertices and/or edges).</p>
+
+<p>In the online demo, if you right click and select properties of
+the &ldquo;Check Inventory&rdquo; diamond you will see this dialog:</p>
+
+![](./assets/model/mx_man_vertex_props.png)
+
+_The properties of a vertex_
+
+<p>These properties show the geometry, label, ID etc, but a dialog
+could just as easily show the user object of the cell. There might be a
+reference to some process on the workflow engine as to how the inventory
+is actually checked. This might be an application specific mechanism for
+both the server and client to assign some identification to remote
+method calls. Another value might be the type of object that process
+returned, maybe a boolean or an integer to indicate stock level in this
+case. Given that return type, it is possible to enforce constraints with
+the diagram and provide visual alerts of if, say, the outgoing edges
+decision check does not correspond to the return type of the vertex.</p>
+
+<p>Next, as an example, the user objects of the outgoing edges might
+contain a label and a boolean state. Again, the mxGraph-based editor
+might provide the means to alter the boolean value. On the server, when
+executing the process, it might follow the edges that correspond to the
+boolean value returned by the decision node.</p>
+
+<p>Keep in mind that the above example is very domain specific, it
+is there to explain how the user object maps to the business logic of
+the application. It visualizes how mxGraph creates what we term a <strong>contextual
+graph</strong>. The context is formed by the connections between vertices and the
+business logic stored within the user objects. A typical application
+receives the visual and business logic from a sever, may allow editing
+of both, then transmits both back to the server for persistence and/or
+execution.</p>
+
+
+#### Cell Types
+
+<p>As described previously, mxGraph is the primary API for using
+this library and the same concept applies to cells. One basic state of
+the cell not exposed on the graph is whether a cell is a vertex or an
+edge, this call be performed on the cell or on the model.</p>
+
+<p>There are two boolean flags on mxCell, vertex and edge, and the
+helper methods set one of these to true when the cell is created.
+isVertex(), isEdge() on mxIGraphModel are what the model uses to
+determine a cell's type, there are not separate objects for either type.
+Technically, it is possible to switch the type of a cell at runtime, but
+take care to invalidate the cell state (see later section) after
+changing the type. Also, be aware that the geometry object variable
+means different things to vertices and edges. Generally, it is not
+recommended to change a cell type at runtime.</p>
+
+
+### Group Structure
+
+<p>Grouping, within mxGraph, is the concept of logically associating
+cells with one another. This is commonly referred to as the concept of
+sub-graphs in many graph toolkits. Grouping involves one or more
+vertices or edges becoming children of a parent vertex or edge (usually
+a vertex) in the graph model data structure. Grouping allows mxGraph to
+provide a number of useful features:</p>
+
+<ul>
+	<li>Sub-graphs, the concept of a logically separate graph that is
+	displayed in the higher level graph as a cell per sub-graph.</li>
+
+	<li>Expanding and collapsing. Collapsing is the ability to replace
+	a collection of grouped cells visually with just their parent cell.
+	Expanding is the reverse of this. This behaviour can be seen by
+	clicking the small &ldquo;-&rdquo; in the top left corner of the group
+	cells of the swimlanes example in the <a
+		href="http://www.jgraph.com/demo/mxgraph/editors/workfloweditor.html">online
+	workfloweditor</a> example. This is described in the C<em>omplexity
+	Management</em> section below.</li>
+
+	<li>Layering. Layering is the concept of assigning cells to a
+	particular z-order layer within the graph display.</li>
+
+	<li>Drill down, step up. These concepts allow sub-graphs to be
+	visualized and edited as if they are a complete graph. In the <em>User
+	Objects</em> section we saw the &ldquo;check inventory&rdquo; vertex as a
+	single cell. Take, for example, the case where a developer is
+	describing each of the vertices in the process as the software
+	processes that perform the task. The application might have an option
+	to drill down into the check inventory vertex. This would result in a
+	new graph appearing that describes in detail how exactly the system
+	checks the inventory. The graph might have the title of the parent
+	&ldquo;check inventory&rdquo; vertex to indicate it is a child, as well
+	as the option to step-up back to the next level up.</li>
+</ul>
+
+<p>In grouping, cells are assigned a parent cell. In the simplest
+case, all cells have the default parent as their parent. The default
+parent is an invisible cell with the same bounds as the graph. This is
+the cell returned by graph.getDefaultParent() in the helloworld example.
+The x,y position of a vertex is its position relative to its parent, so
+in the case of default grouping (all cells sharing the default parent)
+the cell positioning is also the absolute co-ordinates on the graph
+component. In the case all cells being added to the default root, the
+group structure logically looks like, in the case of the helloworld
+example, the diagram below.</p>
+
+<p>Note the addition of the Layer 0 cell, this is the default
+indirection in the group structure that allows layer changes with the
+requirement of additional cells. We include it below for correctness,
+but in later group diagrams it will be omitted.</p>
+
+
+![](./assets/model/mx_man_hello_struct.png)
+
+_The group structure of the helloworld example_
+
+<p>Also, note that the position of the edge label (x,y in geometry)
+is relative to the parent cell.</p>
+
+<p>If we go back to the simple workflow example in the User Objects
+section, we can see what grouping might look like visually. In the
+example the group cells represent people and the child vertices
+represent tasks assigned to those people. In this example the logical
+group structure looks like this:</p>
+
+![](./assets/model/mx_man_log_group_struct.png)
+
+_The logical group structure of the workflow example_
+
+<p>The workflow action vertices are the yellow children and the
+swimlane group vertices are marked blue.</p>
+
+<p>Inserting cells into the group structure is achieved using the
+parent parameter of the insertVertex and insertEdge functions on the
+mxGraph class. These functions set the parent cell on the child
+accordingly and, importantly, informs the parent cell of its new child.</p>
+
+<p>Altering the group structure is performed via the
+mxGraph.groupCells() and mxGraph.ungroupCells() functions.</p>
+
+**Core API functions:**
+
+- **mxGraph.groupCells(group, border, cells)** - Adds the specified cells to the specified group, within a begin/end update
+- **mxGraph.ungroupCells(cells)** - Removes the specified cells from their parent and adds them to their parent's
+parent. Any group empty after the operation are deleted. The operation occurs within a begin/end update.
+
+
+### Complexity Management
+
+<p>There are two primary reasons to control the number of cells
+displayed at any one time. The first is performance, drawing more and
+more cells will reach performance usability limits at some point on any
+platform. The second reason is ease of use, a human can only comprehend
+a certain amount of information. All of the concepts associated with
+grouping, listed above, can be used to reduce the complexity of
+information on the screen for the user.</p>
+
+#### Folding
+
+<p>Folding is the collective term we use for expanding and
+collapsing groups. We say a cell is folded by making it's child vertices
+invisible. There are a number of functions relating to this feature:</p>
+
+<p><strong>Core API function:</strong></p>
+
+<ul><li><strong>mxGraph.foldCells(collapse, recurse, cells)</strong>
+&ndash; States the collapsed state of the specificed cells, within a
+begin/end update.</li></ul>
+
+<p><strong>Folding related functions:</strong></p>
+
+<p><strong>mxGraph.isCellFoldable(cell, collapse)</strong> &ndash;
+By default true for cells with children.</p>
+<p><strong>mxGraph.isCellCollapsed(cell)</strong> &ndash; Returns
+the folded state of the cell</p>
+
+<p>When a group cell is collapsed, three things occur by default:</p>
+
+<ul>
+	<li>The children of that cell become invisible.</li>
+	<li>The group bounds of the group cell is used. Within mxGeometry
+	there is a alternativeBounds field and in groups cells, by default
+	store a separate bounds for their collapsed and expanded states. The
+	switch between these instances is invoked by mxGraph.swapBounds() and
+	this is handled for you within a foldCells() call. This allows
+	collapsed groups to be resized whilst when expanded again the size
+	looks correct using the pre-collapsed size.</li>
+	<li>Edge promotion occurs, by default. Edge promotion means
+	displaying edges that connect to children within the collapsed group
+	that also connect to cells outside of the collapsed group, by making
+	them appear to connect to the collapsed parent.</li>
+</ul>
+
+
+![](./assets/model/swimlane_expanded.png)
+
+_Expanded swimlane_
+
+![](./assets/model/swimlane_collapsed.png)
+
+_Collapsed swimlane_
+
+
+<p>The above two images demonstrate these three concepts. In its
+expanded state the upper group cell displays a small box in the top left
+hand corner with a &ldquo;-&rdquo; character inside. This indicates that
+clicking on this box collapses the group cell. Doing this we get the
+bottom image where the group cell takes on its collapsed size. Child
+vertices and edge that do not leave the group cell are made invisible.
+Finally, edges that exit the group cell are promoted to appear to be
+connected to the collapsed group cell. Clicking on the &ldquo;+&rdquo;
+character that now appears within the box expands the group cell and
+brings it back to its original state of the top image.</p>
+
+<p>Using the mxGraph.foldCells() function, you can achieve the same
+result programmatically as clicking on the expand/collapse symbols. One
+common usage of this is when the application zooms out a specific
+amount, clusters of cells are grouped and the grouped cell collapsed
+(very often without the &ldquo;-&rdquo; box since the application is
+controlling the folding). This way fewer, larger cells are visible to
+the user, each one representing their children cells logically. You
+might then provide a mechanism to zoom into a group, which expands it in
+the process. You might also provide drill-down/step-up, explained next.</p>
+
+
+#### Sub-Graphs, Drill-Down / Step-Up
+
+<p>Sometimes, as an alternative to expand/collapse, or possibly in
+combination with it, your graph will be composed of a number of graphs,
+nested into a hierarchy. Below we see a simple example:</p>
+
+
+![](./assets/model/mx_man_drill_down.png)
+
+_An example top level workflow_
+
+<p>This simple workflow consists of three high level steps.
+Obviously, the individual steps contain a number of sub-steps and we
+will look at a sub-graph of the <em>Solve Bug</em> cell.</p>
+
+<p>Under the <em>Solve Bug</em> vertex we have created a number of
+children to represent the process of solving a bug in more detail, in
+this case the process of solving a bug on the <a
+	href="http://en.wikipedia.org/wiki/Starship_Enterprise">Starship
+Enterprise</a>.</p>
+
+<p>In this example, which uses the GraphEditor example, the menu
+option shown selected in the above image invokes
+mxGraph.enterGroup(cell), which is one of the pair of core API functions
+for sub-graphs.</p>
+
+
+**Core API functions:**
+
+- **mxGraph.enterGroup(cell)** - Makes the specified cell the new root of the display area.
+- **mxGraph.exitGroup()** - Makes the parent of the current root cell, if any, the new root cell.
+- **mxGraph.home()** - Exits all groups, making the default parent the root cell.
+
+<p>The root cell of the graph has been, up to now, the default
+parent vertex to all first-level cells. Using these functions you can
+make any group cell in the group structure the root cell, so that the
+children of that parent appear in the display as the complete graph.</p>
+
+![](./assets/model/mx_man_drilling.png)
+
+_Result of drilling down into the Solve Bug vertex_
+
+
+<p>The same graph expanded using folding instead looks like:</p>
+
+![](./assets/model/mx_man_top_level.png)
+
+
+<p>Exiting the group using the <em>shape-&gt;exit group</em> option,
+which invokes mxGraph.exitGroup, brings you back to the original 3
+vertex top level graph.</p>
+
+
+#### Layering and Filtering
+
+<p>In mxGraph, like many graphical applications, there is the
+concept of z-order. That is, the order of objects as you look into the
+screen direction. Objects can be behind or in front of other objects and
+if they overlap and are opaque then the back-most object will be
+partially or complete obscured. Look back to the <a href="#ill_mx_man_hello_struct">
+graph structure of HelloWorld illustration</a> above. Children cells are stored under
+parents in a deterministic order (by default the order in which you add
+them).</p>
+
+<p>If we move the cells in the HelloWorld example we see the
+following result:</p>
+
+![](./assets/model/mx_man_overlap.png)
+
+_Overlapped vertices_
+
+<p>It can be seen that the <em>World</em> vertex is in front of the
+<em>Hello</em> vertex. This is because the <em>World</em> vertex has a
+higher child index than the <em>Hello</em> vertex, at positions 1 and 0
+respectively in the ordered collection that holds the children of the
+root cell.</p>
+
+<p>To change order we use mxGraph.orderCells.</p>
+
+
+<p><strong>Core API function:</strong></p>
+
+<ul><li><strong>mxGraph.orderCells(back, cells)</strong> &ndash; Moves
+the array of cells to the front or back of their siblings, depending on
+the flag, within a begin/end update.</li></ul>
+
+<p>A sibling cell in mxGraph is any cell that shares the same
+parent. So by invoking this on the <em>Hello</em> vertex it would then
+overlap the <em>World</em> Vertex.</p>
+
+<p>Ordering and grouping can be extended to form logically layered
+groups. The cells are drawn via a depth-first search. Take the
+HelloWorld example again and imagine that both the <em>Hello</em> and <em>World
+</em>vertices have some hierarchy of children underneath them. The <em>Hello</em>
+vertex and all of its children will be drawn before the <em>World</em>
+vertex or any of its children. If <em>Hello</em> and <em>World</em> were
+invisible group cells you then have two hierarchies of cells, one being
+drawn entirely before the other. You can also switch the order of the
+hierarchies by simply switching the order of the invisible group cells.</p>
+
+<p>The concept of layering is demonstrated in the layers.html
+example. Here buttons are used to set the visibility of group layer
+cells. This example ties very closely into the concept of filtering.</p>
+
+<p>In filtering cells with some particular attribute are displayed.
+One option to provide filtering functionality is to check some state
+before rendering the cells. Another method, if the filtering conditions
+are simple and known in advance, is to assign filterable cells by
+groups. Making the groups visible and invisible performs this filtering
+operation.</p>
diff --git a/packages/website/docs/usage/_category_.json b/packages/website/docs/usage/_category_.json
index 95126787b..c8b3fbf15 100644
--- a/packages/website/docs/usage/_category_.json
+++ b/packages/website/docs/usage/_category_.json
@@ -3,6 +3,6 @@
   "position": 2,
   "link": {
     "type": "generated-index",
-    "description": "Everything you need to know to use maxGraph."
+    "description": "Everything you need to know to use specific features of maxGraph."
   }
 }
diff --git a/packages/website/old-mxgraph/known-issues.html b/packages/website/old-mxgraph/known-issues.html
index 84e6f5596..52abf4330 100644
--- a/packages/website/old-mxgraph/known-issues.html
+++ b/packages/website/old-mxgraph/known-issues.html
@@ -1,3 +1,11 @@
+<!-- THIS DOCUMENT IS PROBABLY FULLY OUTDATED AND MOST OF THE INFORMATION IS NO LONGER RELEVANT.
+Last Update: 2017-04-12 (mxGraph 3.7.2 release) source: https://github.com/jgraph/mxgraph/blob/v4.2.2/docs/known-issues.html
+
+It won't be migrated, and it will be removed once all mxGraph documentation content has been integrated in the maxGraph documentation.
+
+See the `known-issues` page in the maxGraph documentation which explains how we take care of this out-dated content.
+-->
+
 <html>
 <head>
 	<title>mxGraph - Known Issues</title>
@@ -93,7 +101,7 @@ if (mxClient.IS_NS)
 graph.setHtmlLabels(true);
 graph.insertVertex(parent, null, '<span style="background:yellow;">Hello</span>', 20, 20, 80, 30, 'textOpacity=50');
 </pre>
-	For different CSS opacities inside the label, try using 
+	For different CSS opacities inside the label, try using
 	<code>mxClient.NO_FO = true</code> before rendering the graph.
 </p>
 <h2><a id="Chrome5LocalFiles"></a>Local XHR in Chrome</h2>
@@ -139,7 +147,7 @@ graph.insertVertex(parent, null, '<span style="background:yellow;">Hello</span>'
 	article also states the the access works for signed scripts, however, this
 	has not been tested.
 </p>
-<p>	
+<p>
 	For mxUtils.saveAs in Firefox, the same restrictions apply. However, the
 	function may be used in IE7 without any client-side settings.
 </p>
diff --git a/packages/website/old-mxgraph/manual.html b/packages/website/old-mxgraph/manual.html
index a67bc52e2..aa1df98dc 100644
--- a/packages/website/old-mxgraph/manual.html
+++ b/packages/website/old-mxgraph/manual.html
@@ -1,265 +1,17 @@
-<html>
-<head>
-	<title>mxGraph User Manual - JavaScript Client</title>
-    <link rel="stylesheet" href="css/manual-styles.css">
-    <link rel="stylesheet" href="css/manual-colors.css">
-    <script type="text/javascript" src="js/toc.js"></script>
-</head>
-<body onload="maketoc(document.getElementById('toc'));">
-<h1>mxGraph User Manual &ndash; JavaScript Client</h1>
-<br/>
-<br/>
-<p>mxGraph Version 4.2.2 &ndash; 28. October 2020</p>
-<p>Copyright (c) JGraph Ltd 2006-2020</p>
-<br/>
-<p>Licensed under <a href="https://creativecommons.org/licenses/by/4.0/">
-Creative Commons Attribution 4.0 International (CC BY 4.0)</a></p>
-
-<br/>
-<h1>Table Of Contents</h1>
-<div id="toc"></div>
-
-<br/>
-<h1><a id="Introduction"></a>Introduction</h1>
-<h2><a id="mxGraph_Products"></a>Product Introduction</h2>
-
-<p>mxGraph is a JavaScript component that provides features aimed at applications that display
-interactive <a href="http://en.wikipedia.org/wiki/Diagram">diagrams</a>
-and graphs. Note by graphs we mean <a
-	href="http://en.wikipedia.org/wiki/Graph_(mathematics)">mathematical
-graphs</a>, not necessarily <a href="http://en.wikipedia.org/wiki/Charts">charts</a>
-(although some charts are graphs). See later section &ldquo;What is a
-Graph?&rdquo; for more details.</p>
-
-<p>Being a developer library, mxGraph is not designed specifically
-to provide a ready to use application, although many of the examples are
-close to being usable applications. mxGraph provides all the commonly
-required functionality to draw, interact with and associate a context
-with a diagram. mxGraph comes with a number of examples that help explain how a
-basic application is put together and showcases
-individual features of the library.</p>
-
-<p>Developers integrating the library in their application should
-read the section
-&ldquo;Pre-requisites&rdquo; below. Given that mxGraph is a component
-part of your application, you must understand how JavaScript web
-applications are constructed at an architectural level, and how to program
-both in JavaScript, as well as any server-side languages used.</p>
-
-<p>mxGraph mainly comprises one JavaScript
-file that contains all of the mxGraph functionality. This is loaded into
-a HTML web page in a JavaScript section and executes in an HTML
-container in the browser. This is an incredibly simple architecture that
-only requires a web server capable of serving html pages and a
-JavaScript enabled web browser.</p>
-
-<p>The key advantages of this technology are:</p>
-<ul>
-	<li>That no third-party plug-ins are required. This removes
-	plug-in vendor dependence.</li>
-	<li>The technologies involved are open and there are many open
-	implementations, no one vendor can remove a product or technology that
-	leaves your application unworkable in practise.</li>
-	<li>Standardized technologies, meaning your application is
-	deployable to the maximum number of browser users without need for
-	additional configuration or installation at the client computer. Large
-	corporate environments often dislike allowing individuals to install
-	browser plug-ins and do not like to change the standard build rolled
-	out to all machines.</li>
-</ul>
-
+<!-- ================================================================================= -->
+<!-- in 1.1 this doesn't apply in maxGraph -->
+<!-- all mxgraph components, including server components -->
+<!-- ================================================================================= -->
 <p><img src="images/mx_man_architecture.png" name="mxgraph_architecture" />
 <br/>
 <em>The mxGraph components and their relationships</em></p>
 
-<h2><a id="mxgraph_applications"></a>What Applications can
-mxGraph be used for?</h2>
-
-<p>Example applications for a graph visualization library include:
-process diagrams, workflow and BPM visualization, flowcharts, traffic or
-water flow, database and WWW visualization, networks and
-telecommunications displays, mapping applications and GIS, UML diagrams,
-electronic circuits, VLSI, CAD, financial and social networks, data
-mining, biochemistry, ecological cycles, entity and cause-effect
-relationships and organisational charts.</p>
-
-<h2><a id="mxgraph_deployment"></a>How is mxGraph deployed?</h2>
-
-<p>In the typical thin-client environment, mxGraph is split into the
-client-side JavaScript library and a server-side library in one of the
-two supported languages, .NET and Java. The JavaScript library is
-contained as part of a larger web application that is delivered to the
-browser using a standard web server. All the browser needs is the
-ability to run JavaScript to be enabled.</p>
-
-<p>In the third part of this manual, you will see an example of an
-html page that embeds the mxGraph library, as well as a simple
-application to invoke the library's functionality.</p>
-
-<h2><a id="mxgraph_technologies"></a>mxGraph Technologies</h2>
-
-<p>mxGraph uses JavaScript for the client-side functionality on the
-browser. The JavaScript code in turn uses the underlying vector graphics
-language on the active browser to render the displayed diagram, currently SVG
-for all supported browsers. mxGraph also includes the feature to render entirely
-using html, this limits the range of functionality available, but is
-suitable for more simple diagrams.</p>
-
-<p>As a developer you are not exposed to browser specific features.
-As mentioned, the vector graphics language varies by browser, so mxGraph
-abstracts their features into a common class. Similarly, for event
-handling and DOMs. Browsers differ in their implementation of these two
-major browser functionalities, mxGraph exposes a constant API over all
-browsers and adapts to the inconsistencies behind the scenes.</p>
-
-<h2><a id="mxgraph_licensing"></a>mxGraph Licensing</h2>
-
-<p>The JavaScript client of mxGraph is licensed under the
-<a href="https://www.apache.org/licenses/LICENSE-2.0"> Apache
-2.0 license</a>. For detailed licensing questions you are always advised to
-consult a legal professional.</p>
-
-<h2><a id="what_graph"></a>What is a Graph?</h2>
-
-<p>Graph visualization is based on the mathematical theory of
-networks, graph theory. If you're seeking JavaScript bar <em>charts</em>,
-pie <em>charts</em>, Gantt <em>charts</em>, have a look at the <a
-	href="http://code.google.com/apis/chart/">Google Charts</a> project
-instead, or similar</p>
-<p>A graph consists of vertices, also called nodes, and of edges
-(the connecting lines between the nodes). Exactly how a graph appears
-visually is not defined in graph theory. The term <em>cell</em> will be
-used throughout this manual to describe an element of a graph, either
-edges, vertices or groups.</p>
-
-<p><img src="images/mx_man_simple_graph.png" /><br/>
-<em>A simple Graph</em></p>
-<br/>
-
-<p>There are additional definitions in graph theory that provide
-useful background when dealing with graphs, they are listed in the
-Appendices if of interest to you.</p>
-
-<h3><a id="graph_visualization"></a>Graph Visualization</h3>
-
-<p>Visualization is the process of creating a useful visual
-representation of a graph. The scope of visualization functionality is
-one of mxGraphs' main strength. mxGraph supports a wide range of
-features to enable the display of cells to only be limited by the skill
-of the developer and the platform functionality available. Vertices may
-be shapes, images, vector drawing, animations, virtually any graphical
-operations available in browsers. You can also use HTML mark-up in both
-vertices and edges.</p>
-
-<p><img src="images/mx_man_graph_vis.png"><br/>
-<em>Graph Visualization of a transport system. (c) Tourizm Maps
-2003, http://www.world-maps.co.uk</em></p>
-<br/>
-<h3><a id="graph_interaction"></a>Graph Interaction</h3>
-
-<p>Interaction is the way in which an application using mxGraph can
-alter the graph model through the web application GUI. mxGraph supports
-dragging and cloning cells, re-sizing and re-shaping, connecting and
-disconnecting, dragging and dropping from external sources, editing cell
-labels in-place and more. One of the key benefits of mxGraph is the
-flexibility of how interaction can be programmed.</p>
-
-<p>Many complex graphical web applications rely on a round-trip to
-the server in order to form the display, not only the base display but
-also the interaction events. Although this is often given the title of
-AJAX functionality, such server reliance is not appropriate for
-interaction events. Visual feedback taking longer than about 0.2 seconds
-in an application generally seriously impacts the usability. By placing
-all of the interaction on the client, mxGraph provides the true feel of
-an application, rather than seeming like a dumb remote terminal. It also
-allows the possibility of off-line use.</p>
-
-<p><img src="images/mx_man_graph_interaction.png" /><br/>
-<em>Selection shading while selecting an area through mouse drag</em></p>
-<br/>
-<h3><a id="graph_layouts"></a>Graph Layouts</h3>
-
-<p>Graph cells can be drawn anywhere in a simple application,
-including on top of one another. Certain applications need to present
-their information in a generally ordered, or specifically ordered
-structure. This might involve ensuring cells do not overlap and stay at
-least a certain distance from one another, or that cells appear in
-specific positions relative to other cells, usually the cells they are
-connected to by edges. This activity, called the layout application, can
-be used in a number of ways to assist users in setting out their graph.
-For non-editable graphs, layout application is the process of applying a
-layout algorithm to the cells. For interactive graphs, meaning those
-that can be edited through the UI, layout application might involve only
-allowing users to make changes to certain cells in certain positions, to
-re-apply the layout algorithm after each change to the graph, or to
-apply the layout when editing is complete.</p>
-
-<p><img src="images/mx_man_graph_layout.png" /><br/>
-<em>Layout of a workflow using a horizontal hierarchical layout</em></p>
-
-<p>mxGraph supports a range of tree, force-directed and hierarchical
-layouts which will fit most layout needs. See the later section on using
-the layouts for more information.</p>
-
-<p>In a client-server architecture there are two options for how
-layouts can be run. The Javascript versions provide the ability to run
-the layouting entirely on the client, while the same layout
-implementation in Java on the server-side enables the option to offload
-some processing to the server, if required.</p>
-
-<h3><a id="graph_analysis"></a>Graph Analysis</h3>
-
-<p>Analysis of graphs involves the application of algorithms
-determining certain details about the graph structure, for example,
-determining all routes or the shortest path between two cells. There are
-more complex graph analysis algorithms, these being often applied in
-domain specific tasks. Techniques such as clustering, decomposition, and
-optimization tend to be targeted at certain fields of science and have
-not been implemented in the core mxGraph packages at the current time of
-writing.</p>
-
-<p><img src="images/mx_man_graph_analysis.jpg"
-	name="shortest_path_analyis" /><br/>
-<em>Shortest Path Analysis</em></p>
-<br/>
 
-<h2><a id="about_manual"></a>About this Manual</h2>
-
-<h3><a id="pre_requisites"></a>Pre-requisites for mxGraph</h3>
-
-<p>To benefit fully from this manual you will need to have a
-reasonable understanding of web applications and of the server
-technology you wish to deploy using. Deployment examples are available
-for each of the server technologies supported, some familiarity with
-that server technology is obviously required.</p>
-
-<p>Basic XML knowledge is useful for changing the editor
-configuration files that describe the visual and behavioural aspects of
-the editor. You will need to understand and implement Javascript coding
-and be familiar with object orientated programming principles and modern
-software design.</p>
-
-<p>You do not need knowledge of the underlying vector graphics
-language that the browser uses, such as SVG or HTML canvas. mxGraph
-abstracts the description of the visual component into one API.</p>
-
-<h1><a id="Getting_Started"></a>Getting Started</h1>
-
-<h2><a id="mxgraph_site"></a>The mxGraph Package</h2>
-
-<h3><a id="obtaining_mxgraph"></a>Obtaining mxGraph</h3>
-
-<p>
-mxGraph is available from the <a href="https://github.com/jgraph/mxgraph">GitHub project</a>.
-Released versions are tagged "va.b.c", where a, b and c are version number parts following
-<a href="http://semver.org/">semantic versioning</a>.
-</p>
-
-<p>
-Each formal release is also available as .zip or .tar.gz on the
-<a href="https://github.com/jgraph/mxgraph/releases">mxGraph releases</a> page.
-</p>
+<!-- ================================================================================= -->
+<!-- in 2 -->
+<!-- ================================================================================= -->
 
+<!-- in 2.1.2 this doesn't apply in maxGraph -->
 <h3><a id="project_structure"></a>Project structure and build
 options</h3>
 
@@ -343,6 +95,7 @@ directories in the installation root.</p>
 <p><em>Table: Project Directory Structure</em></p>
 <br/>
 
+
 <h3><a id="npm"></a>npm</h3>
 
 <p>mxGraph is also available via the npm package manager. To use mxGraph as
@@ -797,840 +550,9 @@ user on most modern networks, but there might be situations where the
 smaller version would be preferable.</p>
 
 <br/>
-<h1><a id="model_cells"></a>mxGraph Model and Cells</h1>
-
-<h2><a id="mxgraph_architecture"></a>Core mxGraph architecture</h2>
-
-<h3><a id="mxgraph_model"></a>The mxGraph Model</h3>
-
-<p>The mxGraph model is the core model that describes the structure
-of the graph, the class is called mxGraphModel and is found within the
-model package. Additions, changes and removals to and from the graph
-structure take place through the graph model API. The model also
-provides methods to determine the structure of the graph, as well as
-offering methods to set visual states such as visibility, grouping and
-style.</p>
-
-<p>However, although the transactions to the model are stored on the
-model, mxGraph is designed in such a way that the main public API is
-through the mxGraph class. The concept of &ldquo;add this cell to the
-graph&rdquo; is a more natural description of the action than &ldquo;add
-this cell to the model of the graph&rdquo;. Where it is intuitive,
-functions available on the model and cells are duplicated on the graph
-and those methods on the graph class are considered the main public API.
-Throughout the rest of this manual these key API methods are given a pink background:</p>
-<div id="coreapi">
-<p>anExampleCoreAPIMethod()</p>
-</div>
-
-<p>So, though many of the main API calls are through the mxGraph
-class, keep in mind that mxGraphModel is the underlying object that
-stores the data structure of your graph.</p>
-
-<p>mxGraph uses a transactional system for making changes to the
-model. In the HelloWorld example we saw this code:</p>
-
-<pre>
-// Adds cells to the model in a single step
-graph.getModel().beginUpdate();
-try
-{
-   var v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);
-   var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
-   var e1 = graph.insertEdge(parent, null, '', v1, v2);
-}
-finally
-{
-   // Updates the display
-   graph.getModel().endUpdate();
-}
-</pre>
-
-<p>to perform the insertion of the 2 vertices and 1 edge. For each
-change to the model you make a call to beginUpdate(), make the
-appropriate calls to change the model, then call endUpdate() to finalize
-the changes and have the change event notifications sent out.</p>
-
-<div id="coreapi">
-<p><strong>Key API Methods:</strong></p>
-
-<ul>
-	<li><strong>mxGraphModel.beginUpdate() </strong>- starts a new
-	transaction or a sub-transaction.</li>
-	<li><strong>mxGraphModel.endUpdate()</strong> - completes a
-	transaction or a sub-transaction.</li>
-	<li><strong>mxGraph.addVertex()</strong> - Adds a new vertex to
-	the specified parent cell.</li>
-	<li><strong>mxGraph.addEdge()</strong> - Adds a new edge to the
-	specified parent cell.</li>
-</ul>
-</div>
-
-<p><strong>Note</strong> &ndash; Technically you do not have to
-surround your changes with the begin and end update calls. Changes made
-outside of this update scope take immediate effect and send out the
-notifications immediately. In fact, changes within the update scope
-enact on the model straight away, the update scope is there to control
-the timing and concatenation of event notifications. Unless the update
-wrapping causes code aesthetic issues, it is worth using it by habit to
-avoid possible problems with event and undo granularity.</p>
-
-<p>Note the way in which the model changes are wrapped in a try
-block and the endUpdate() in a finally block. This ensures the update is
-completed, even if there is an error in the model changes. You should
-use this pattern wherever you perform model changes for ease of
-debugging.</p>
-
-<p>Ignore the reference to the parent cell for now, that will be
-explained later in this chapter.</p>
-
-<h3><a id="transaction_model"></a>The Transaction Model</h3>
-
-<p>The sub-transaction in the blue block above refers to the fact
-that transactions can be nested. That is, there is a counter in the
-model that increments for every <em>beginUpdate</em> call and decrements
-for every <em>endUpdate</em> call. After increasing to at least 1, when
-this count reaches 0 again, the model transaction is considered complete
-and the event notifications of the model change are fired.</p>
-
-<p>This means that every sub-contained section of code can (and
-should) be surrounded by the begin/end combination. This provide the
-ability in mxGraph to create separate transactions that be used as
-&ldquo;library transactions&rdquo;, the ability to create compound
-changes and for one set of events to be fired for all the changes and
-only one undo created. Automatic layouting is a good example of where
-the functionality is required.</p>
-
-<p>In automatic layouting, the user makes changes to the graph,
-usually through the user interface, and the application automatically
-positions the result according to some rules. The automatic positioning,
-the layouting, is a self-contained algorithm between begin/end update
-calls that has no knowledge of the specifics of the change. Because all
-changes within the begin/end update are made directly to the graph
-model, the layout can act upon the state of the model as the change is
-in progress.</p>
-
-<p>It is important to distinguish between functionality that acts on
-the graph model as part of a compound change and functionality that
-reacts to atomic graph change events. In the first case, such as for
-automatic layouting, the functionality takes the model as-is and acts
-upon it. This method should only be used for parts of compound model
-changes. All other parts of the application should only react to model
-change events.</p>
-
-<p>Model change events are fired when the last endUpdate call
-reduces the counter back down to 0 and indicate that at least one atomic
-graph change has occurred. The change event contains complete
-information as to what has altered (see later section on <strong>Events</strong>
-for more details).</p>
-
-<h4><a id="model_change_methods"></a>The Model Change Methods</h4>
-
-<p>Below is a list of the methods that alter the graph model and
-should be placed, directly or indirectly, with the scope of an update:</p>
-
-<ul>
-	<li>add(parent, child, index)</li>
-	<li>remove(cell)</li>
-	<li>setCollapsed(cell, collapsed)</li>
-	<li>setGeometry(cell, geometry)</li>
-	<li>setRoot(root)</li>
-	<li>setStyle(cell, style)</li>
-	<li>setTerminal(cell, terminal, isSource)</li>
-	<li>setTerminals(edge,source,target)</li>
-	<li>setValue(cell, value)</li>
-	<li>setVisible(cell, visible)</li>
-</ul>
-
-<p>Initially, we will just concern ourselves with the add and
-remove, as well as the geometry and style editing methods. Note that
-these are not core API methods, as usual these methods are on the
-mxGraph class, where appropriate, and they perform the update
-encapsulation for you.</p>
-
-<p><em>Design Background</em> - Some people are confused by the
-presence of visual information being stored by the model. These
-attributes comprise cell positioning, visibility and collapsed state.
-The model stores the default state of these attributes, providing a
-common place to set them on a per-cell basis, whereas, views can
-override the values on a per-view basis. The model is simply the first
-common place in the architecture where these attributes can be set on a
-global basis. Remember, this is a graph <em>visualization</em> library,
-the visualization part is the core functionality.</p>
-
-<h5><a id="inserting_cells"></a>Inserting Cells</h5>
-
-<p>The three graph cells created in the <CODE>HelloWorld</CODE>
-application are two vertices and one edge connecting the vertices. If
-you are not familiar with basic graph theory and its terminology, please
-see the <a href="http://en.wikipedia.org/wiki/Graph_theory">wikipedia
-entry</a>.</p>
-
-<p>You can add vertices and edges using the add() method on the
-model. However, for the purposes of general usage of this library, learn
-that mxGraph.insertVertex() and mxGraph.insertEdge() are the core public
-API for adding cells. The function of the model requires that the cell
-to be added is already created, whereas the mxGraph.insertVertex()
-creates the cell for you.</p>
-
-<div id="coreapi">
-<p><strong>Core API functions:</strong></p>
-
-<ul>
-	<li><strong>mxGraph.insertVertex(</strong><strong>parent,
-	id, value, x, y, width, height, style</strong><strong>)</strong> &ndash; creates
-	and inserts a new vertex into the model, within a begin/end update
-	call.</li>
-	<li><strong>mxGraph.insertEdge(</strong><strong>parent,
-	id, value, source, target, style</strong><strong>)</strong><strong>
-	&ndash; </strong>creates and inserts a new edge into the model, within a
-	begin/end update call.</li>
-</ul>
-</div>
-
-<p><code>mxGraph.insertVertex()</code> will create an mxCell object
-and return it from the method used. The parameters of the function are:</p>
-
-<ul>
-<li><strong>parent</strong> &ndash; the cell which is the immediate
-parent of the new cell in the group structure. We will address the
-group structure shortly, but for now use <code>graph.getDefaultParent();</code>
-as your default parent, as used in the HelloWorld example.</li>
-
-<li><strong>id</strong> &ndash; this is a global unique identifier
-that describes the cell, it is always a string. This is primarily for
-referencing the cells in the persistent output externally. If you do not
-wish to maintain ids yourself, pass null into this parameter and ensure
-that mxGraphModel.isCreateIds() returns true. This way the model will
-manage the ids and ensure they are unique.</li>
-
-<li><strong>value</strong> &ndash; this is the user object of the
-cell. User object are simply that, just objects, but form the objects
-that allow you to associate the business logic of an application with
-the visual representation of mxGraph. They will be described in more
-detail later in this manual, however, to start with if you use a string
-as the user object, this will be displayed as the label on the vertex or
-edge.</li>
-
-<li><strong>x, y, width, height</strong> &ndash; as the names
-suggest, these are the x and y position of the top left corner of the
-vertex and its width and height.</li>
-
-<li><strong>style</strong> &ndash; the style description to be
-applied to this vertex. Styles will be described in more detail shortly,
-but at a simple level this parameter is a string that follows a
-particular format. In the string appears zero or more style names and
-some number of key/value pairs that override the global style or set a
-new style. Until we create custom styles, we will just use those
-currently available.</li>
-</ul>
-
-<p>With the edge addition method, the identically named parameters
-perform the same function as in the vertex addition method. The source
-and target parameters define the vertices to which the edge is
-connected. Note that the source and target vertices should already have
-been inserted into the model.</p>
-
-<h3><a id="mxcell"></a>mxCell</h3>
-
-<p>mxCell is the cell object for both vertices and edges. mxCell
-duplicates many of the functions available in the model. The key
-difference in usage is that using the model methods creates the
-appropriate event notifications and undo, using the cell makes the
-change but there is no record of the change. This can be useful for
-temporary visual effects such as animations or changes on a mouse over,
-for example. As a general rule though, use the model editing API unless
-you encounter a specific problem with this mechanism.</p>
-
-<p>When creating a new cell, three things are required in the
-constructor, a value (user object), a geometry and a style. We will now
-explore these 3 concepts before returning to the cell.</p>
-
-<h4><a id="styles"></a>Styles</h4>
-
-<p>The concept of styles and stylesheets in conceptually similar to
-CSS stylesheets, though note that CSS are actually used in mxGraph, but
-only to affect global styles in the DOM of the HTML page. Open up the
-util.mxConstants.js file in your editor and search for the first match
-on &ldquo;STYLE_&rdquo;. If you scroll down you will see a large number
-of strings defined for all the various styles available with this
-prefix. Some of styles apply to vertices, some to edges and some to
-both. As you can see, these define visual attributes on the element they
-act upon.</p>
-
-<p>The mxStylesheet holds one object, styles, which is a hashtable
-mapping style names to an array of styles:</p>
-
-<p><img src="images/mx_man_styles.png" name="graphics5"/><br/>
-<em>Style arrays within the styles collection</em></p>
-<br/>
-
-<p>In the above image the blue box represents the styles hashtable
-in mxStyleSheet. The string 'defaultVertex' is the key to an array of
-string/value pairs, which are the actual styles. Note that mxGraph
-creates two default styles, one for vertices and one for edges. If you
-look back to the helloworld example, no style was passed into the
-optional style parameter of insertVertex or insertEdge. In this case the
-default style would be used for those cells.</p>
-
-<h5><a id="setting_cell_style"></a>Setting the Style of a Cell</h5>
-
-<p>If you wanted to specify a style other than the default for a
-cell, you must pass that new style either to the cell when it is created
-(mxGraph's insertVertex and insertEdge both have an optional parameter
-for this) or pass that style to the cell using model.setStyle().</p>
-
-<p>The style that you pass has the form stylename. ,note that the
-stylenames and key/value pairs may be in any order. Below are examples
-to demonstrate this concept, adapting the insertVertex call we saw in
-helloworld:</p>
-
-<ol>
-	<li>
-	<p>A new style called 'ROUNDED' has been created, to apply this to
-	a vertex:</p>
-	<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'ROUNDED');</pre>
-	</li>
-
-	<li>
-	<p>To create a new vertex with the ROUNDED style, overriding the
-	stroke and fill colors:</p>
-	<pre>var v1 = graph.insertVertex(parent, null, 'Hello',  20, 20, 80, 30, 'ROUNDED;strokeColor=red;fillColor=green');</pre>
-	</li>
-
-	<li>
-	<p>To create a new vertex with no global style, but with local
-	stroke and fill colors:</p>
-	<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, ';strokeColor=red;fillColor=green');</pre>
-	</li>
-	<li>
-	<p>To create a vertex that uses the defaultVertex style, but a
-	local value of the fill color:</p>
-	<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'defaultVertex;fillColor=blue');</pre>
-	</li>
-</ol>
-
-<br/>
-<p>Note that default style must be explicitly named in this case,
-missing the style out sets no global style on the cell when the
-semi-colon starts the string. If the string starts with no semi-colon,
-the default style is used.</p>
-
-<p>Again, the mxGraph class provides utility functions that form the
-core API for accessing and changing the styles of cells:</p>
-
-<div id="coreapi">
-<p><strong>Core API functions:</strong></p>
-
-<ul>
-<li>
-<strong>mxGraph.setCellStyle(style, cells)</strong> &ndash; Sets
-the style for the array of cells, encapsulated in a begin/end update.
-</li>
-<li>
-<strong>mxGraph.getCellStyle(cell)</strong> &ndash; Returns the
-style for the specified cell, merging the styles from any local style
-and the default style for that cell type.
-</li>
-</ul>
-</div>
-
-<h5><a id="new_global_style"></a>Creating a New Global Style</h5>
-<p>To create the ROUNDED global style described above, you can
-follow this template to create a style and register it with
-mxStyleSheet:</p>
-
-<pre>
-let style = {};
-style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
-style[mxConstants.STYLE_OPACITY] = 50;
-style[mxConstants.STYLE_FONTCOLOR]= '#774400';
-graph.getStylesheet().putCellStyle('ROUNDED',style);
-</pre>
-
-<h4><a id="geometry"></a>Geometry</h4>
-
-<p>In the helloworld example we saw the position and size of the
-vertices passed into the insertVertex function. The coordinate system in
-JavaScript is x is positive to the right and y is positive downwards,
-and in terms of the graph, the positioning is absolute to the container
-within which the mxGraph is placed.</p>
-
-<p>The reason for a separate mxGeometry class, as opposed to simply
-having the mxRectangle class store this information, is that the edges
-also have geometry information.</p>
-
-<p>The width and height values are ignored for edges and the x and y
-values relate to the positioning of the edge label. In addition, edges
-have the concept of control points. These are intermediate points along
-the edge that the edge is drawn as passing through. The use of control
-points is sometimes referred to as <strong>edge routing</strong>.</p>
-
-<p><img src="images/mx_man_edge_routing.png" name="ill_edge_routing"/><br/>
-<em>An edge routed by 2 control points</em></p>
-
-<p>There are two more important additional concepts in geometry,
-relative positioning and offsets</p>
-
-<h5><a id="relative_positioning"></a>Relative Positioning</h5>
-
-<p>By default, the x and y position of a vertex is the offset of the
-top left point of the bounding rectangle of the parent to the top left
-point of the bounding rectangle of the cell itself. The concept of
-parents and groups is discussed later in this chapter, but without going
-into too much detail, if a cell does not have cell parent, the graph
-container is its parent for positioning purposes.</p>
-
-
-<p><img src="images/mx_man_non_relative_pos.png"
-	name="ill_non_realtive_pos"/><br/>
-<em>Non-relative vertex positioning</em></p>
-<br/>
-
-
-<p>For an edge, in non-relative mode, which is the default mode, the
-edge label position is the absolute offset from the graph origin.</p>
-
-
-<p><img src="images/mx_man_non_realtive_edge_pos.png"
-	name="ill_non_rel_edge_pos"/><br/>
-<em>Non-relative edge label positioning</em></p>
-<br/>
-
-
-<p>For vertices in relative mode, (x,y) is the proportion along the
-parent cell's (width, height) where the cell's origin lies. (0,0) is the
-same origin as the parent, (1,1) places the origin at the bottom right
-corner of the parent. The same relative positioning extends below 0 and
-above 1 for both dimensions. This positioning is useful for keeping
-child cells fixed relative to the overall parent cell size.</p>
-
-<p><img src="images/mx_man_rel_vert_pos.png" name="rel_vert_pos"/><br/>
-<em>Relative vertex positions</em></p>
-<br/>
-
-<p>Lastly, edge labels in relative mode are palced based on the
-positioning from the center of the edge. The x-coordinate is the
-relative distance from the source end of the edge, at -1, to the target
-end of the edge, at 1. The y co-ordinate is the pixel offset orthogonal
-from the edge. The diagram below shows the values of x,y for various
-edge labels in relative mode. Note that for a straight edge, the
-calculations are simple. For edges with multiple control points, the
-edge has to be traced along its segments (a segment being the line
-between end points and/or control points) to find the correct distance
-along the edge. The y value is the orthogonal offset from that segment.</p>
-
-<p>Switching relative positioning on for edge labels is a common
-preference for applications. Navigate to the mxGraph.insertEdge()
-function in mxGraph, you will see this calls createEdge(). In
-createEdge() the geometry is set relative for every edge created using
-this prototype. This is partly the reason for the amount of helper
-functions in mxGraph, they enable easy changing of the default
-behaviour. You should try to use the mxGraph class API as much as
-possible to provide this benefit in your applications.</p>
-
-<h5><a id="offsets"></a>Offsets</h5>
-
-<p>The offset field in mxGeometry is an absolute x,y offset applied
-to the cell <strong>label</strong>. In the case of edge labels, the
-offset is always applied after the edge label has been calculated
-according to the relative flag in the above section.</p>
-
-<div id="coreapi">
-<p><strong>Core API functions:</strong></p>
-
-<ul><li><strong>mxGraph.resizeCell(cell, bounds)</strong> &ndash; Resizes
-the specified cell to the specified bounds, within a begin/end update
-call.</li>
-<li><strong>mxGraph.resizeCells(cells, bounds)</strong> &ndash;
-Resizes each of the cells in the cells array to the corresponding entry
-in the bounds array, within a begin/end update call.</li>
-</ul>
-</div>
-
-<h4><a id="user_objects"></a>User Objects</h4>
-
-<p>The User object is what gives mxGraph diagrams a context, it
-stores the business logic associated with a visual cell. In the
-HelloWorld example the user object has just been a string, in this case
-it simply represents the label that will be displayed for that cell. In
-more complex applications, these user objects will be objects instead.
-Some attribute of that object will generally be the label that the
-visual cell will display, the rest of the object describes logic
-relating to the application domain.</p>
-
-<p>Using the example of a simple workflow or process application,
-say we have the graph below (<a
-	href="http://www.jgraph.com/demo/mxgraph/editors/workfloweditor.html">this
-example is available online</a>, select the Swimlanes example from the tasks
-window):</p>
-
-<p><img src="images/mx_man_simple_workflow.png"
-	name="ill_simple_workflow"/><br/>
-<em>A simple workflow</em></p>
-<br/>
-
-<p>Typically, this workflow will exist on some application server
-and/or database. The browser user connects to that server, or some
-front-end server linked to the application server and the user's web
-application requests the &ldquo;order&rdquo; workflow. The server
-obtains the data of that workflow and transmits it to the client.</p>
-
-<p>mxGraph supports the process of populating the model on the
-server-side and transmitting to the client, and back again. See the
-later chapter on &ldquo;I/O and Server Communication&rdquo;.</p>
-
-<p>The data transmitted will be both the visual model (the diagram)
-as well as the business logic (mostly contained in the user objects).
-The client will initially show the diagram above. If the user has
-permission to edit this workflow they will normally be able to do two
-things, 1) edit the diagram, add and remove vertices, as well as
-changing the connections, and 2) edit the user objects of the cells
-(vertices and/or edges).</p>
-
-<p>In the online demo, if you right click and select properties of
-the &ldquo;Check Inventory&rdquo; diamond you will see this dialog:</p>
-
-<p><img src="images/mx_man_vertex_props.png" name="ill_vertex_props"/><br/>
-<em>The properties of a vertex</em></p>
-<br/>
-
-<p>These properties show the geometry, label, ID etc, but a dialog
-could just as easily show the user object of the cell. There might be a
-reference to some process on the workflow engine as to how the inventory
-is actually checked. This might be an application specific mechanism for
-both the server and client to assign some identification to remote
-method calls. Another value might be the type of object that process
-returned, maybe a boolean or an integer to indicate stock level in this
-case. Given that return type, it is possible to enforce constraints with
-the diagram and provide visual alerts of if, say, the outgoing edges
-decision check does not correspond to the return type of the vertex.</p>
-
-<p>Next, as an example, the user objects of the outgoing edges might
-contain a label and a boolean state. Again, the mxGraph-based editor
-might provide the means to alter the boolean value. On the server, when
-executing the process, it might follow the edges that correspond to the
-boolean value returned by the decision node.</p>
-
-<p>Keep in mind that the above example is very domain specific, it
-is there to explain how the user object maps to the business logic of
-the application. It visualizes how mxGraph creates what we term a <strong>contextual
-graph</strong>. The context is formed by the connections between vertices and the
-business logic stored within the user objects. A typical application
-receives the visual and business logic from a sever, may allow editing
-of both, then transmits both back to the server for persistence and/or
-execution.</p>
-
-<h4><a id="cell_types"></a>Cell Types</h4>
-<p>As described previously, mxGraph is the primary API for using
-this library and the same concept applies to cells. One basic state of
-the cell not exposed on the graph is whether a cell is a vertex or an
-edge, this call be performed on the cell or on the model.</p>
-
-<p>There are two boolean flags on mxCell, vertex and edge, and the
-helper methods set one of these to true when the cell is created.
-isVertex(), isEdge() on mxIGraphModel are what the model uses to
-determine a cell's type, there are not separate objects for either type.
-Technically, it is possible to switch the type of a cell at runtime, but
-take care to invalidate the cell state (see later section) after
-changing the type. Also, be aware that the geometry object variable
-means different things to vertices and edges. Generally, it is not
-recommended to change a cell type at runtime.</p>
-
-<h3><a id="group_structure"></a>Group Structure</h3>
-<p>Grouping, within mxGraph, is the concept of logically associating
-cells with one another. This is commonly referred to as the concept of
-sub-graphs in many graph toolkits. Grouping involves one or more
-vertices or edges becoming children of a parent vertex or edge (usually
-a vertex) in the graph model data structure. Grouping allows mxGraph to
-provide a number of useful features:</p>
-
-<ul>
-	<li>Sub-graphs, the concept of a logically separate graph that is
-	displayed in the higher level graph as a cell per sub-graph.</li>
-
-	<li>Expanding and collapsing. Collapsing is the ability to replace
-	a collection of grouped cells visually with just their parent cell.
-	Expanding is the reverse of this. This behaviour can be seen by
-	clicking the small &ldquo;-&rdquo; in the top left corner of the group
-	cells of the swimlanes example in the <a
-		href="http://www.jgraph.com/demo/mxgraph/editors/workfloweditor.html">online
-	workfloweditor</a> example. This is described in the C<em>omplexity
-	Management</em> section below.</li>
-
-	<li>Layering. Layering is the concept of assigning cells to a
-	particular z-order layer within the graph display.</li>
-
-	<li>Drill down, step up. These concepts allow sub-graphs to be
-	visualized and edited as if they are a complete graph. In the <em>User
-	Objects</em> section we saw the &ldquo;check inventory&rdquo; vertex as a
-	single cell. Take, for example, the case where a developer is
-	describing each of the vertices in the process as the software
-	processes that perform the task. The application might have an option
-	to drill down into the check inventory vertex. This would result in a
-	new graph appearing that describes in detail how exactly the system
-	checks the inventory. The graph might have the title of the parent
-	&ldquo;check inventory&rdquo; vertex to indicate it is a child, as well
-	as the option to step-up back to the next level up.</li>
-</ul>
-
-<p>In grouping, cells are assigned a parent cell. In the simplest
-case, all cells have the default parent as their parent. The default
-parent is an invisible cell with the same bounds as the graph. This is
-the cell returned by graph.getDefaultParent() in the helloworld example.
-The x,y position of a vertex is its position relative to its parent, so
-in the case of default grouping (all cells sharing the default parent)
-the cell positioning is also the absolute co-ordinates on the graph
-component. In the case all cells being added to the default root, the
-group structure logically looks like, in the case of the helloworld
-example, the diagram below.</p>
-
-<p>Note the addition of the Layer 0 cell, this is the default
-indirection in the group structure that allows layer changes with the
-requirement of additional cells. We include it below for correctness,
-but in later group diagrams it will be omitted.</p>
-
-
-<p><a id="ill_mx_man_hello_struct"><img src="images/mx_man_hello_struct.png"
-	WIDTH=441 HEIGHT=241 BORDER=0></a><br/>
-<em>The group structure of the helloworld example</em></p>
-<br/>
-
-<p>Also, note that the position of the edge label (x,y in geometry)
-is relative to the parent cell.</p>
-
-<p>If we go back to the simple workflow example in the User Objects
-section, we can see what grouping might look like visually. In the
-example the group cells represent people and the child vertices
-represent tasks assigned to those people. In this example the logical
-group structure looks like this:</p>
-
-
-<p><img src="images/mx_man_log_group_struct.png"
-	name="ill_mx_man_log_group_struct"/><br/>
-<em>The logical group structure of the workflow example</em></p>
-<br/>
-
-<p>The workflow action vertices are the yellow children and the
-swimlane group vertices are marked blue.</p>
-
-<p>Inserting cells into the group structure is achieved using the
-parent parameter of the insertVertex and insertEdge functions on the
-mxGraph class. These functions set the parent cell on the child
-accordingly and, importantly, informs the parent cell of its new child.</p>
-
-<p>Altering the group structure is performed via the
-mxGraph.groupCells() and mxGraph.ungroupCells() functions.</p>
-
-<div id="coreapi">
-<p><strong>Core API functions:</strong></p>
-
-<ul><li><strong>mxGraph.groupCells(group, border, cells)</strong> &ndash;
-Adds the specified cells to the specified group, within a begin/end
-update</li>
-<li><strong>mxGraph.ungroupCells(cells)</strong> &ndash; Removes the
-specified cells from their parent and adds them to their parent's
-parent. Any group empty after the operation are deleted. The operation
-occurs within a begin/end update.</li>
-</ul>
-</div>
-
-<h3><a id="complexity_management"></a>Complexity Management</h3>
-
-<p>There are two primary reasons to control the number of cells
-displayed at any one time. The first is performance, drawing more and
-more cells will reach performance usability limits at some point on any
-platform. The second reason is ease of use, a human can only comprehend
-a certain amount of information. All of the concepts associated with
-grouping, listed above, can be used to reduce the complexity of
-information on the screen for the user.</p>
-
-<h4><a id="folding"></a>Folding</h4>
-
-<p>Folding is the collective term we use for expanding and
-collapsing groups. We say a cell is folded by making it's child vertices
-invisible. There are a number of functions relating to this feature:</p>
-
-<div id="coreapi">
-<p><strong>Core API function:</strong></p>
-
-<ul><li><strong>mxGraph.foldCells(collapse, recurse, cells)</strong>
-&ndash; States the collapsed state of the specificed cells, within a
-begin/end update.</li></ul>
-</div>
-
-<p><strong>Folding related functions:</strong></p>
-
-<p><strong>mxGraph.isCellFoldable(cell, collapse)</strong> &ndash;
-By default true for cells with children.</p>
-<p><strong>mxGraph.isCellCollapsed(cell)</strong> &ndash; Returns
-the folded state of the cell</p>
 
-<p>When a group cell is collapsed, three things occur by default:</p>
 
-<ul>
-	<li>The children of that cell become invisible.</li>
-	<li>The group bounds of the group cell is used. Within mxGeometry
-	there is a alternativeBounds field and in groups cells, by default
-	store a separate bounds for their collapsed and expanded states. The
-	switch between these instances is invoked by mxGraph.swapBounds() and
-	this is handled for you within a foldCells() call. This allows
-	collapsed groups to be resized whilst when expanded again the size
-	looks correct using the pre-collapsed size.</li>
-	<li>Edge promotion occurs, by default. Edge promotion means
-	displaying edges that connect to children within the collapsed group
-	that also connect to cells outside of the collapsed group, by making
-	them appear to connect to the collapsed parent.</li>
-</ul>
-
-
-<p><img src="images/mx_man_expand_swim.png"
-	name="ill_mx_man_expand_swim"/><br/>
-<em>Expanded swimlane</em></p>
-
-
-<p><img src="images/mx_man_collapse_swim.png"
-	name="ill_mx_man_collapse_swim"/><br/>
-<em>Collapsed Swimlane</em></p>
-
-<p>The above two images demonstrate these three concepts. In its
-expanded state the upper group cell displays a small box in the top left
-hand corner with a &ldquo;-&rdquo; character inside. This indicates that
-clicking on this box collapses the group cell. Doing this we get the
-bottom image where the group cell takes on its collapsed size. Child
-vertices and edge that do not leave the group cell are made invisible.
-Finally, edges that exit the group cell are promoted to appear to be
-connected to the collapsed group cell. Clicking on the &ldquo;+&rdquo;
-character that now appears within the box expands the group cell and
-brings it back to its original state of the top image.</p>
-
-<p>Using the mxGraph.foldCells() function, you can achieve the same
-result programmatically as clicking on the expand/collapse symbols. One
-common usage of this is when the application zooms out a specific
-amount, clusters of cells are grouped and the grouped cell collapsed
-(very often without the &ldquo;-&rdquo; box since the application is
-controlling the folding). This way fewer, larger cells are visible to
-the user, each one representing their children cells logically. You
-might then provide a mechanism to zoom into a group, which expands it in
-the process. You might also provide drill-down/step-up, explained next.</p>
-
-<h4><a id="sub_graph_drilling"></a>Sub-Graphs, Drill-Down /
-Step-Up</h4>
-
-<p>Sometimes, as an alternative to expand/collapse, or possibly in
-combination with it, your graph will be composed of a number of graphs,
-nested into a hierarchy. Below we see a simple example:</p>
-
-
-<p><img src="images/mx_man_drill_down.png"
-	name="ill_mx_man_drill_down"/><br/>
-<em>An example top level workflow</em></p>
-<br/>
-
-<p>This simple workflow consists of three high level steps.
-Obviously, the individual steps contain a number of sub-steps and we
-will look at a sub-graph of the <em>Solve Bug</em> cell.</p>
-
-<p>Under the <em>Solve Bug</em> vertex we have created a number of
-children to represent the process of solving a bug in more detail, in
-this case the process of solving a bug on the <a
-	href="http://en.wikipedia.org/wiki/Starship_Enterprise">Starship
-Enterprise</a>.</p>
-
-<p>In this example, which uses the GraphEditor example, the menu
-option shown selected in the above image invokes
-mxGraph.enterGroup(cell), which is one of the pair of core API functions
-for sub-graphs.</p>
-
-<div id="coreapi">
-<p><strong>Core API functions:</strong></p>
-
-<ul><li><strong>mxGraph.enterGroup(cell)</strong> &ndash; Makes the
-specified cell the new root of the display area.</li>
-<li><strong>mxGraph.exitGroup()</strong> - Makes the parent of the
-current root cell, if any, the new root cell.</li>
-<li><strong>mxGraph.home()</strong> - Exits all groups, making the
-default parent the root cell.</li>
-</ul>
-</div>
-
-<p>The root cell of the graph has been, up to now, the default
-parent vertex to all first-level cells. Using these functions you can
-make any group cell in the group structure the root cell, so that the
-children of that parent appear in the display as the complete graph.</p>
-
-<p><img src="images/mx_man_drilling.png" name="ill_mx_man_drilling"/><br/>
-<em>Result of drilling down into the Solve Bug vertex</em></p>
-
-<P>The same graph expanded using folding instead looks like:</p>
-
-<p><img src="images/mx_man_top_level.png" name="ill_mx_mantop_level"
-        WIDTH=695 HEIGHT=227 BORDER=0></p>
-<p>Exiting the group using the <em>shape-&gt;exit group</em> option,
-which invokes mxGraph.exitGroup, brings you back to the original 3
-vertex top level graph.</p>
-
-<h4><a id="layer_filter"></a>Layering and Filtering</h4>
-
-<p>In mxGraph, like many graphical applications, there is the
-concept of z-order. That is, the order of objects as you look into the
-screen direction. Objects can be behind or in front of other objects and
-if they overlap and are opaque then the back-most object will be
-partially or complete obscured. Look back to the <a href="#ill_mx_man_hello_struct">
-graph structure of HelloWorld illustration</a> above. Children cells are stored under
-parents in a deterministic order (by default the order in which you add
-them).</p>
-
-<p>If we move the cells in the HelloWorld example we see the
-following result:</p>
-
-<p><img src="images/mx_man_overlap.png" name="ill_mx_man_overlap"/><br/>
-<em>Overlapped vertices</em></p>
-
-<p>It can be seen that the <em>World</em> vertex is in front of the
-<em>Hello</em> vertex. This is because the <em>World</em> vertex has a
-higher child index than the <em>Hello</em> vertex, at positions 1 and 0
-respectively in the ordered collection that holds the children of the
-root cell.</p>
-
-<p>To change order we use mxGraph.orderCells.</p>
-
-<div id="coreapi">
-<p><strong>Core API function:</strong></p>
-
-<ul><li><strong>mxGraph.orderCells(back, cells)</strong> &ndash; Moves
-the array of cells to the front or back of their siblings, depending on
-the flag, within a begin/end update.</li></ul>
-</div>
-
-<p>A sibling cell in mxGraph is any cell that shares the same
-parent. So by invoking this on the <em>Hello</em> vertex it would then
-overlap the <em>World</em> Vertex.</p>
-
-<p>Ordering and grouping can be extended to form logically layered
-groups. The cells are drawn via a depth-first search. Take the
-HelloWorld example again and imagine that both the <em>Hello</em> and <em>World
-</em>vertices have some hierarchy of children underneath them. The <em>Hello</em>
-vertex and all of its children will be drawn before the <em>World</em>
-vertex or any of its children. If <em>Hello</em> and <em>World</em> were
-invisible group cells you then have two hierarchies of cells, one being
-drawn entirely before the other. You can also switch the order of the
-hierarchies by simply switching the order of the invisible group cells.</p>
-
-<p>The concept of layering is demonstrated in the layers.html
-example. Here buttons are used to set the visibility of group layer
-cells. This example ties very closely into the concept of filtering.</p>
-
-<p>In filtering cells with some particular attribute are displayed.
-One option to provide filtering functionality is to check some state
-before rendering the cells. Another method, if the filtering conditions
-are simple and known in advance, is to assign filterable cells by
-groups. Making the groups visible and invisible performs this filtering
-operation.</p>
-
-<br/>
+<!-- ================================================================================= -->
+<!-- in 3: everything has been integrated -->
+<!-- ================================================================================= -->
 
-<hr size="1">
-&copy; 2006-2017 by JGraph Ltd.
-</body>
-</html>


Test patch:
diff --git a/packages/core/__tests__/view/plugins/index.test.ts b/packages/core/__tests__/view/plugins/index.test.ts
new file mode 100644
index 000000000..8fcd861fa
--- /dev/null
+++ b/packages/core/__tests__/view/plugins/index.test.ts
@@ -0,0 +1,40 @@
+/*
+Copyright 2022-present The maxGraph project Contributors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { describe, expect, test } from '@jest/globals';
+import { getDefaultPlugins } from '../../../src';
+
+describe('getDefaultPlugins', () => {
+  test('returns a new array each time it is called', () => {
+    const plugins1 = getDefaultPlugins();
+    const plugins2 = getDefaultPlugins();
+    expect(plugins1).not.toBe(plugins2);
+    expect(plugins1).toEqual(plugins2);
+  });
+
+  test('returns an array with the correct length', () => {
+    const plugins = getDefaultPlugins();
+    // detect any changes in default plugins, order does not matter
+    expect(plugins).toHaveLength(7);
+  });
+
+  test('returns an array containing only functions', () => {
+    const plugins = getDefaultPlugins();
+    plugins.forEach((plugin) => {
+      expect(typeof plugin).toBe('function');
+    });
+  });
+});