Skip to content

Conversation

@tbouffard
Copy link
Member

@tbouffard tbouffard commented Jan 20, 2025

Move getTooltip and getTooltipForCell from AbstractGraph to the TooltipHandler plugin as this is the only place where they are used.
This improves modularity and tree-shaking, clarifies responsibilities, and reduces the amount of code in AbstractGraph by removing the TooltipMixin.

The stories have been updated accordingly and can be used as examples for adapting application code.

BREAKING CHANGES: The getTooltip and getTooltipForCell methods have been moved from AbstractGraph to the TooltipHandler plugin.
If you were overriding these methods in a AbstractGraph subclass, you should now extend TooltipHandler instead.

Covers #762

Impacts on the size of the examples

Examples that don't use TooltipHander: -0.7kB

Example name Size before (32c54d4) Size after
ts-example 433.31 kB 433.31 kB
ts-example-selected-features 368.09 kB 367.41 kB
ts-example-without-defaults 307.22 kB 306.55 kB
js-example 468.30 kB 468.30 kB
js-example-selected-features 389.98 kB 389.30 kB
js-example-without-defaults 324.78 kB 324.10 kB

Remaining tasks

  • rebase on main
  • JSDoc: getTooltipForCell example + code refactoring
  • Decide if we make the methods protected in the handler (may prevent from assiging the new impl and force to subclass) --> no, keep them public, this is another topic
  • Decide whether to remove or relocate setTooltips: move it to AbstractGraph
  • Migrate the stories using the getTooltip Graph methods to TypeScript to better detect the usage of these methods
  • getTooltipForCell comment: explain when a cell can have a specific method, no available in the maxGraph implementation
  • Story: manual test to validate this is still working
  • doc changelog: breaking changes
  • PR description: doc breaking changes
  • Measure impact on tree-shaking (use the 2 examples without defaults)

Summary by CodeRabbit

  • Breaking Changes

    • Tooltip customization is now provided by the tooltip plugin rather than by overriding graph methods. If you previously customized tooltips on the graph, migrate that logic into the tooltip plugin.
  • New Features

    • Added a runtime toggle to enable or disable tooltip display.

✏️ Tip: You can customize this high-level summary in your review settings.

@tbouffard tbouffard added the refactor Code refactoring label Jan 20, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2025

Walkthrough

This PR moves tooltip resolution from the graph mixin into the TooltipHandler plugin, adds AbstractGraph.setTooltips(enabled), removes TooltipMixin and its type augmentations, updates tests, and migrates story files to override tooltip methods on the TooltipHandler plugin.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Added breaking-change note: getTooltip and getTooltipForCell moved from AbstractGraph/TooltipMixin to the TooltipHandler plugin
Core: Graph API
packages/core/src/view/AbstractGraph.ts
Added setTooltips(enabled: boolean) to AbstractGraph to enable/disable TooltipHandler plugin
Core: Tooltip plugin
packages/core/src/view/plugins/TooltipHandler.ts
Added getTooltip(state, node, x, y) and getTooltipForCell(cell) implementations and supporting imports; centralized tooltip resolution in the plugin
Mixin removal
packages/core/src/view/mixins/TooltipMixin.ts, packages/core/src/view/mixins/TooltipMixin.type.ts, packages/core/src/view/mixins/_graph-mixins-apply.ts, packages/core/src/view/mixins/_graph-mixins-types.ts
Removed TooltipMixin implementation and its type augmentation; removed it from mixin application and aggregated mixin types
Tests
packages/core/__tests__/view/Graph.test.ts, packages/core/__tests__/view/handler/TooltipHandler.test.ts
Updated Graph test import and name; added TooltipHandler test to verify getTooltip behavior when no plugins are present and adjusted imports/usages
Stories (migration to plugin)
packages/html/stories/Events.stories.ts, packages/html/stories/HelloPort.stories.ts, packages/html/stories/Stencils.stories.ts, packages/html/stories/Stylesheet.stories.ts, packages/html/stories/UserObject.stories.ts, packages/html/stories/Wires.stories.ts
Replaced direct graph tooltip overrides with plugin-based overrides (retrieve TooltipHandler via graph.getPlugin(...) and override getTooltip/getTooltipForCell on the plugin or supply a custom handler)

Sequence Diagram(s)

mermaid
sequenceDiagram
autonumber
participant User
participant Graph
participant TooltipHandler
participant SelectionHandler
participant Cell/Overlays
User->>Graph: hover node (state, node, x, y)
Graph->>TooltipHandler: getTooltip(state, node, x, y)
TooltipHandler->>Cell/Overlays: check folding icon / overlays
alt overlay or folding match
TooltipHandler-->>Graph: return overlay/folding tooltip
else
TooltipHandler->>SelectionHandler: getTooltipForNode(state, node, x, y)
alt selection handler returns tip
SelectionHandler-->>Graph: return selection tooltip
else
TooltipHandler->>Cell/Overlays: getTooltipForCell(cell)
Cell/Overlays-->>TooltipHandler: cell tooltip (cell.getTooltip or convertValueToString)
TooltipHandler-->>Graph: return cell tooltip
end
end
Graph-->>User: display tooltip

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Review TooltipHandler.ts closely for correct precedence and fallbacks (folding icon, overlays, SelectionCellsHandler delegation, cell fallback).
  • Verify AbstractGraph.setTooltips integrates with plugin registry and toggles plugin enabled state.
  • Inspect story file changes to ensure correct plugin retrieval and proper binding/usage of overridden functions.
  • Confirm all removed mixin type augmentations have been replaced by plugin typings where necessary and no residual references remain.

Possibly related issues

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving tooltip methods from AbstractGraph to TooltipHandler plugin, with the breaking change indicator (!) appropriately placed.
Description check ✅ Passed The description comprehensively covers the PR purpose, breaking changes, impact measurements, and remaining tasks. All key template sections are addressed with substantive content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/tree-shaking_tooltip_mixin_code_to_tooltip_plugin

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86457f7 and 5d14537.

📒 Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • packages/core/__tests__/view/handler/TooltipHandler.test.ts (1 hunks)
  • packages/html/stories/UserObject.stories.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/tests/view/handler/TooltipHandler.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Format code using Prettier with tab width 2, trailing comma ES5, print width 90, and end of line auto.

Files:

  • CHANGELOG.md
  • packages/html/stories/UserObject.stories.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use single quotes in TypeScript/JavaScript code (Prettier config: singleQuote: true).

**/*.{ts,tsx,js,jsx}: Use isNullish function when checking for null or undefined on variables that can have falsy values (numbers, strings, booleans) to avoid treating 0, "", or false as nullish.
Wrap multiple model changes in batchUpdate() to ensure efficient batch processing.

Files:

  • packages/html/stories/UserObject.stories.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 776
File: packages/core/src/view/AbstractGraph.ts:492-495
Timestamp: 2025-04-24T12:34:56.726Z
Learning: PR #776 focuses on refactoring to introduce AbstractGraph as a base class and moving code from Graph to AbstractGraph. Type improvements and other refinements should be addressed in future PRs to keep this one focused on the core architectural change.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 857
File: packages/core/src/view/plugins/SelectionHandler.ts:1081-1092
Timestamp: 2025-06-26T13:27:19.012Z
Learning: User tbouffard prefers to keep PRs focused on their main objective and defer implementation improvements or logic fixes to future dedicated PRs. For maxGraph, refactoring PRs like Dictionary→Map migration should not include unrelated logic improvements even when valid issues are identified in the migrated code.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 740
File: packages/core/src/util/requestUtils.ts:79-106
Timestamp: 2025-03-31T08:32:17.055Z
Learning: PR #740 is focused on reorganizing code into namespaces (guiUtils and requestUtils) without changing any implementations. Implementation improvements should be suggested for future PRs.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 849
File: packages/html/stories/DragSource.stories.js:98-101
Timestamp: 2025-06-13T07:48:10.300Z
Learning: User tbouffard prefers answers in English; avoid switching to other languages in future replies.
📚 Learning: 2025-01-28T16:22:25.804Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 593
File: .github/workflows/create-github-release.yml:42-42
Timestamp: 2025-01-28T16:22:25.804Z
Learning: In the GitHub release notes template for maxGraph, TODO comments are intentionally included to mark sections that must be reviewed by maintainers before publishing the release. These TODOs should not be removed or converted to validation steps as they are part of the release review process.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-05-26T12:34:54.318Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 835
File: packages/html/stories/Orthogonal.stories.ts:114-117
Timestamp: 2025-05-26T12:34:54.318Z
Learning: The `null!` assertion pattern exists across multiple stories in the TypeScript migration and should be addressed systematically rather than in individual PRs.

Applied to files:

  • packages/html/stories/UserObject.stories.ts
🧬 Code graph analysis (1)
packages/html/stories/UserObject.stories.ts (2)
packages/html/stashed/grapheditor/www/js/Graph.js (1)
  • trg (7004-7004)
packages/core/src/view/plugins/TooltipHandler.ts (1)
  • getTooltipForCell (412-419)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build (windows-2022)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-24.04)
🔇 Additional comments (2)
CHANGELOG.md (1)

12-15: LGTM!

The breaking changes entry clearly documents the migration path for users who were overriding getTooltip and getTooltipForCell on AbstractGraph subclasses.

packages/html/stories/UserObject.stories.ts (1)

35-35: LGTM!

Type import added correctly to support the plugin-based tooltip customization.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tbouffard tbouffard changed the title refactor/tree-shaking_tooltip_mixin_code_to_tooltip_plugin refactor!: move all Graph tooltips methods to TooltipHandler Jan 20, 2025
@tbouffard tbouffard changed the title refactor!: move all Graph tooltips methods to TooltipHandler refactor!: move all Graph tooltip methods to TooltipHandler Jan 28, 2025
@tbouffard tbouffard force-pushed the refactor/tree-shaking_tooltip_mixin_code_to_tooltip_plugin branch from fee8b53 to da69908 Compare December 12, 2025 17:59
@tbouffard tbouffard changed the title refactor!: move all Graph tooltip methods to TooltipHandler refactor!: move tooltip methods from AbstractGraph to TooltipHandler Dec 17, 2025
@tbouffard tbouffard changed the title refactor!: move tooltip methods from AbstractGraph to TooltipHandler refactor!: move tooltip methods to TooltipHandler Dec 17, 2025
Move `getTooltip` and `getTooltipForCell` from `AbstractGraph` to the `TooltipHandler` plugin as this is the only place where they are used.
This improves modularity and tree-shaking, clarifies responsibilities, and reduces the amount of code in `AbstractGraph` by removing the `TooltipMixin`.

The stories have been updated accordingly and can be used as examples for adapting application code.

BREAKING CHANGES: The `getTooltip` and `getTooltipForCell` methods have been moved from `AbstractGraph` to the `TooltipHandler` plugin.
If you were overriding these methods in a `AbstractGraph` subclass, you should now extend `TooltipHandler` instead.
@tbouffard tbouffard force-pushed the refactor/tree-shaking_tooltip_mixin_code_to_tooltip_plugin branch from b211e94 to 86457f7 Compare December 17, 2025 15:05
@tbouffard tbouffard marked this pull request as ready for review December 17, 2025 15:05
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
packages/core/src/view/plugins/TooltipHandler.ts (1)

362-369: Consider using Array.prototype.some() for early exit.

The LATER comment indicates awareness of this, but using some() would allow breaking early once a tooltip is found. Given the PR focus on refactoring, this can be deferred.

-    if (!tip && state.overlays) {
-      state.overlays.forEach((shape: Shape) => {
-        // LATER: Exit loop if tip is not null
-        if (!tip && (node === shape.node || node.parentNode === shape.node)) {
-          tip = shape.overlay ? (shape.overlay.toString() ?? null) : null;
-        }
-      });
-    }
+    if (!tip && state.overlays) {
+      state.overlays.some((shape: Shape) => {
+        if (node === shape.node || node.parentNode === shape.node) {
+          tip = shape.overlay ? (shape.overlay.toString() ?? null) : null;
+          return tip !== null; // exit early if found
+        }
+        return false;
+      });
+    }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32c54d4 and 86457f7.

📒 Files selected for processing (15)
  • CHANGELOG.md (2 hunks)
  • packages/core/__tests__/view/Graph.test.ts (1 hunks)
  • packages/core/__tests__/view/handler/TooltipHandler.test.ts (1 hunks)
  • packages/core/src/view/AbstractGraph.ts (2 hunks)
  • packages/core/src/view/mixins/TooltipMixin.ts (0 hunks)
  • packages/core/src/view/mixins/TooltipMixin.type.ts (0 hunks)
  • packages/core/src/view/mixins/_graph-mixins-apply.ts (0 hunks)
  • packages/core/src/view/mixins/_graph-mixins-types.ts (0 hunks)
  • packages/core/src/view/plugins/TooltipHandler.ts (4 hunks)
  • packages/html/stories/Events.stories.ts (2 hunks)
  • packages/html/stories/HelloPort.stories.ts (2 hunks)
  • packages/html/stories/Stencils.stories.ts (2 hunks)
  • packages/html/stories/Stylesheet.stories.ts (2 hunks)
  • packages/html/stories/UserObject.stories.ts (2 hunks)
  • packages/html/stories/Wires.stories.ts (2 hunks)
💤 Files with no reviewable changes (4)
  • packages/core/src/view/mixins/_graph-mixins-apply.ts
  • packages/core/src/view/mixins/TooltipMixin.type.ts
  • packages/core/src/view/mixins/TooltipMixin.ts
  • packages/core/src/view/mixins/_graph-mixins-types.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Format code using Prettier with tab width 2, trailing comma ES5, print width 90, and end of line auto.

Files:

  • CHANGELOG.md
  • packages/core/src/view/AbstractGraph.ts
  • packages/html/stories/Stylesheet.stories.ts
  • packages/html/stories/HelloPort.stories.ts
  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
  • packages/html/stories/Stencils.stories.ts
  • packages/html/stories/Wires.stories.ts
  • packages/core/src/view/plugins/TooltipHandler.ts
  • packages/html/stories/UserObject.stories.ts
  • packages/html/stories/Events.stories.ts
  • packages/core/__tests__/view/Graph.test.ts
packages/core/src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/core/src/**/*.ts: Include .js file extensions in all import statements within packages/core/src/ to comply with ESLint rule n/file-extension-in-import.
Do not use console statements in any code. Use proper logging mechanisms instead (ESLint rule: no-console: error).
Do not use eval() function in any code (ESLint rule: no-eval: error).
Do not use const enums. Convert all const enums to regular enums (ESLint rule forbids const enums).
TypeScript source files in core package must strictly maintain typing with no implicit types and all functions having explicit return type annotations.

Files:

  • packages/core/src/view/AbstractGraph.ts
  • packages/core/src/view/plugins/TooltipHandler.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use single quotes in TypeScript/JavaScript code (Prettier config: singleQuote: true).

**/*.{ts,tsx,js,jsx}: Use isNullish function when checking for null or undefined on variables that can have falsy values (numbers, strings, booleans) to avoid treating 0, "", or false as nullish.
Wrap multiple model changes in batchUpdate() to ensure efficient batch processing.

Files:

  • packages/core/src/view/AbstractGraph.ts
  • packages/html/stories/Stylesheet.stories.ts
  • packages/html/stories/HelloPort.stories.ts
  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
  • packages/html/stories/Stencils.stories.ts
  • packages/html/stories/Wires.stories.ts
  • packages/core/src/view/plugins/TooltipHandler.ts
  • packages/html/stories/UserObject.stories.ts
  • packages/html/stories/Events.stories.ts
  • packages/core/__tests__/view/Graph.test.ts
packages/core/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Define styles as objects conforming to CellStyle type as documented in packages/core/src/types.ts.

Files:

  • packages/core/src/view/AbstractGraph.ts
  • packages/core/src/view/plugins/TooltipHandler.ts
packages/core/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Code must conform to ES2020 standard and target modern browsers (Chrome, Edge, Firefox, Safari, Chromium-based browsers). No IE support.

Files:

  • packages/core/src/view/AbstractGraph.ts
  • packages/core/src/view/plugins/TooltipHandler.ts
packages/core/__tests__/**/*.test.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Test files must follow the naming pattern **/*.test.ts and be located in packages/core/__tests__/ directory.

Files:

  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
  • packages/core/__tests__/view/Graph.test.ts
packages/core/__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/core/__tests__/**/*.test.{ts,tsx}: Tests should use Jest with jsdom environment and be located in packages/core/__tests__/ mirroring the src/ directory structure.
Import paths in tests should omit .js extension (handled by moduleNameMapper).

Files:

  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
  • packages/core/__tests__/view/Graph.test.ts
🧠 Learnings (15)
📓 Common learnings
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 776
File: packages/core/src/view/AbstractGraph.ts:492-495
Timestamp: 2025-04-24T12:34:56.726Z
Learning: PR #776 focuses on refactoring to introduce AbstractGraph as a base class and moving code from Graph to AbstractGraph. Type improvements and other refinements should be addressed in future PRs to keep this one focused on the core architectural change.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 857
File: packages/core/src/view/plugins/SelectionHandler.ts:1081-1092
Timestamp: 2025-06-26T13:27:19.012Z
Learning: User tbouffard prefers to keep PRs focused on their main objective and defer implementation improvements or logic fixes to future dedicated PRs. For maxGraph, refactoring PRs like Dictionary→Map migration should not include unrelated logic improvements even when valid issues are identified in the migrated code.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 740
File: packages/core/src/util/requestUtils.ts:79-106
Timestamp: 2025-03-31T08:32:17.055Z
Learning: PR #740 is focused on reorganizing code into namespaces (guiUtils and requestUtils) without changing any implementations. Implementation improvements should be suggested for future PRs.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 849
File: packages/html/stories/DragSource.stories.js:98-101
Timestamp: 2025-06-13T07:48:10.300Z
Learning: User tbouffard prefers answers in English; avoid switching to other languages in future replies.
📚 Learning: 2025-01-28T16:22:25.804Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 593
File: .github/workflows/create-github-release.yml:42-42
Timestamp: 2025-01-28T16:22:25.804Z
Learning: In the GitHub release notes template for maxGraph, TODO comments are intentionally included to mark sections that must be reviewed by maintainers before publishing the release. These TODOs should not be removed or converted to validation steps as they are part of the release review process.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-12-11T08:46:43.160Z
Learnt from: CR
Repo: maxGraph/maxGraph PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T08:46:43.160Z
Learning: Applies to packages/core/src/**/*.{ts,tsx} : Define styles as objects conforming to `CellStyle` type as documented in `packages/core/src/types.ts`.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
📚 Learning: 2025-04-22T16:34:40.309Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 774
File: packages/ts-example-selected-features/package.json:11-13
Timestamp: 2025-04-22T16:34:40.309Z
Learning: In the maxGraph project, TypeScript is defined as a dependency in the root package.json (~5.8.2) and not in individual package.json files for example packages. The build scripts in example packages can use `tsc` commands because the TypeScript dependency is hoisted in the monorepo structure.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
📚 Learning: 2025-04-29T13:29:45.122Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 791
File: packages/core/src/view/style/edge/Segment.ts:26-35
Timestamp: 2025-04-29T13:29:45.122Z
Learning: In the maxGraph project, JSDoc `{link}` references to symbols don't need to be imported in the current file to work correctly. TypeDoc can resolve symbols across the entire project namespace, not just within the current file, which is common in modern documentation systems and IDEs.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
📚 Learning: 2025-04-28T08:24:39.831Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 785
File: packages/core/src/view/style/register.ts:19-19
Timestamp: 2025-04-28T08:24:39.831Z
Learning: In the maxGraph project, the Perimeter namespace is defined in the './builtin-style-elements' file as a namespace export ('export * as Perimeter'), making this the correct import location for accessing the Perimeter namespace.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
  • packages/html/stories/Stencils.stories.ts
📚 Learning: 2025-04-28T08:24:39.831Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 785
File: packages/core/src/view/style/register.ts:19-19
Timestamp: 2025-04-28T08:24:39.831Z
Learning: In the maxGraph project, the Perimeter namespace is defined in the 'builtin-style-elements.ts' file using the statement 'export * as Perimeter from './perimeter';'. To access the Perimeter namespace in other files, they must import from './builtin-style-elements' instead of directly from './perimeter', as part of the tree-shaking optimization.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
  • packages/html/stories/Stencils.stories.ts
📚 Learning: 2025-05-13T12:54:55.231Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 826
File: packages/js-example-nodejs/src/index.cjs:64-69
Timestamp: 2025-05-13T12:54:55.231Z
Learning: For example code in the maxGraph repository, maintainers prefer to keep scripts simple without error handling to focus on demonstrating core functionality, especially in demonstration scripts like those in packages/js-example-nodejs.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
📚 Learning: 2025-04-24T12:34:10.366Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 776
File: packages/core/src/view/Graph.ts:85-92
Timestamp: 2025-04-24T12:34:10.366Z
Learning: The Graph class intentionally doesn't use collaborators (cellRenderer, selectionModel, view) from options in initializeCollaborators, as it's designed to replicate the previous implementation using only its factory methods for backward compatibility.

Applied to files:

  • packages/html/stories/Stylesheet.stories.ts
  • packages/html/stories/Events.stories.ts
📚 Learning: 2024-11-24T17:28:08.023Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 582
File: packages/core/__tests__/view/handler/config.test.ts:0-0
Timestamp: 2024-11-24T17:28:08.023Z
Learning: In `packages/core/__tests__/view/handler/config.test.ts`, when writing Jest tests in TypeScript for configuration reset functions, small duplication is acceptable if it maintains test clarity and readability. Avoid refactoring tests in ways that could make them harder to understand, especially when future use cases might require specific checks.

Applied to files:

  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
  • packages/core/__tests__/view/Graph.test.ts
📚 Learning: 2025-12-11T08:46:43.160Z
Learnt from: CR
Repo: maxGraph/maxGraph PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T08:46:43.160Z
Learning: Applies to packages/core/__tests__/**/*.test.{ts,tsx} : Tests should use Jest with jsdom environment and be located in `packages/core/__tests__/` mirroring the `src/` directory structure.

Applied to files:

  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
📚 Learning: 2025-12-11T08:46:43.160Z
Learnt from: CR
Repo: maxGraph/maxGraph PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T08:46:43.160Z
Learning: Applies to packages/core/__tests__/**/*.test.{ts,tsx} : Import paths in tests should omit `.js` extension (handled by moduleNameMapper).

Applied to files:

  • packages/core/__tests__/view/handler/TooltipHandler.test.ts
  • packages/core/__tests__/view/Graph.test.ts
📚 Learning: 2025-04-24T12:33:36.243Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 776
File: packages/core/src/view/Graph.ts:77-83
Timestamp: 2025-04-24T12:33:36.243Z
Learning: All register functions in maxGraph (`registerDefaultShapes`, `registerDefaultEdgeStyles`, `registerDefaultPerimeters`, and `registerDefaultEdgeMarkers`) have internal state flags to prevent duplicate registrations, making them inherently idempotent.

Applied to files:

  • packages/html/stories/Stencils.stories.ts
📚 Learning: 2025-02-08T16:39:11.178Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 660
File: packages/core/src/view/geometry/node/StencilShapeRegistry.ts:0-0
Timestamp: 2025-02-08T16:39:11.178Z
Learning: The StencilShapeRegistry.getStencil method's implementation using non-null assertion (!) is validated by dedicated tests to handle null/undefined inputs correctly, returning undefined in such cases.

Applied to files:

  • packages/html/stories/Stencils.stories.ts
📚 Learning: 2025-12-11T08:46:43.160Z
Learnt from: CR
Repo: maxGraph/maxGraph PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T08:46:43.160Z
Learning: Use `Graph` class for prototyping/demos with automatic setup of defaults.

Applied to files:

  • packages/html/stories/Events.stories.ts
🧬 Code graph analysis (2)
packages/html/stories/HelloPort.stories.ts (1)
packages/core/src/view/plugins/TooltipHandler.ts (1)
  • getTooltipForCell (412-419)
packages/core/__tests__/view/handler/TooltipHandler.test.ts (1)
packages/core/__tests__/utils.ts (1)
  • createGraphWithoutPlugins (29-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build
  • GitHub Check: build (ubuntu-24.04)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (windows-2022)
🔇 Additional comments (12)
packages/core/src/view/AbstractGraph.ts (1)

532-535: LGTM! Method correctly handles missing plugin.

The optional chaining ensures that calling setTooltips(true) on a graph without the TooltipHandler plugin does not throw an error, which aligns with the test coverage in Graph.test.ts.

packages/html/stories/Events.stories.ts (1)

109-114: LGTM! Correctly migrated to plugin-based tooltip customization.

The tooltip customization now uses the TooltipHandler plugin instead of overriding graph methods, which aligns with the PR's goal of moving tooltip logic to the plugin. The non-null assertion is safe here since getDefaultPlugins() includes the TooltipHandler.

packages/html/stories/Stylesheet.stories.ts (1)

66-76: LGTM! Plugin-based tooltip correctly implemented.

The migration to TooltipHandler-based tooltips is correct. Note that this story overrides getTooltip (which receives a CellState) rather than getTooltipForCell, which is appropriate given the tooltip logic needs access to the cell state. The references to this.graph.getLabel(...) are correct since this refers to the TooltipHandler instance.

packages/html/stories/Stencils.stories.ts (1)

196-199: LGTM! Consistent with the plugin-based tooltip pattern.

The tooltip customization correctly uses the TooltipHandler plugin, maintaining consistency with the other migrated stories. The non-null assertion is safe given the use of getDefaultPlugins().

packages/html/stories/Wires.stories.ts (2)

381-405: LGTM! Excellent use of plugin subclassing.

This story demonstrates a cleaner pattern for customizing tooltips by extending TooltipHandler rather than overriding methods at runtime. This approach is more type-safe and maintainable. The recursive tooltip building logic correctly uses super.getTooltipForCell(cell) to get the base tooltip.


732-732: Consistent with the subclassing approach.

Replacing TooltipHandler with MyCustomTooltipHandler in the plugins array correctly integrates the custom tooltip logic. This demonstrates that plugin-based customization can be done through either:

  1. Runtime method override (as in Events/Stylesheet/Stencils stories), or
  2. Subclassing (as done here)

Both patterns are valid; subclassing may be preferable for complex customizations.

packages/core/__tests__/view/Graph.test.ts (1)

20-24: LGTM! Test correctly validates setTooltips with missing plugin.

The test verifies that calling setTooltips(true) on a graph without the TooltipHandler plugin does not throw an error, which confirms the optional chaining implementation in AbstractGraph.setTooltips works as intended.

packages/html/stories/UserObject.stories.ts (1)

170-180: Plugin-based tooltip override implementation looks good.

The pattern correctly captures the original method, overrides it with proper this binding via regular function, and delegates to the original for non-edge cases.

packages/html/stories/HelloPort.stories.ts (1)

79-94: Well-structured plugin-based tooltip override.

The implementation correctly handles the null-safety check for edge terminals (line 86) and properly delegates to the original method. This serves as a good reference pattern for other stories.

packages/core/src/view/plugins/TooltipHandler.ts (3)

29-34: Imports correctly structured with .js extensions and type-only imports.

The new imports follow the coding guidelines: .js file extensions for ESM compliance, and type keyword for type-only imports like EventSource, Shape, SelectionCellsHandler, and Cell.


395-419: Well-documented method with backward compatibility.

The JSDoc includes a clear usage example, and the implementation maintains backward compatibility with mxGraph by checking for the cell's getTooltip method before falling back to convertValueToString.


36-45: Class documentation addresses the SelectionCellsHandler dependency.

The JSDoc now includes the important note about SelectionCellsHandler requirement for full edge tooltip support, addressing the concern from the previous review.

@sonarqubecloud
Copy link

@maxGraph maxGraph deleted a comment from sonarqubecloud bot Dec 18, 2025
@tbouffard tbouffard merged commit 3f073e2 into main Dec 19, 2025
12 checks passed
@tbouffard tbouffard deleted the refactor/tree-shaking_tooltip_mixin_code_to_tooltip_plugin branch December 19, 2025 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant