Repository: maxGraph/maxGraph
Pull request #801: refactor!: remove the ELBOW enum
Author: login: tbouffard
Labels: name: refactor
description: Code refactoring
Created: 2025-05-03T18:14:40Z | Merged: 2025-05-03T19:11:41Z

Introduce the `ElbowValue` type.

Also add a script to build all examples.
This simplifies the maintenance of the GH workflow and let easily built all examples locally with a single command.

BREAKING CHANGES: the ELBOW enum has been removed. Use the `ElbowValue` type instead.



## Notes

Covers #378

### Impact on the size of the examples

| Example                      | v0.19.0 | With #795 and #796 | With #798, #799, #800 and #801  |
|-----------------------------|---------|------------|------------|
| js-example                  | 475.30 kB | 474.01 kB |  470.31 kB |
| js-example-selected-features | 415.10 kB | 413.98 kB | 410.72 kB |
| js-example-without-default  | 347.33 kB | 346.21 kB | 343.09 kB |
| ts-example                  | 438.64 kB | 437.42 kB | 435.02 kB |
| ts-example-selected-features | 380.70 kB |  379.54 kB | 377.37 kB |
| ts-example-without-default  | 329.90 kB | 328.74 kB | 326.63 kB |


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **Breaking Changes**
  - The enum for elbow styles has been removed and replaced with a string type. If you previously used `constants.ELBOW`, update your code to use the string values `'horizontal'` or `'vertical'` directly.

- **Documentation**
  - The changelog has been updated to reflect the removal of the elbow enum and its replacement with a string type.

- **Style**
  - Code comments and examples now use string literals for elbow styles instead of the removed enum.

- **Chores**
  - Build configuration updated to slightly lower chunk size warning limits in multiple example projects.
  - A new script was added to streamline building all example projects collectively.
  - The CI workflow was improved by consolidating multiple build steps into a single streamlined step.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 08a051d636..5e519ed31b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -55,20 +55,10 @@ jobs:
           path: packages/core/coverage/lcov-report
       - name: Test TypeScript support
         run: npm test -w packages/ts-support
-      - name: Build ts-example (custom shapes)
-        run: npm run build -w packages/ts-example
-      - name: Build ts-example (selected features)
-        run: npm run build -w packages/ts-example-selected-features
-      - name: Build ts-example (without defaults)
-        run: npm run build -w packages/ts-example-without-defaults
+      - name: Build all examples
+        run: ./build-all-examples.bash
       - name: Build Storybook mini-site
         run: npm run build -w packages/html
-      - name: Build js-example
-        run: npm run build -w packages/js-example
-      - name: Build js-example (selected features)
-        run: npm run build -w packages/js-example-selected-features
-      - name: Build js-example (without defaults)
-        run: npm run build -w packages/js-example-without-defaults
       - name: Upload all examples as artifact
         uses: actions/upload-artifact@v4
         with:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fe87fdb8b..a2d5f305d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ _**Note:** Yet to be released breaking changes appear here._
   - `constants.ARROW` --> `ArrowValue`
   - `constants.DIRECTION` --> `DirectionValue`
   - `constants.EDGESTYLE` --> `EdgeStyleValue`
+  - `constants.ELBOW` --> `ElbowValue`
   - `constants.PERIMETER` --> `PerimeterValue`
   - `constants.RENDERING_HINT`: no replacement as it wasn't used
   - `constants.SHAPE` --> `ShapeValue`
diff --git a/build-all-examples.bash b/build-all-examples.bash
new file mode 100755
index 0000000000..a66d26e7e5
--- /dev/null
+++ b/build-all-examples.bash
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# This script builds all examples in the packages directory.
+echo "Building all examples..."
+
+for dir in packages/ts-example* packages/js-example*; do
+  if [ -d "$dir" ]; then
+    echo
+    echo "##################################################"
+    echo "Building $dir"
+    echo "##################################################"
+    (cd "$dir" && npm run build)
+  fi
+done
+
+echo "All examples built successfully."
diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts
index 4c16c06072..e3195b9ac9 100644
--- a/packages/core/src/types.ts
+++ b/packages/core/src/types.ts
@@ -203,10 +203,9 @@ export type CellStateStyle = {
    * This defines how the three-segment orthogonal edge style leaves its terminal vertices.
    * The 'vertical' style leaves the terminal vertices at the top and bottom sides.
    *
-   * The possible values are 'horizontal' and 'vertical'.
    * @default 'horizontal'
    */
-  elbow?: 'horizontal' | 'vertical';
+  elbow?: ElbowValue;
   /**
    * This defines the style of the end arrow marker.
    *
@@ -1468,3 +1467,8 @@ export type DialectValue =
   | 'strictHtml'
   /** The SVG display dialect name. */
   | 'svg';
+
+/**
+ * @since 0.20.0
+ */
+export type ElbowValue = 'horizontal' | 'vertical';
diff --git a/packages/core/src/util/Constants.ts b/packages/core/src/util/Constants.ts
index d7f5809abb..0cc2a89187 100644
--- a/packages/core/src/util/Constants.ts
+++ b/packages/core/src/util/Constants.ts
@@ -438,11 +438,3 @@ export const DIRECTION_MASK = {
   /** All directions. */
   ALL: 15,
 };
-
-/**
- * Default is horizontal.
- */
-export enum ELBOW {
-  VERTICAL = 'vertical',
-  HORIZONTAL = 'horizontal',
-}
diff --git a/packages/core/src/view/handler/ElbowEdgeHandler.ts b/packages/core/src/view/handler/ElbowEdgeHandler.ts
index 97261f9bde..5f642dac6f 100644
--- a/packages/core/src/view/handler/ElbowEdgeHandler.ts
+++ b/packages/core/src/view/handler/ElbowEdgeHandler.ts
@@ -17,7 +17,7 @@ limitations under the License.
 */
 
 import EdgeHandler from './EdgeHandler';
-import { CURSOR, ELBOW } from '../../util/Constants';
+import { CURSOR } from '../../util/Constants';
 import InternalEvent from '../event/InternalEvent';
 import Point from '../geometry/Point';
 import Rectangle from '../geometry/Rectangle';
@@ -113,7 +113,7 @@ class ElbowEdgeHandler extends EdgeHandler {
   getCursorForBend() {
     return this.state.style.edgeStyle === 'topToBottomEdgeStyle' ||
       (this.state.style.edgeStyle === 'elbowEdgeStyle' &&
-        this.state.style.elbow === ELBOW.VERTICAL)
+        this.state.style.elbow === 'vertical')
       ? 'row-resize'
       : 'col-resize';
   }
diff --git a/packages/core/src/view/mixins/EdgeMixin.type.ts b/packages/core/src/view/mixins/EdgeMixin.type.ts
index a7f96e3cea..ffb89e5a9d 100644
--- a/packages/core/src/view/mixins/EdgeMixin.type.ts
+++ b/packages/core/src/view/mixins/EdgeMixin.type.ts
@@ -129,8 +129,8 @@ declare module '../AbstractGraph' {
      * graph.flipEdge = function(edge) {
      *   if (edge) {
      *     const style = this.getCurrentCellStyle(edge);
-     *     const elbow = style.elbow ?? Constants.ELBOW.HORIZONTAL;
-     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.ELBOW.VERTICAL : Constants.ELBOW.HORIZONTAL;
+     *     const elbow = style.elbow ?? 'horizontal';
+     *     const value = (elbow == 'horizontal') ? 'vertical' : 'horizontal';
      *     this.setCellStyles('elbow', value, [edge]);
      *   }
      * };
diff --git a/packages/core/src/view/style/edge/Elbow.ts b/packages/core/src/view/style/edge/Elbow.ts
index 37161ae3ce..61784a89e7 100644
--- a/packages/core/src/view/style/edge/Elbow.ts
+++ b/packages/core/src/view/style/edge/Elbow.ts
@@ -20,7 +20,6 @@ import { SideToSide } from './SideToSide';
 import { TopToBottom } from './TopToBottom';
 import CellState from '../../cell/CellState';
 import Point from '../../geometry/Point';
-import { ELBOW } from '../../../util/Constants';
 
 import type { EdgeStyleFunction } from '../../../types';
 
@@ -67,7 +66,7 @@ export const ElbowConnector: EdgeStyleFunction = (
     }
   }
 
-  if (!horizontal && (vertical || state.style.elbow === ELBOW.VERTICAL)) {
+  if (!horizontal && (vertical || state.style.elbow === 'vertical')) {
     TopToBottom(state, source, target, points, result);
   } else {
     SideToSide(state, source, target, points, result);
diff --git a/packages/html/stories/Indicators.stories.js b/packages/html/stories/Indicators.stories.js
index 1830b2be60..d948936973 100644
--- a/packages/html/stories/Indicators.stories.js
+++ b/packages/html/stories/Indicators.stories.js
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import { Graph, EdgeStyle, constants, KeyHandler } from '@maxgraph/core';
+import { Graph, EdgeStyle, KeyHandler } from '@maxgraph/core';
 import { globalTypes, globalValues } from './shared/args.js';
 import { createGraphContainer } from './shared/configure.js';
 
@@ -58,7 +58,7 @@ const Template = ({ label, ...args }) => {
   style = graph.getStylesheet().getDefaultEdgeStyle();
 
   style.edge = EdgeStyle.ElbowConnector;
-  style.elbow = constants.ELBOW.VERTICAL;
+  style.elbow = 'vertical';
   style.rounded = true;
 
   // Gets the default parent for inserting new cells. This
diff --git a/packages/ts-example-selected-features/vite.config.js b/packages/ts-example-selected-features/vite.config.js
index 66728daebe..f4bab01b25 100644
--- a/packages/ts-example-selected-features/vite.config.js
+++ b/packages/ts-example-selected-features/vite.config.js
@@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => {
           },
         },
       },
-      chunkSizeWarningLimit: 380, // @maxgraph/core
+      chunkSizeWarningLimit: 378, // @maxgraph/core
     },
   };
 });
diff --git a/packages/ts-example-without-defaults/vite.config.js b/packages/ts-example-without-defaults/vite.config.js
index 4f7832c409..cffbd82595 100644
--- a/packages/ts-example-without-defaults/vite.config.js
+++ b/packages/ts-example-without-defaults/vite.config.js
@@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => {
           },
         },
       },
-      chunkSizeWarningLimit: 329, // @maxgraph/core
+      chunkSizeWarningLimit: 327, // @maxgraph/core
     },
   };
 });
diff --git a/packages/ts-example/vite.config.js b/packages/ts-example/vite.config.js
index 8ba580d770..ae63a91e86 100644
--- a/packages/ts-example/vite.config.js
+++ b/packages/ts-example/vite.config.js
@@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => {
           },
         },
       },
-      chunkSizeWarningLimit: 438, // @maxgraph/core
+      chunkSizeWarningLimit: 436, // @maxgraph/core
     },
   };
 });


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 5f0b2f35d6b13b2e28bc7da0664043fbcec89d1f and 48160dc57ddca68eec4313ad91db25b19a1d613a.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `CHANGELOG.md` (1 hunks)
* `packages/core/src/types.ts` (2 hunks)
* `packages/core/src/util/Constants.ts` (0 hunks)
* `packages/core/src/view/handler/ElbowEdgeHandler.ts` (2 hunks)
* `packages/core/src/view/mixins/EdgeMixin.type.ts` (1 hunks)
* `packages/core/src/view/style/edge/Elbow.ts` (1 hunks)
* `packages/html/stories/Indicators.stories.js` (2 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* packages/core/src/util/Constants.ts

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: build (windows-2022)
* GitHub Check: build (macos-14)
* GitHub Check: build (ubuntu-22.04)
* GitHub Check: build

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>packages/core/src/view/style/edge/Elbow.ts (1)</summary>

`69-69`: **String literal replacement looks good.**

The replacement of `ELBOW.VERTICAL` enum with the string literal `'vertical'` aligns with the PR objective to remove the ELBOW enum in favor of the new `ElbowValue` type.

</details>
<details>
<summary>packages/html/stories/Indicators.stories.js (2)</summary>

`18-18`: **Import statement correctly updated.**

The removal of the `constants` import aligns with the PR objective of removing the ELBOW enum.

---

`61-61`: **String literal replacement looks good.**

The replacement of `constants.ELBOW.VERTICAL` with the string literal `'vertical'` maintains the same behavior while removing the dependency on the enum.

</details>
<details>
<summary>CHANGELOG.md (1)</summary>

`19-19`: **Breaking change properly documented.**

The changelog has been correctly updated to document the breaking change from `constants.ELBOW` to `ElbowValue`, providing clear migration guidance for users.

</details>
<details>
<summary>packages/core/src/view/handler/ElbowEdgeHandler.ts (2)</summary>

`20-20`: **Import statement correctly updated.**

The import statement has been updated to only import `CURSOR` from Constants, removing the `ELBOW` enum import which is being removed from the codebase.

---

`116-116`: **String literal replacement looks good.**

The replacement of `ELBOW.VERTICAL` enum with the string literal `'vertical'` maintains the same behavior while aligning with the PR objective to remove the enum.

</details>
<details>
<summary>packages/core/src/types.ts (2)</summary>

`1471-1474`: **Good addition of the ElbowValue type alias.**

Adding the type alias to replace the enum is a clean approach and aligns with TypeScript best practices for string literal types.

---

`208-208`: **Appropriate type update for elbow property.**

The property now uses the newly defined ElbowValue type alias instead of an inline union type, maintaining consistency throughout the codebase.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-03T18:16:54Z
user: login: tbouffard
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-03T18:25:57Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-03T18:26:16Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>build-all-examples.bash (1)</summary><blockquote>

`7-15`: **Handle unmatched globs and consider parallel builds**  
By default, if no directories match the glob, the loop will iterate once with the literal pattern. You may want to enable `nullglob` or add an explicit check to avoid silent skips. Additionally, for faster CI runs, you could parallelize builds (e.g., with `xargs -P` or GNU `parallel`).  

Example diff to enable `nullglob`:
```diff
 #!/usr/bin/env bash
-set -euo pipefail
+set -euo pipefail
+shopt -s nullglob
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 06188330703be5579a942b29aef14e93124d66b0 and c9258fd243e0fd5b01c5ac9ef1a3644de66f6a82.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/workflows/build.yml` (1 hunks)
* `build-all-examples.bash` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* .github/workflows/build.yml

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: build (windows-2022)

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>build-all-examples.bash (3)</summary>

`1-2`: **Robust shell setup with strict mode**  
Using `#!/usr/bin/env bash` combined with `set -euo pipefail` is excellent for catching errors early and avoiding unbound variables.

---

`4-5`: **Clear startup messaging**  
The comment and initial `echo` clearly communicate the script’s purpose to users.

---

`17-18`: **Confirm overall success**  
The final `echo` provides clear feedback once all builds complete.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-03T18:49:20Z

Review comments:
diff_hunk: @@ -130,7 +130,7 @@ declare module '../AbstractGraph' {
      *   if (edge) {
      *     const style = this.getCurrentCellStyle(edge);
      *     const elbow = style.elbow ?? Constants.ELBOW.HORIZONTAL;
-     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.ELBOW.VERTICAL : Constants.ELBOW.HORIZONTAL;
+     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.'vertical' : Constants.ELBOW.HORIZONTAL;
path: packages/core/src/view/mixins/EdgeMixin.type.ts
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix syntax error in code example.**

The updated example contains a syntax error where it incorrectly mixes string literals with the Constants namespace. Since you're removing the ELBOW enum, the code example should be updated to use string literals directly.


```diff
-     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.'vertical' : Constants.ELBOW.HORIZONTAL;
+     *     const value = (elbow == 'horizontal') ? 'vertical' : 'horizontal';
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
     *     const value = (elbow == 'horizontal') ? 'vertical' : 'horizontal';
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->

✅ Addressed in commits f34d691 to 0618833
created_at: 2025-05-03T18:16:53Z
author_association: NONE
diff_hunk: @@ -130,7 +130,7 @@ declare module '../AbstractGraph' {
      *   if (edge) {
      *     const style = this.getCurrentCellStyle(edge);
      *     const elbow = style.elbow ?? Constants.ELBOW.HORIZONTAL;
-     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.ELBOW.VERTICAL : Constants.ELBOW.HORIZONTAL;
+     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.'vertical' : Constants.ELBOW.HORIZONTAL;
path: packages/core/src/view/mixins/EdgeMixin.type.ts
user: login: tbouffard
body: Good catch, fixed in 06188330
created_at: 2025-05-03T18:25:56Z
author_association: MEMBER
diff_hunk: @@ -130,7 +130,7 @@ declare module '../AbstractGraph' {
      *   if (edge) {
      *     const style = this.getCurrentCellStyle(edge);
      *     const elbow = style.elbow ?? Constants.ELBOW.HORIZONTAL;
-     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.ELBOW.VERTICAL : Constants.ELBOW.HORIZONTAL;
+     *     const value = (elbow == Constants.ELBOW.HORIZONTAL) ? Constants.'vertical' : Constants.ELBOW.HORIZONTAL;
path: packages/core/src/view/mixins/EdgeMixin.type.ts
user: login: coderabbitai[bot]
body: @tbouffard Thanks for confirming the fix! That ensures the code example correctly uses string literals instead of the removed ELBOW enum. 👍

---

<!-- This is an auto-generated comment: tweet message by coderabbit.ai -->

If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Simplify%20your%20code%20by%20replacing%20removed%20enums%20with%20direct%20string%20literals%20to%20avoid%20syntax%20errors.%20Cleaner%2C%20clearer%2C%20and%20less%20error-prone!%20Try%20%40coderabbitai%20for%20smart%20code%20fixes!%20%F0%9F%94%A7%E2%9C%A8&url=https%3A%2F%2Fgithub.com%2FmaxGraph%2FmaxGraph%2Fpull%2F801%23discussion_r2072441746)?

Thank you for using CodeRabbit!

<!-- end of auto-generated comment: tweet message by coderabbit.ai -->




<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@tbouffard Thanks for confirming the fix! That ensures the code example correctly uses string literals instead of the removed ELBOW enum. 👍

---

&lt;!-- This is an auto-generated comment: tweet message by coderabbit.ai --&gt;

If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Simplify%20your%20code%20by%20replacing%20removed%20enums%20with%20direct%20string%20literals%20to%20avoid%20syntax%20errors.%20Cleaner%2C%20clearer%2C%20and%20less%20error-prone!%20Try%20%40coderabbitai%20for%20smart%20code%20fixes!%20%F0%9F%94%A7%E2%9C%A8&url=https%3A%2F%2Fgithub.com%2FmaxGraph%2FmaxGraph%2Fpull%2F801%23discussion_r2072441746)?

Thank you for using CodeRabbit!

&lt;!-- end of auto-generated comment: tweet message by coderabbit.ai --&gt;

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-03T18:26:16Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-03T18:14:47Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: rate limited by coderabbit.ai -->

> [!WARNING]
> ## Rate limit exceeded
> 
> @tbouffard has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait **17 minutes and 4 seconds** before requesting another review.
> 
> <details>
> <summary>⌛ How to resolve this issue?</summary>
> 
> After the wait time has elapsed, a review can be triggered using the `@coderabbitai review` command as a PR comment. Alternatively, push new commits to this PR.
> 
> We recommend that you space out your commits to avoid hitting the rate limit.
> 
> </details>
> 
> 
> <details>
> <summary>🚦 How do rate limits work?</summary>
> 
> CodeRabbit enforces hourly rate limits for each developer per organization.
> 
> Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
> 
> Please see our [FAQ](https://docs.coderabbit.ai/faq) for further information.
> 
> </details>
> 
> <details>
> <summary>📥 Commits</summary>
> 
> Reviewing files that changed from the base of the PR and between c9258fd243e0fd5b01c5ac9ef1a3644de66f6a82 and f7ca58b7b17f1a401d5587bdd7275ae4475fc58b.
> 
> </details>
> 
> <details>
> <summary>📒 Files selected for processing (1)</summary>
> 
> * `build-all-examples.bash` (1 hunks)
> 
> </details>

<!-- end of auto-generated comment: rate limited by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This change removes the `ELBOW` enum from the codebase and replaces its usage with a new string literal type alias, `ElbowValue`, which represents `'horizontal' | 'vertical'`. All references to the enum are updated to use string literals or the new type alias. Documentation and code comments are adjusted accordingly, and imports of the removed enum are eliminated from affected files. No changes are made to the logic or structure of public APIs, except for the updated type annotation.

## Changes

| File(s)                                                                 | Change Summary                                                                                          |
|-------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| `packages/core/src/util/Constants.ts`                                   | Removed the exported `ELBOW` enum and its members.                                                     |
| `packages/core/src/types.ts`                                            | Introduced exported type alias `ElbowValue`; updated `CellStateStyle.elbow` to use `ElbowValue`.       |
| `packages/core/src/view/handler/ElbowEdgeHandler.ts`<br>`packages/core/src/view/style/edge/Elbow.ts` | Removed import of `ELBOW` and replaced enum usage with string literals in conditional checks.           |
| `packages/core/src/view/mixins/EdgeMixin.type.ts`                      | Updated code comment example to use string literal instead of `Constants.ELBOW.VERTICAL`.              |
| `packages/html/stories/Indicators.stories.js`                          | Removed import of `constants` and replaced `constants.ELBOW.VERTICAL` with string literal `'vertical'`.|
| `.github/workflows/build.yml`<br>`build-all-examples.bash`             | Consolidated example builds into a single script; added new script to build all example packages.      |
| `packages/ts-example*/vite.config.js`                                  | Decreased `chunkSizeWarningLimit` values slightly in all three example Vite config files.              |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant CellStateStyle
    participant ElbowEdgeHandler
    participant Elbow

    User->>CellStateStyle: Set elbow property (ElbowValue)
    ElbowEdgeHandler->>CellStateStyle: Read elbow property
    ElbowEdgeHandler->>ElbowEdgeHandler: Compare elbow to 'vertical' or 'horizontal'
    Elbow->>CellStateStyle: Access elbow property
    Elbow->>Elbow: Compare elbow to 'vertical'
```

## Possibly related PRs

- maxGraph/maxGraph#701: Refined the `elbow` type from a string literal union to a named type alias and removed the related enum, continuing the type refinement and usage consistency for `CellStateStyle.elbow`.
- maxGraph/maxGraph#800: Removed the `DIALECT` enum and replaced it with a string literal union type `DialectValue`, similar to the `ELBOW` enum removal and replacement with `ElbowValue`.

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=maxGraph/maxGraph&utm_content=801):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-03T18:52:59Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=maxGraph_maxGraph&pullRequest=801) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=maxGraph_maxGraph&pullRequest=801&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=maxGraph_maxGraph&pullRequest=801&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=maxGraph_maxGraph&pullRequest=801&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=maxGraph_maxGraph&pullRequest=801&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=maxGraph_maxGraph&pullRequest=801&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=maxGraph_maxGraph&pullRequest=801)


author_association: NONE