Skip to content

Releases: maxGraph/maxGraph

0.21.0

23 Jul 17:09
v0.21.0
e16e84b
Compare
Choose a tag to compare

Version 0.21.0 released on 2025-07-23.

⚡ This release improves Webpack and Node.js compatibility, removes legacy code, and slightly reduces bundle size. ⚡

Resources

Breaking changes

Important

These changes might require updates in your codebase if you relied on internal behaviors or legacy APIs.
See the issues and pull requests referenced below for migration help.

fit method moved to FitPlugin

The AbstractGraph.fit method and the minFitScale and maxFitScale properties have been moved to the FitPlugin.
This helps reduce the size of the base graph when the plugin is not used.

Tip

The fit method now accepts a single options parameter to reduce boilerplate. See #734.

Removal of Dictionary class

The Dictionary class has been removed. You can now use the native JavaScript Map object, which is available in all environments supported by maxGraph.
This class was originally introduced in mxGraph to support old browsers lacking Map.

If your code used Dictionary, replace it with Map.

Note

This change slightly reduces the bundle size. See #857.

Rounded shapes: consistent arcSize rendering

The way arcSize is computed for rounded shapes is now consistent across all shape types and matches the behavior of mxGraph.

Important

If you were relying on the previous behavior (especially for edges), you may need to multiply your arcSize value by 2 to keep the same rendering.

TypeScript-specific changes

  • AbstractGraph.getPlugin() now explicitly returns undefined if the plugin is not found.
    You must handle the undefined case in your code.

  • Improved return types for EditorToolbar methods:

    • addPrototype() now returns HTMLImageElement (was HTMLImageElement | HTMLButtonElement)
    • addCombo() now returns HTMLSelectElement (was HTMLElement)

Highlights

🔍 Search bar on the documentation website

You can now quickly search the documentation!
The new search bar uses a local lunr-search index for fast results.

website_search_20250722.mp4

Note

For more details, see #853

🛠️ Webpack configuration simplified + Node.js ESM support

maxGraph can now be used with Webpack and Node.js ESM without extra config 🎉

Before this update, using maxGraph with Webpack required a workaround like this:

module.exports = {
  module: {
    rules: [
      {
        test: /\.m?js/,
        resolve: {
          fullySpecified: false,
        },
      },
    ],
  },
};

This was needed because import paths in maxGraph were missing the .js extension.
This also caused issues when importing maxGraph in ESM contexts with Node.js — no workaround was possible in that case.

These issues are now fixed ✅

Note

See #827 (issue) and #867 (fix)

📦 Bundle size reduction

Small but measurable size gains:

  • -0.7 kB: removal of the Dictionary class and internal refactoring (#857)
  • -1.0 kB: when not using the FitPlugin, due to fit logic moving out of BaseGraph (#734)

What's Changed

🎉 New Features

  • feat: let choose the implementation of ConstraintHandler by @tbouffard in #838
  • feat(type): allow optional for parameters of AbstractGraph.addCells by @tbouffard in #847
  • feat: add search to website by @tbouffard in #853
  • feat: ease webpack configuration and add support Node ESM by @tbouffard in #867

🐛 Bug Fixes

  • fix(FitPlugin): handle edge cases in fitCenter calculation by @tbouffard in #831
  • fix: correct Editor cycleAttribute and swapStyles methods by @tbouffard in #871
  • fix!: improve the robustness of codecs by @tbouffard in #872
  • fix: consistently compute the arcSize for edges and vertices by @tbouffard in #884

📝 Documentation

⚙️ Refactor

  • refactor!: move AbstractGraph.fit to FitPlugin by @tbouffard in #734
  • refactor: migrate the Orthogonal story to TypeScript by @tbouffard in #835
  • refactor: migrate the FixedPoints story to TypeScript by @tbouffard in #839
  • refactor(type)!: make AbstractGraph.getPlugin return T | undefined by @tbouffard in #842
  • refactor: increase usage of the MouseListenerSet interface by @tbouffard in #848
  • refactor(stories): remove reference to Graph handler by @tbouffard in #849
  • refactor!: remove Dictionary and use Map instead by @tbouffard in #857
  • refactor: migrate the DragSource story to TypeScript by @tbouffard in #860
  • refactor: remove reference to legacy insert cells methods by @tbouffard in #876
  • refactor: migrate the Thread story to TypeScript by @tbouffard in #877
  • refactor: migrate the Stylesheet story to TypeScript by @tbouffard in #878

🛠 Chore

Full Changelog: v0.20.0...v0.21.0

0.20.0

16 May 18:39
v0.20.0
0a18ab1
Compare
Choose a tag to compare

Version 0.20.0 released on 2025-05-16.

This new version improves registry consistency, removes legacy enums, supports CommonJS, and enables tree-shaking optimizations.

Resources

Breaking changes

Important

Several breaking changes are introduced to align internal APIs, improve tree-shaking, and reduce complexity. These changes mostly affect users customizing the graph.

Unified Registry API for Style Elements

All style-related registries now implement the same Registry interface. This ensures a consistent developer experience and makes it easier to use or extend them. 🛠️

  • All registries now expose the same methods: add, get, getName, and clear.
  • Their internal storage is no longer directly accessible.

Note

If you were using custom style registration, you'll likely need to update your code.

Renamed / Replaced Registries

  • MarkerShapeEdgeMarkerRegistry
  • Shapes are now registered via ShapeRegistry (not CellRenderer anymore)
  • StyleRegistry has been removed. Use EdgeStyleRegistry and PerimeterRegistry instead.

Code migration examples

// Edge Marker
- MarkerShape.addMarker('oval', EdgeMarker.oval);
+ EdgeMarkerRegistry.add('oval', EdgeMarker.oval);

// Perimeter
- StyleRegistry.putValue('hexagonPerimeter', Perimeter.HexagonPerimeter);
+ PerimeterRegistry.add('hexagonPerimeter', Perimeter.HexagonPerimeter);

// Shape
- CellRenderer.registerShape('rhombus', RhombusShape);
+ ShapeRegistry.add('rhombus', RhombusShape);

// Stencil Shape
- StencilShapeRegistry.addStencil('my-stencil', new StencilShape(shape));
+ StencilShapeRegistry.add('my-stencil', new StencilShape(shape));

Special case: EdgeStyleRegistry

In addition to method renaming, EdgeStyleRegistry.add() now takes an extra options object to categorize the style. This avoids hardcoded behavior and improves flexibility. 🧩

- StyleRegistry.putValue('elbowEdgeStyle', EdgeStyle.ElbowConnector);
+ EdgeStyleRegistry.add('elbowEdgeStyle', EdgeStyle.ElbowConnector, { handlerKind: 'elbow', isOrthogonal: true });

This change supports internal refactors (see Highlights) and better extension patterns.

Element retrieval

For most users, no impact is expected. Retrieval methods are typically used in custom extensions only.

// Edge Marker
- MarkerShape.markers['oval'];
+ EdgeMarkerRegistry.get('oval');

// Edge Style
- StyleRegistry.getValue('elbowEdgeStyle');
+ EdgeStyleRegistry.get('elbowEdgeStyle');

// Perimeter
- StyleRegistry.getValue('hexagonPerimeter');
+ PerimeterRegistry.get('hexagonPerimeter');

// Shape
- CellRenderer.defaultShapes['rhombus'];
+ ShapeRegistry.get('rhombus');

// Stencil Shape
- StencilShapeRegistry.getStencil('my-stencil')
+ StencilShapeRegistry.get('my-stencil')

Note

EdgeMarkerRegistry still exposes its specific createMarker method unchanged. 🎯

Enum Removal and Renaming

All remaining enums have been removed. They caused unnecessary complexity and weren’t actually used to list values. 🧹

Use the corresponding string-based types instead:

Removed Enum Use this instead
constants.ALIGN AlignValue, VAlignValue
constants.DIALECT DialectValue
constants.ARROW ArrowValue
constants.DIRECTION DirectionValue
constants.EDGESTYLE EdgeStyleValue
constants.ELBOW ElbowValue
constants.PERIMETER PerimeterValue
constants.SHAPE ShapeValue
constants.TEXT_DIRECTION TextDirectionValue
constants.RENDERING_HINT No replacement

Other specific changes:

  • constants.NODETYPE → replaced by value object constants.NODE_TYPE

    • DOCUMENTTYPEDOCUMENT_TYPE
  • constants.FONT → replaced by constants.FONT_STYLE_FLAG

  • constants.CURSOR → values moved to:

    • ConnectionHandler
    • EdgeHandlerConfig
    • HandleConfig
    • VertexHandlerConfig

Also, constants.DIRECTION_MASK is now read-only. 🔒

Highlights

CommonJS Support for Node & Test Environments

maxGraph now ships with dual ESM and CommonJS builds. 🎉

Historically, only ESM was supported, as maxGraph was mainly used in browser-based applications with bundlers. But some new use cases made CJS support necessary:

Why it's useful

  • Testing (e.g. with Jest): CJS is default in many test setups. Previously, you had to:

    • Add extra config just to run tests.
    • Migrate whole test suites to ESM - a massive task in large apps.
    • Replace CJS-only dependencies.

Now, maxGraph works in Jest without forcing ESM migration. ✅

  • Node-based (headless) apps: Like SVG export use cases (see #761). Some apps still use CommonJS, and maxGraph was previously unusable in those.

Now it just works. 😎

Tip

Two new examples were added to show CommonJS usage:

  • TypeScript: Use with Jest + ts-jest
  • JavaScript: Run headless in Node.js using jsdom, export XML and SVG

Tree-shaking Improvements

Tree-shaking is now much more effective thanks to multiple internal refactors. 🧼

Main improvement

EdgeStyle implementations are no longer hardcoded throughout the codebase. Instead, the code only relies on what is dynamically registered with configuration (see Breaking changes).

This allows bundlers to remove unused styles - big win on size! 📦

Example size comparison

Examples from maxGraph repo

Even with no changes in your app, enum removal already saves 3–5 kB. If your app avoids most EdgeStyles, savings can go up to 17 kB. 📉

Note

See #806 for enum removal, and #809 for EdgeStyle tree-shaking.

Example v0.19.0 enums removal EdgeStyles tree-shaking v0.20.0
js-example 475.30 kB 469.80 kB 470.56 kB 467.59 kB
js-example-selected-features 415.10 kB 410.18 kB 393.27 kB 390.40 kB
js-example-without-default 347.33 kB 342.69 kB 325.79 kB 325.44 kB
ts-example 438.64 kB 434.80 kB 435.46 kB 435.23 kB
ts-example-selected-features 380.70 kB 377.11 kB 369.30 kB 369.09 kB
ts-example-without-default 329.90 kB 326.43 kB 309.40 kB 309.18 kB

Warning

The 3 kB drop in js-example* is from button simplification in the examples, not related to maxGraph itself (see #822).

Examples from maxgraph-integration-examples repo

All share common Graph config and use EdgeStyle.OrthConnector. ⚙️

Example 0.19.0 0.20.0
farm 406.09 kB (2 chunks) 404.25 kB (5 chunks)
lit (vite) 402.19 kB 389.92 kB
parcel 506.70 kB 500.98 kB
rollup 380.44 kB 369.02 kB
rsbuild 361.94 kB 347.19 kB
vite 383.50 kB 371.86 kB

What's Changed

🎉 New Features

🐛 Bug Fixes

  • fix: correctly set italic in styleUtils.getSizeForString by @tbouffard in #805
  • fix: ensure mdx pages can be displayed by storybook by @tbouffard in #814

📝 Documentation

⚙️ Refactor

Read more

0.19.0

30 Apr 06:32
v0.19.0
7cb8da3
Compare
Choose a tag to compare

This new version improves tree-shaking for EdgeStyle and Perimeter, updates the documentation, and fixes bugs.

Resources

Breaking changes

Warning

These changes only impact advanced use cases where edge styles or perimeters are customized directly.

  • EdgeStyle is now a namespace
    It used to be a class with static properties. You could technically mutate it to add or override values — but that’s no longer possible.
    If you were doing this, you now need to define your own EdgeStyle implementation and register it explicitly.

  • Perimeter is now a namespace
    Previously a plain object, Perimeter could be mutated too. Not anymore.
    Like with EdgeStyle, create your own perimeter implementation and register it if needed.

Highlights

📦 Tree-shaking improvements for EdgeStyle and Perimeter

Until now, all edge styles and perimeters were bundled into your app even if you only used a few of them. Why? Because EdgeStyle and Perimeter were objects that referenced everything, which prevented bundlers from optimizing properly.

Here’s what changed:

  • EdgeStyle is now a namespace. This allows bundlers to drop unused edge styles and only keep what’s actually registered and used via StyleRegistry.
  • Perimeter is now also a namespace, instead of a value object. This improves bundling behavior, especially for bundlers that couldn’t previously optimize it (Webpack, Vite when misconfigured, etc.).

Note

Bundlers like Rollup already did a great job here. But now all bundlers should behave nicely 🎉

📉 Impact on bundle size

Depending on what edge styles and perimeters your app uses, and the bundler you're using, bundle size can shrink by 1 to 5 kB.

🔍 A few things to keep in mind

  • The EdgeStyle change currently has limited effect, since many built-in styles are still referenced directly in the codebase. This will improve in the future (see #767).
  • The Perimeter change doesn’t impact apps built with Rollup or Vite (which uses Rollup internally), since they already optimized this before. But it’s now cleaner and safer across the board.

Here’s a concrete example of what Rollup was doing with the old object-based Perimeter (with minification disabled):

const RectanglePerimeter = ...
const EllipsePerimeter = ...

const Perimeter = {
  RectanglePerimeter,
  EllipsePerimeter
};

Only the perimeters actually used are bundled in.

🔬 Real-world examples from the maxGraph repo

Note

JS examples use Webpack, TS examples use Vite (Rollup)
⚠️ The TS and JS examples don't cover the same use cases
📦 In JS examples: the size = full app
📦 In TS examples: the size = maxGraph chunk only

Example v0.18.0 After #785 After #791
js-example 476.10 kB 475.92 kB 475.30 kB
js-example-selected-features 423.45 kB 415.59 kB 415.10 kB
js-example-without-default 347.86 kB 347.83 kB 347.33 kB
ts-example 439.30 kB 439.15 kB 438.64 kB
ts-example-selected-features 381.15 kB 381.14 kB 380.70 kB
ts-example-without-default 330.38 kB 330.38 kB 329.90 kB

Analysis:

  • In the *-without-default examples, there's no change — because Perimeter wasn't used.
  • In TS examples, the gains are minor (Rollup already tree-shaked well).
  • The best gains are seen in JS/Webpack examples where tree-shaking was previously limited.

🔬 Examples from the maxgraph-integration-examples repository

Example 0.18.0 0.19.0
farm 407.8 kB (in 5 chunks) 406.1 kB (in 2 chunks)
lit (vite) 402.7 kB 402.2 kB
parcel 506.5 kB 506.7 kB
rollup 381.0 kB 380.4 kB
rsbuild 358.0 kB 361.9 kB
vite 384.0 kB 383.5 kB

What's Changed

🎉 New Features

🐛 Bug Fixes

  • fix: correctly convert "arc" attributes to boolean in StencilShape by @tbouffard in #788

📝 Documentation

  • docs: add structure section and improve npm package details by @tbouffard in #792

Full Changelog: v0.18.0...v0.19.0

0.18.0

26 Apr 15:33
v0.18.0
676dbd8
Compare
Choose a tag to compare

This new version introduces BaseGraph for better control over loaded features, adds new utilities to register default style elements, and significantly reduces bundle size!

Resources

Highlights

🚀 Introducing BaseGraph

Historically, the Graph class has been the main entry point in maxGraph, just like it was in mxGraph.
It automatically loads default plugins and style elements, making it convenient for prototyping but less ideal for production use - it increases the bundle size by including features you might not even use.

With v0.18.0, you now have a better option:

  • BaseGraph: an alternative to Graph that loads nothing by default. You choose what to include.
  • AbstractGraph: a new abstract class with all the common logic, shared by both Graph and BaseGraph.
  • Graph remains fully functional, but it's now built on top of AbstractGraph.

This is a big step toward full tree-shaking support!
More improvements are coming soon. Stay tuned! 📻

Note

See issue #665 for the full roadmap on tree-shaking improvements.

  • Related PR: Introduce BaseGraph in #776

🛠 Usage of BaseGraph

BaseGraph also simplifies constructor usage:
Instead of many parameters (and sometimes lots of null), you now pass a single configuration object.

Example - Basic setup:

const graph = new BaseGraph({
  container: document.getElementById('graphContainer')!,
});

Example - Full configuration:

const graph = new BaseGraph({
  container: document.getElementById('graphContainer')!,
  model: new MyGraphDataModel(),
  stylesheet: new MyStylesheet(),
  plugins: [Plugin1, Plugin2],
  cellRenderer: new MyCellRenderer(),
  view: (graph: AbstractGraph) => new MyGraphView(graph),
  selectionModel: (graph: AbstractGraph) => new MyGraphSelectionModel(graph),
});

Compared to Graph, it's much cleaner - no need to extend classes just to customize internals!

⚡ Comparison: Graph Usage

When using the traditional Graph class, customization often requires class extension and overriding internal methods (createXXX) which makes the code heavier and less readable.

Example - Basic setup:

const graph = new Graph(document.getElementById('graphContainer')!);

Example - Full customization:

class MyCustomGraph extends Graph {
  override createCellRenderer(): CellRenderer {
    return new MyCellRenderer();
  }

  override createGraphView(): GraphView {
    return new MyGraphView(this);
  }

  override createSelectionModel(): GraphSelectionModel {
    return new MyGraphSelectionModel(this);
  }
}

const graph = new MyCustomGraph(
  document.getElementById('graphContainer')!,
  new MyGraphDataModel(),
  new MyStylesheet(),
  [Plugin1, Plugin2],
);


// If you want to override only some elements and not others, you might end up passing `undefined` explicitly:
// In case of the GraphDataModel and Stylesheet are managed by overriding `createGraphDataModel` and `createStylesheet` respectively
const graph = new MyCustomGraph(
  document.getElementById('graphContainer')!,
  undefined,
  undefined, 
  [Plugin1, Plugin2],
);

Warning

This approach leads to less readable code and harder maintenance, especially when you don't want to override everything!

🎨 Easier Ways to Register Style Elements

Want to manually register default styles? New helper functions are available:

registerDefaultEdgeMarkers();
registerDefaultEdgeStyles();
registerDefaultPerimeters();
registerDefaultShapes();

Use them to selectively register only what your app actually needs!
If you need all built-in elements for a category, these helpers make it super easy.

Note

"Edge Marker" factories (for arrow shapes and such) are now public too. Flexibility unlocked! 🔓

📦 Impact of BaseGraph on Bundle Size

Using BaseGraph with only the styles and plugins you need can drastically shrink your app's bundle size.
Tree-shaking now works better and smarter!

In our examples, switching to BaseGraph with a minimal setup gave measurable improvements, even with default bundler configs!
The "without-defaults" examples showed a decrease 105 kB!

🔬 Examples from the maxGraph repository

Tip

JS examples use Webpack, TS examples use Vite (Vite/Rollup does better tree-shaking!)

  • the JS and TS examples doesn't cover the same use case
  • the size mentioned here is the one of the whole application in the JS examples and the one of the maxGraph chunk in the TS examples
Example 0.17.0 before BaseGraph (main branch, commit 94a1609) 0.18.0
js-example 475.7 kB 475.8 kB 476.1 kB
js-example-selected-features - 476.1 kB 423.5 kB
js-example-without-default 452.1 kB 454.2 kB 347.8 kB
ts-example 439.1 kB 439.0 kB 439.3 kB
ts-example-selected-features - 439.1 kB 381.2 kB
ts-example-without-default 435.1 kB 434.9 kB 330.4 kB

📖 See documentation for full example details.

🔬 Examples from the maxgraph-integration-examples repository

Integration projects also switched to BaseGraph, showing similar gains:

Example Previously with Graph Now with BaseGraph
farm 454.2 kB (in 2 chunks) 407.8 kB (in 5 chunks)
lit (vite) 462.4 kB 402.7 kB
parcel 529.3 kB 506.5 kB
rollup 439.2 kB 381.0 kB
rsbuild 416.9 kB 358.0 kB
vite 443.1 kB 384.0 kB

Fun fact:

  • Removing the optional CellEditorHandler plugin in vite drops another ~12.5 kB!

  • Related PRs: #214, #215

What's Changed

🎉 New Features

  • feat: simplify types used to register shapes by @tbouffard in #768
  • feat(core): explicitly support undefined container in Graph constructor by @tbouffard in #769
  • feat: let register and unregister default style elements by @tbouffard in #757
  • feat: introduce examples that not rely on default plugins and styles by @tbouffard in #774
  • feat: let efficiently not load default plugins and style builtins by @tbouffard in #776
  • feat: let serialize BaseGraph with Codecs by @tbouffard in #778

🐛 Bug Fixes

  • fix: use the right list of excluded fields in GraphCodec by @tbouffard in #777

📝 Documentation

  • docs: explain that the mxGraph migration guide is no longer updated by @tbouffard in #783

⚙️ Refactor

  • refactor(type): explicitly declare the MouseListenerSet interface by @tbouffard in #770
  • refactor: reorganize builtin style elements by @tbouffard in #775
  • refactor: use CellEditorHandler plugin in selected-features examples by @tbouffard in #779

Full Changelog: v0.17.0...v0.18.0

0.17.0

06 Apr 17:24
v0.17.0
e22b2e1
Compare
Choose a tag to compare

This new version improves graph fitting, makes i18n fully configurable, and reduces bundle size significantly.

Resources

Breaking changes

Important

These changes may impact existing usages. Please review them carefully and check the related pull requests for migration guidance.

🔐 Eval usage is now disabled by default

To prevent potential security issues, StylesheetCodec.allowEval is now false by default.

Note

See #736 for details.

🌐 Configurable i18n

The built-in Translations class is no longer used by default. If you want to keep using it, you must now explicitly enable it:

GlobalConfig.i18n = new TranslationsAsI18n();

Note

See #737

🧰 Utility functions access changes

Several utils have been reorganized for better clarity and maintainability:

  • These functions are now accessed through specific namespaces:
    • get, getAll, load, post, submitrequestUtils
    • error, popupguiUtils
  • The old utils namespace has been removed.
  • Remaining relevant properties were moved to guiUtils.

Note

See #740

💥 Removed internal functions

Some functions that were mistakenly exposed as public have been removed:

  • Utils.copyTextToClipboard is no longer available.

    See #738

  • cellArrayUtils.filterCells was removed - just use the native Array.filter() instead!

    See #752

Highlights

🎯 New: Fit Center

You can now center and fit your graph into the container with the new FitPlugin.
The method is inspired by the former example provided in the JSDoc of Graph.fit() but improved to:

  • handle margins better,
  • reduce visual shifts when called multiple times.

The storybook and TypeScript example have been updated to showcase how it works in various contexts.

PR_733_story_fit_center.mp4

Note

See #733

🌍 Configurable i18n support

Until now, the Translations class was always used internally. Now you can:

  • Disable i18n completely for smaller bundles,
  • Plug in your own i18n solution.

This makes maxGraph more flexible and lighter by default.

Note

See #737

📦 Smaller bundle size

Thanks to the new i18n configuration, tree-shaking now works better.
Depending on your setup, you could reduce the size of your app by 5-10kB - and probably more with tuned bundler configs!

Tip

Examples use default bundler configs and still show measurable gains.

🔬 Examples in the maxGraph repo

Example 0.16.0 0.17.0
js-example 484.1 kB 475.71 kB
js-example-without-defaults 462.4 kB 452.13 kB
ts-example 444.4 kB 439.15 kB
ts-example-without-defaults 440.4 kB 435.12 kB

📖 See documentation for what each example includes.

🔬 Examples in maxgraph-integration-examples

All integration projects reuse a shared core similar to ts-example. Here's the app size:

Example 0.16.0 0.17.0
farm 461.0 kB 453.9 kB
lit with vite 471.7 kB 466.5 kB
parcel[1] 521.2 KB 528.1 kB
rollup 443.7 kB 438.3 kB
rsbuild 429.4 kB 417.3 kB
vite 447.5 kB 442.2 kB

[1] parcel is the sole bundler that increases the size of the application. Parcel was bump from 2.13.3 to 2.14.4 which may have introduced changes.

➰ New story: curved edges

We've added a story to show the difference between:

  • default edges
  • curved edges
  • rounded edges
PR_731_story_edges_curved_and_rounded.mp4

Note

See #731

What's Changed

🎉 New Features

  • feat: refine the type of CellStateStyle.elbow by @tbouffard in #701
  • feat: CellStateStyle port constraints accept multiple DirectionValue by @tbouffard in #721
  • feat: let "fit center" with the new FitPlugin by @tbouffard in #733
  • feat!: limit usage of the eval function by @tbouffard in #736
  • feat!: introduce a way to configure the I18n provider by @tbouffard in #737

🐛 Bug Fixes

  • fix: consider ManhattanConnector as orthogonal by @tbouffard in #707
  • fix(type): let Graph fitScale properties allow null by @tbouffard in #715
  • fix(story): add buttons to container, not to the document by @tbouffard in #750
  • fix(story): ensure that the Model Codecs are always registered by @tbouffard in #749
  • fix: make Graph.options truly per-instance by @tbouffard in #751

📝 Documentation

⚙️ Refactor

  • refactor: migrate the Events story to TypeScript by @tbouffard in #702
  • refactor: introduce shared code to manage description of story by @tbouffard in #703
  • refactor: migrate the Wrapping story to TypeScript by @tbouffard in #720
  • refactor: simplify type management in Codecs by @tbouffard in #723
  • refactor: apply internal improvements to editor classes by @tbouffard in #726
  • refactor: improve the management of CellStateStyle.curved by @tbouffard in #731
  • refactor: remove isNotNullish internal function by @tbouffard in #732
  • refactor: move plugins to a dedicated folder by @tbouffard in #735
  • refactor!: move internal utils functions to a dedicated directory by @tbouffard in #738
  • refactor!: expose all exported functions in namespaces by @tbouffard in #740
  • refactor!: move properties of utils to guiUtils by @tbouffard in #741
  • refactor(types): simplify imports of the Graph types by @tbouffard in #743
  • refactor!: remove cellArrayUtils.filterCells by @tbouffard in #752

🛠 Chore

  • chore: add more checks in ts-support by @tbouffard in #728
  • chore(types): enforce usage of explicit override keyword in examples by @tbouffard in #739

Full Changelog: v0.16.0...v0.17.0

0.16.0

02 Mar 11:55
18755d6
Compare
Choose a tag to compare

⚡ This new version enhances internationalization (i18n), improves connector configurations, and prepares for future updates with tree shaking optimizations. ⚡

Resources


Breaking changes

Note

Some changes are introduced to prepare for tree shaking improvements as part of issue #665.

  • Private utility functions:
    The functions utils.isNullish and utils.isNotNullish are now marked as private. They were mistakenly made public and have always been intended for internal use.

  • Removed utility functions:
    Several utility functions, originally designed for internal use to retrieve default values for CellStateStyle and CellStyle, have been removed:

    • utils.getValue
    • stringUtils.getColor
    • stringUtils.getNumber
    • stringUtils.getStringValue

    You should now use the nullish coalescing operator (??) and Optional chaining (?.) instead.

  • Removed Client.isBrowserSupported:
    The Client.isBrowserSupported method has been removed. It was not correctly validating all the prerequisites for determining whether the browser supports maxGraph. This method is now deprecated with no direct replacement.

  • Moved Client.VERSION to constants.VERSION:
    The VERSION constant, previously stored in Client, is now stored in the constants module to ensure its immutability, as it represents the actual version of maxGraph.

  • Relocated Translations configuration:
    Configuration elements for translations have been moved from Client to TranslationsConfig. The following properties have been migrated:

    • Client.defaultLanguageTranslationsConfig.getDefaultLanguage
    • Client.setDefaultLanguageTranslationsConfig.setDefaultLanguage
    • Client.languageTranslationsConfig.getLanguage
    • Client.setLanguageTranslationsConfig.setLanguage
    • Client.languagesTranslationsConfig.getLanguages
    • Client.setLanguagesTranslationsConfig.setLanguages
  • Connector Configuration changes:

    • ManhattanConnector: Now configured via the global ManhattanConnectorConfig object. Several properties that were previously part of EdgeStyle have moved to this configuration object:
      • MANHATTAN_END_DIRECTIONSendDirections
      • MANHATTAN_MAX_ALLOWED_DIRECTION_CHANGEmaxAllowedDirectionChange
      • MANHATTAN_MAXIMUM_LOOPSmaxLoops
      • MANHATTAN_START_DIRECTIONSstartDirections
      • MANHATTAN_STEPstep
    • OrthConnector: Now configured via the global OrthogonalConnectorConfig object. The following properties have been moved:
      • orthBufferbuffer
      • orthPointsFallbackpointsFallback
  • Internal utility methods:
    Several properties and utility methods previously exposed by EdgeStyle are now internal. For example:

    • The getRoutePattern method has been removed entirely, as it was not being used anywhere within the codebase.

Highlights

🌍 Custom Shape Support for Overlays

You can now use custom shapes for overlays instead of just images. The CellRenderer provides extension points for configuring custom shapes and their associated DOM nodes.

Here is an example of custom Overlays taken from the Overlays story 👇🏿

PR_696_custom_overlays.webm

Note

For more details, see #696.

🌐 Improved i18n Support

This release enhances i18n support with the restoration of original mxGraph resource files (Chinese, English, and German) and adds French and Spanish resources. Additionally, a new configuration object, TranslationsConfig, is introduced to simplify and extend internationalization functionality in future releases.
This update is part of ongoing efforts to allow for custom i18n mechanisms in future versions (see issue #688).

🔗 Enhanced Manhattan and Orthogonal Connector Configuration

The configuration for both the Manhattan and Orthogonal connectors is now centralized in dedicated global configuration objects: ManhattanConnectorConfig and OrthogonalConnectorConfig. This change helps clarify responsibilities and makes future tree shaking optimizations easier. Additionally, related reset functions are now available.


What's Changed

🎉 New Features

  • feat!: introduce global config for the Orthogonal connector by @tbouffard in #678
  • feat!: introduce global config for the Manhattan connector by @tbouffard in #681
  • feat: provide i18n default resources by @tbouffard in #689
  • feat: provide i18n resources for French and Spanish by @tbouffard in #690
  • feat!: introduce TranslationsConfig by @tbouffard in #691
  • feat: allow to use custom shape for overlays by @tbouffard in #696

🐛 Bug Fixes

  • fix: Graph.isValidAncestor manages null Cell parameter by @tbouffard in #699

📝 Documentation

⚙️ Refactor

  • refactor!: mark isNullish and isNotNullish as private by @tbouffard in #661
  • refactor!: remove extra getDefault functions and related functions by @tbouffard in #662
  • refactor!: remove Client.isBrowserSupported by @tbouffard in #679
  • refactor!: move VERSION to constants by @tbouffard in #680
  • refactor!: extract Orthogonal and Manhattan connectors by @tbouffard in #684
  • refactor: rename OrthConnectorConfig to OrthogonalConnectorConfig by @tbouffard in #685
  • refactor: do not redeclare ImageShape properties already in Shape by @tbouffard in #694
  • refactor: reset more global configurations in stories by @tbouffard in #646
  • refactor: use external CSS file MenuStyle and ShowRegion stories by @tbouffard in #698

Full Changelog: v0.15.1...v0.16.0

0.15.1

13 Feb 10:52
721bdd4
Compare
Choose a tag to compare

⚡ This new version includes bug fixes and documentation improvements. ⚡

Resources

What's Changed

🐛 Bug Fixes

  • fix: remove some circular dependencies by @tbouffard in #663
  • fix(VertexHandler): display overlay when resizing a vertex by @tbouffard in #673

📝 Documentation

  • docs: fix typo in CHANGELOG by @tbouffard in #653
  • docs: apply quick fixes to the "getting started" and "demos" page by @tbouffard in #654
  • docs(release): better explain how to choose the new version by @tbouffard in #655
  • docs: add more information about perimeters by @tbouffard in #656
  • docs: add missing Logging category to the Logger interface by @tbouffard in #667
  • docs: add a first blog post in the website by @tbouffard in #672

⚙️ Refactor

🛠 Chore

  • ci(release): fix api call to get milestone number by @tbouffard in #651
  • ci: include js-example-without-defaults during the build by @tbouffard in #669

Full Changelog: v0.15.0...v0.15.1

0.15.0

29 Jan 11:21
9428e87
Compare
Choose a tag to compare

A step forward! This new version brings major improvements, especially in documentation and edge handling, while also addressing long-standing issues. ⚡

Many thanks to @HalilFocic for all the fixes and the great work on improving the documentation! 🙌

Resources


Breaking Changes 🚨

The impact of breaking changes in this release is minimal. They mainly affect unused or non-functional parts of the API.

EdgeHandler Property Removal

Some properties have been removed from EdgeHandler because they couldn't be modified correctly. They are now replaced by global configuration options in EdgeHandlerConfig:

  • addEnabledaddBendOnShiftClickEnabled
  • removeEnabledremoveBendOnShiftClickEnabled
  • virtualBendOpacity
  • virtualBendsEnabled

Note

For more details, see #633.

domUtils.importNodeImplementation Removed

  • This function was only used internally in mxGraph to support old versions of Internet Explorer.
  • It was never intended to be part of the public API.
  • No migration is needed, as the function was unused.

Note

For more details, see #648.


Highlights ✨

🚀 Major Documentation Improvements

The entire mxGraph manuals and tutorials have been integrated and adapted for maxGraph! 🎉

This is a huge milestone that ensures we have comprehensive and structured documentation, benefiting from the experience and maturity of mxGraph.

We also listened to your feedback and have placed a stronger emphasis on examples and demos in the documentation, making it easier to find relevant code snippets for specific features directly from most pages.

What’s next? Better organization of manuals and tutorials:

  • Creating a clear learning path for newcomers.
  • Ensuring consistency with the existing usage documentation of all specific features that were already documented before integrating the manuals and tutorials.

Note

Documentation is a hot topic! Join the discussion on the roadmap: GitHub Discussion #595.


🔧 New EdgeHandler Configuration

Managing edge bend points is now much easier!

Previously in mxGraph, modifying EdgeHandler properties required updating the class prototype, which no longer worked in `maxGraph`. Now, you can configure everything via EdgeHandlerConfig. This allows:

  • Virtual bends: Add bends at the midpoint of all edge segments.
  • Adding bends: Shift-click anywhere on an edge.
  • Removing bends: Shift-click an existing point.

Note

For more details, see #633.

PR_633_new_properties_in_story.mp4

🔄 Fix: Vertex Rotation

A major issue from the first release of maxGraph has been fixed!

The rotation handle was misplaced, and the initial rotation angle was incorrect. The handle always appeared to the right of the vertex, even after rotation, making subsequent rotations behave incorrectly.

This made the feature impossible to use—but not anymore! ✅

Note

For more details, see issue #482.

Before

story_stencils.mp4

Now

stencils.mov

What's Changed

🎉 New Features

  • feat: introduce global config for the Entity Relation connector by @tbouffard in #620
  • feat: make the stencils XML schema available in the npm package by @tbouffard in #626
  • feat!: make edge bend points easier to manage by @tbouffard in #633

🐛 Bug Fixes

  • fix: correct rotation handle positioning during vertex rotation by @HalilFocic in #592
  • fix(VertexHandler): do not create label handle for swimlane by @tbouffard in #607
  • fix: popup menu story caused has more submenus open by @HalilFocic in #572
  • fix(TooltipHandler): initialize the div when tooltip is shown by @HalilFocic in #591
  • fix: ensure that codecs for base JS elements are registered by @tbouffard in #610
  • fix(story): correctly set the perimeter on labels at page load by @HalilFocic in #589

📝 Documentation

⚙️ Refactor

  • refactor(VertexHandler): simplify management of style.rotation by @tbouffard in #634
  • refactor: migrate the "Animation" story to TypeScript by @tbouffard in #635
  • refactor: migrate the "AutoLayout" story to TypeScript by @tbouffard in #638
  • refactor: remove clipboard fallback for old browsers by @tbouffard in #645
  • refactor!: remove unused domUtils.importNodeImplementation by @tbouffard in #648

🛠 Chore

  • ci: build and deploy the website when the storybook resources change by @tbouffard in #609
  • ci: configure dependabot to update JavaScript dependencies by @tbouffard in #629
  • ci: fix dependabot configuration by @tbouffard in #630
  • ci: improve the template of the GitHub release by @tbouffard in #593
  • chore: add a script to simplify version update on release by @tbouffard in #650

Full Changelog: v0.14.0...v0.15.0

0.14.0

28 Nov 07:48
62d4c8f
Compare
Choose a tag to compare

⚡ This new version offers more configuration options for vertex and edge handles, and allows certain default style configurations to be globally replaced. ⚡

🎉 We've made it easier to shape your graphs the way you want!

Labels are now editable out of the box ✍️, handles can be customized with ease 🎨, and shadows have new global style options 🌌.

Many thanks to @HalilFocic for all the fixes provided and those to come! 🙌

Resources

Highlights

Editable Labels and Correct Editing Position

Labels are now editable by default for both vertices and edges, restoring the expected behavior seen in mxGraph.

Previously, due to a bug, making the label editable required configuring the Cell style with:

style.editable = true;

This is no longer necessary.

In addition, when editing a label, the editing area now appears exactly where the label is in "view" mode. Previously, a bug caused it to appear at the bottom of the page, which was... less than ideal. 😅

PR_567_label_edition.webm

Note

For more details, see issues #567 and #570.

Tip

If you want to restore the previous behavior (cells not editable), use one of the following:

const graph = new Graph(container);

// forbid cell label edition
graph.setCellsEditable(false);

// make vertex labels not editable by default (use the getDefaultEdgeStyle to apply the same to the edge labels)
graph.getStylesheet().getDefaultVertexStyle().editable = false;

// and if you want to make the label of a specific vertex editable
vertex.style.editable = true;

More Configuration Options for EdgeHandler and VertexHandler

Edge handles, which represent the edge points when an edge is selected, can now be a "circle" ⚪ instead of just a "square" ⬛.

Configuration for EdgeHandler and VertexHandler is now more straightforward. Previously, changing default values like the color or size of handles required extending the original implementation.

Now, you can use simple configuration value objects to change default settings, such as:

EdgeHandlerConfig.handleShape = 'circle';
EdgeHandlerConfig.selectionColor = 'blue';
EdgeHandlerConfig.selectionDashed = false;

// configure the label handle of both edge and vertex
HandleConfig.size = 8;
HandleConfig.strokeColor = '#0088cf';

VertexHandlerConfig.selectionColor = 'orange';

Check it out in the story:

rn_0.14.0_custom_handles_config.webm

Note

For more details, see issues #576 and #586.

Important

Not all default values are configurable for now. This is a first step, stay tuned for future updates. For more details, see issue #192.

Override the Default Shadow Style Values

Global style defaults are defined in the constants namespace, and up until now, changing them globally wasn't possible. You could only change them for an instance of Graph with custom configurations for edge and vertex default styles.

Starting with version 0.14.0, you can now change the default shadow styles globally for all instances of Graph:

StyleDefaultsConfig.shadowColor = 'chartreuse';
StyleDefaultsConfig.shadowOpacity = 0.5;

Check out the new CustomStyleDefaults story to see it in action:

PR_577_custom_default_shadow_styles.webm

Note

For more details, see issue #577.

Important

Overriding more default style values will be possible in the future. This is just the beginning—stay tuned for more updates! For details, see issue #192.

What's Changed

🎉 New Features

  • feat: allow usage of functions in CellStateStyle.edgeStyle by @tbouffard in #563
  • feat: ease configuration of handles in VertexHandler by @tbouffard in #569
  • feat: let configure the defaults value of the shadow styles by @tbouffard in #577
  • feat: ease configuration of handles in EdgeHandler by @tbouffard in #576
  • feat: allow the use of circles for edge handles by @tbouffard in #586

🐛 Bug Fixes

  • fix: correctly use the default value of CellStateStyle.editable by @tbouffard in #570
  • fix: improve the panning on iOS/iPadOS by @HalilFocic in #566
  • fix(label): improve editing position and 'label changed" event by @HalilFocic in #567
  • fix(VertexHandle): add missing setPosition call in processEvent by @HalilFocic in #583

📝 Documentation

  • docs: explain what is included in the changelog file by @tbouffard in #561
  • docs: improve JSDoc of elements in the constants namespace by @tbouffard in #568
  • docs: improve JSDoc of handlers and constants by @tbouffard in #575
  • docs: mention examples in the documentation introduction by @tbouffard in #585

⚙️ Refactor

  • refactor(CellMixin): simplify isCell*able methods by @tbouffard in #571
  • refactor: use constants.NS_SVG instead of hard coded values by @tbouffard in #578
  • refactor: simplify the reset config functions by @tbouffard in #582

🛠 Chore

New Contributors

Full Changelog: v0.13.1...v0.14.0

0.13.1

04 Nov 15:11
6c73e30
Compare
Choose a tag to compare

⚡ This release contains documentation improvements and bug fixes (mainly for MaxPopupMenu and PrintPreview). ⚡

npm package: 0.13.1
Fixed issues: milestone 0.13.1
See also the Changelog file.

What's Changed

🐛 Bug Fixes

  • fix(story): convert page-breaks story to typescript and add missing imports by @reuse-ay in #537
  • fix: add missing printUtils export by @tbouffard in #538
  • fix(PrintPreview): Execute writeHead even if css is null by @reuse-ay in #541
  • fix: correctly call methods in TemporaryCellStates and PrintPreview by @tbouffard in #546
  • fix: display submenu image in MenuStyle story by @tbouffard in #551
  • fix: make ShowRegion story correctly create the preview page by @tbouffard in #553
  • fix: improve type of the handler parameter in factoryMethod by @tbouffard in #554
  • fix: allow to insert vertex without setting position and size by @tbouffard in #555

📝 Documentation

⚙️ Refactor

  • refactor: improve signature of some PrintPreview methods by @tbouffard in #548

🛠 Chore

  • chore(test): switch from ts-jest to @swc/jest by @tbouffard in #540
  • chore(package): store application resources in the lib folder by @tbouffard in #543

New Contributors

Full Changelog: v0.13.0...v0.13.1