Skip to content

Commit b5ccb9e

Browse files
Merge pull request #497 from synergycodes/main
Release v0.9.0
2 parents 33ee754 + 70112e6 commit b5ccb9e

File tree

384 files changed

+11565
-1590
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

384 files changed

+11565
-1590
lines changed

.github/workflows/pr-check.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,13 @@ jobs:
3535

3636
- name: Run unit tests
3737
run: pnpm run test
38+
39+
- name: Check API report
40+
run: pnpm run api:check
41+
42+
- name: Upload API report if check failed
43+
if: failure()
44+
uses: actions/upload-artifact@v4
45+
with:
46+
name: api-report
47+
path: packages/ng-diagram/api-report/ng-diagram.api.md

.github/workflows/publish-npm.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ jobs:
2020
node-version: 22
2121
registry-url: 'https://registry.npmjs.org'
2222

23+
- name: Upgrade npm for trusted publishing
24+
run: npm install -g npm@latest
25+
2326
- name: Setup pnpm
2427
uses: pnpm/action-setup@v4
2528
with:
@@ -41,8 +44,5 @@ jobs:
4144
run: cd packages/ng-diagram && pnpm build:prod
4245

4346
- name: Publish to npm
44-
run: |
45-
cd packages/ng-diagram/dist/ng-diagram
46-
npm publish --provenance --access public
47-
env:
48-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
47+
run: npm publish
48+
working-directory: packages/ng-diagram/dist/ng-diagram

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ pnpm-lock.yaml
1616
**/dist
1717

1818
**/src/content/docs/api/**/*.md
19+
**/api-report/*.md

CHANGELOG.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
## [0.9.0] - 2025-12-12
11+
12+
### Added
13+
14+
- API stability and deprecation policy documentation with defined stability levels and Angular version support matrix ([#462](https://github.com/synergycodes/ng-diagram/pull/462))
15+
- API Extractor integration for automated breaking change detection with CI validation ([#462](https://github.com/synergycodes/ng-diagram/pull/462))
16+
- Landing page diagram example in documentation ([#464](https://github.com/synergycodes/ng-diagram/pull/464))
17+
- [Floating edges](/docs/guides/edges/floating-edges/) for edges with no ports specified ([#465](https://github.com/synergycodes/ng-diagram/pull/465))
18+
- [Ports with custom content](/docs/guides/nodes/ports/#custom-content) - ports can now render custom Angular components instead of simple circles ([#468](https://github.com/synergycodes/ng-diagram/pull/468))
19+
- [`hideWatermark`](/docs/api/types/configuration/flowconfig/#hidewatermark) config option to hide the ngDiagram watermark via diagram configuration ([#469](https://github.com/synergycodes/ng-diagram/pull/469))
20+
- Expose [`computePartsBounds`](/docs/api/services/ngdiagrammodelservice/#computepartsbounds) method in API ([#477](https://github.com/synergycodes/ng-diagram/pull/477))
21+
- Added overload to [`getOverlappingNodes`](/docs/api/services/ngdiagrammodelservice/#getoverlappingnodes) to accept `Node` object in addition to node ID, supporting cases when the node object has newer data than the node in state (e.g., within middlewares) ([#486](https://github.com/synergycodes/ng-diagram/pull/486))
22+
- [`modelActionTypes`](/docs/api/types/middleware/middlewarecontext/#modelactiontypes) property on `MiddlewareContext` - an array containing all action types that triggered the middleware execution. For transactions, this includes the transaction name followed by all action types from commands executed within the transaction. For single commands, this is a single-element array ([#489](https://github.com/synergycodes/ng-diagram/pull/489))
23+
- Add grab cursor on background when panning ([#479](https://github.com/synergycodes/ng-diagram/pull/479))
24+
- Disable diagram panning by config [`viewportPanningEnabled`](/docs/api/types/configuration/flowconfig/#viewportpanningenabled) ([#480](https://github.com/synergycodes/ng-diagram/pull/480))
25+
- [Async transaction](/docs/guides/transactions/#async-transactions) support - transactions now accept async callbacks, allowing asynchronous operations like data fetching before adding or modifying the diagram ([#493](https://github.com/synergycodes/ng-diagram/pull/493))
26+
- [`waitForMeasurements`](/docs/guides/transactions/#waitformeasurements) transaction option - ensures the transaction promise resolves only after all DOM measurements (node sizes, port positions, edge labels) are complete. Useful when performing viewport operations like `zoomToFit()` after adding or modifying elements ([#493](https://github.com/synergycodes/ng-diagram/pull/493))
27+
28+
### Changed
29+
30+
- Standardized error messages across the ng-diagram library ([#463](https://github.com/synergycodes/ng-diagram/pull/463))
31+
32+
### Fixed
33+
34+
- Fixed misleading error when destroying `NgDiagramModelService` after engine is already destroyed. The error incorrectly reported "Library engine not initialized yet". Now the service checks if engine is available and skips listener cleanup if already destroyed. ([#466](https://github.com/synergycodes/ng-diagram/issues/466) - thanks for finding this [@Filipstrozik](https://github.com/Filipstrozik) 💪)
35+
- Fixed keyboard movement of nodes with arrow keys when using large snap step values ([#461](https://github.com/synergycodes/ng-diagram/pull/461))
36+
- Fixed drag-snapping issues with different snapping configurations. The issue still occurred when dragging multiple nodes at the same hierarchy level (i.e., nodes without groups) ([#470](https://github.com/synergycodes/ng-diagram/pull/470))
37+
- Fixed incorrectly computed measuredBounds for nodes ([#486](https://github.com/synergycodes/ng-diagram/pull/486))
38+
- Fixed missing edge arrowheads in Safari. Safari doesn't support `context-stroke` in SVG markers, so a fallback using inline markers with `currentColor` substitution is now used for Safari compatibility ([#487](https://github.com/synergycodes/ng-diagram/pull/487))
39+
- Fixed copy-paste retaining `groupId` when pasting nodes outside their group. Now `groupId` is only preserved when the group is also copied, with the reference updated to the new group's ID ([#491](https://github.com/synergycodes/ng-diagram/pull/491))
40+
- Fixed zoom to fit not working correctly on diagram initialization ([#492](https://github.com/synergycodes/ng-diagram/pull/492))
41+
- Fixed bullet points styles in the documentation ([#494](https://github.com/synergycodes/ng-diagram/pull/494))
42+
43+
### Deprecated
44+
45+
- `modelActionType` property on `MiddlewareContext` is now deprecated. Use `modelActionTypes` instead, which supports multiple actions from transactions. ([#489](https://github.com/synergycodes/ng-diagram/pull/489))
46+
847
## [0.8.1] - 2025-11-20
948

1049
### Added
@@ -71,7 +110,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
71110

72111
Initial tagged release.
73112

74-
[unreleased]: https://github.com/synergycodes/ng-diagram/compare/v0.8.1...HEAD
113+
[unreleased]: https://github.com/synergycodes/ng-diagram/compare/v0.9.0...HEAD
114+
[0.9.0]: https://github.com/synergycodes/ng-diagram/releases/tag/v0.9.0
75115
[0.8.1]: https://github.com/synergycodes/ng-diagram/releases/tag/v0.8.1
76116
[0.8.0]: https://github.com/synergycodes/ng-diagram/releases/tag/v0.8.0
77117
[0.4.0-beta.5]: https://github.com/synergycodes/ng-diagram/releases/tag/v0.4.0-beta.5

apps/angular-demo/src/app/app.component.ts

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,22 @@ export class AppComponent {
266266
resizable: true,
267267
rotatable: true,
268268
},
269+
{
270+
id: '13',
271+
position: { x: 1200, y: 250 },
272+
data: { text: 'SN 777888' },
273+
type: 'chip',
274+
autoSize: false,
275+
size: { width: 200, height: 200 },
276+
},
277+
{
278+
id: '14',
279+
position: { x: 1200, y: 550 },
280+
data: { text: 'SN 877889' },
281+
type: 'chip',
282+
autoSize: false,
283+
size: { width: 200, height: 300 },
284+
},
269285
],
270286
edges: [
271287
{
@@ -321,8 +337,6 @@ export class AppComponent {
321337
source: '9',
322338
target: '10',
323339
data: { labelPosition: 0.7 },
324-
sourcePort: 'port-right',
325-
targetPort: 'port-left',
326340
type: 'labelled-edge',
327341
routing: 'bezier',
328342
},
@@ -336,6 +350,87 @@ export class AppComponent {
336350
type: 'dashed-edge',
337351
routing: 'orthogonal',
338352
},
353+
{
354+
id: '11',
355+
data: {},
356+
source: '13',
357+
sourcePort: 'port-left-4',
358+
target: '14',
359+
targetPort: 'port-left-1',
360+
targetArrowhead: 'ng-diagram-arrow',
361+
},
362+
{
363+
id: '12',
364+
data: {},
365+
source: '13',
366+
sourcePort: 'port-left-4',
367+
target: '14',
368+
targetPort: 'port-left-2',
369+
targetArrowhead: 'ng-diagram-arrow',
370+
},
371+
{
372+
id: '13',
373+
data: {},
374+
source: '13',
375+
sourcePort: 'port-left-4',
376+
target: '14',
377+
targetPort: 'port-left-3',
378+
targetArrowhead: 'ng-diagram-arrow',
379+
},
380+
{
381+
id: '14',
382+
data: {},
383+
source: '14',
384+
sourcePort: 'port-right-3',
385+
target: '13',
386+
targetPort: 'port-right-4',
387+
targetArrowhead: 'ng-diagram-arrow',
388+
},
389+
{
390+
id: '15',
391+
data: {},
392+
source: '13',
393+
sourcePort: 'port-right-3',
394+
target: '14',
395+
targetPort: 'port-right-4',
396+
targetArrowhead: 'ng-diagram-arrow',
397+
},
398+
{
399+
id: '16',
400+
data: {},
401+
source: '13',
402+
sourcePort: 'port-right-2',
403+
target: '14',
404+
targetPort: 'port-right-1',
405+
targetArrowhead: 'ng-diagram-arrow',
406+
},
407+
{
408+
id: '17',
409+
data: {},
410+
source: '14',
411+
sourcePort: 'port-right-2',
412+
target: '13',
413+
targetPort: 'port-right-2',
414+
targetArrowhead: 'ng-diagram-arrow',
415+
},
416+
{
417+
id: '18',
418+
data: {},
419+
source: '13',
420+
sourcePort: 'port-right-1',
421+
target: '14',
422+
targetPort: 'port-left-4',
423+
targetArrowhead: 'ng-diagram-arrow',
424+
},
425+
{
426+
id: '19',
427+
data: {},
428+
source: '13',
429+
sourcePort: 'port-left-2',
430+
target: '14',
431+
targetPort: 'port-right-1',
432+
targetArrowhead: 'ng-diagram-arrow',
433+
},
339434
],
340435
});
341436
}

apps/angular-demo/src/app/data/node-template.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { NgDiagramNodeTemplateMap } from 'ng-diagram';
2+
import { ChipNodeComponent } from '../node-template/chip-node/chip-node.component';
23
import { CustomizedDefaultNodeComponent } from '../node-template/customized-default-node/customized-default-node.component';
34
import { GroupNodeComponent } from '../node-template/group-node/group-node.component';
45
import { ImageNodeComponent } from '../node-template/image-node/image-node.component';
@@ -11,6 +12,7 @@ export enum NodeTemplateType {
1112
Resizable = 'resizable',
1213
CustomizedDefault = 'customized-default',
1314
Group = 'group',
15+
Chip = 'chip',
1416
}
1517

1618
export const nodeTemplateMap = new NgDiagramNodeTemplateMap([
@@ -19,4 +21,5 @@ export const nodeTemplateMap = new NgDiagramNodeTemplateMap([
1921
[NodeTemplateType.Resizable, ResizableNodeComponent],
2022
[NodeTemplateType.Group, GroupNodeComponent],
2123
[NodeTemplateType.CustomizedDefault, CustomizedDefaultNodeComponent],
24+
[NodeTemplateType.Chip, ChipNodeComponent],
2225
]);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<ng-diagram-node-resize-adornment>
2+
<div class="chip-node">{{ text() }}</div>
3+
<ng-diagram-port id="port-left-1" type="both" style="top: 15%" side="left" originPoint="centerRight">
4+
<div>🔤</div>
5+
</ng-diagram-port>
6+
<ng-diagram-port id="port-left-2" type="both" style="top: 35%" side="left" originPoint="centerRight">
7+
<div>A2</div>
8+
</ng-diagram-port>
9+
<ng-diagram-port id="port-left-3" type="both" style="top: 55%" side="left" originPoint="centerRight">
10+
<div>A3</div>
11+
</ng-diagram-port>
12+
<ng-diagram-port id="port-left-4" type="both" style="top: 75%" side="left" originPoint="centerLeft">
13+
<div>A4</div>
14+
</ng-diagram-port>
15+
<ng-diagram-port id="port-right-1" type="both" style="top: 15%" side="right" originPoint="centerRight">
16+
<div>🔢</div>
17+
</ng-diagram-port>
18+
<ng-diagram-port id="port-right-2" type="both" style="top: 35%" side="right">
19+
<div>🆎</div>
20+
</ng-diagram-port>
21+
<ng-diagram-port id="port-right-3" type="both" style="top: 55%" side="right">
22+
<div style="display: flex; flex-direction: row; gap: 0.25rem; background: #fff; pointer-events: none">
23+
<span>D7</span>
24+
<img
25+
width="25"
26+
height="25"
27+
alt=""
28+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABNklEQVR4AeyWgRGCMAxF1Ul0EzdRJ1En0U10E91E86A97BH0SKJ4HFxDy5H+voa0dDEb+JoA/jYCS0mNk9gjwG6igRaa0iyLFgEc6bQtXc1P6KF1EQXaUjVFA9in11epV2Jzp6GBFoMTCZFrigawTq+PUt/FvAWNXRIBIjXrSgPITlDXXv47EKhkbdqVaQDVi1/dJgBLBFhSLNNDxGeyALCUSKbNUAB5eVK7GSwRIPRsLmf36CJgAZBucSUKwJyYUQDmxIwCICHZbql7fZ8oAHNiRgH0mvWr8wSgRYBkIkr5YELba51a7wA4mnV27EHEfwMturR2Tw0gH58YnIOk92TMnxMtIttaphoAjuz1LWemYDD0mDmatAsJDQAHHFnb3hMx/Rk4RxXtwroACqdvPowf4FP0ngAAAP//V5oXqQAAAAZJREFUAwC6a0hBuVRVWgAAAABJRU5ErkJggg=="
29+
/>
30+
</div>
31+
</ng-diagram-port>
32+
<ng-diagram-port id="port-right-4" type="both" style="top: 75%" side="right">
33+
<div style="display: flex; flex-direction: row; gap: 0.25rem; padding: 0 0.25rem">
34+
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="#000000" viewBox="0 0 256 256">
35+
<path
36+
d="M235.33,116.72,139.28,20.66a16,16,0,0,0-22.56,0l-96,96.06a16,16,0,0,0,0,22.56l96.05,96.06h0a16,16,0,0,0,22.56,0l96.05-96.06a16,16,0,0,0,0-22.56ZM128,224h0L32,128,128,32,224,128Z"
37+
></path>
38+
</svg>
39+
<span>D8</span>
40+
</div>
41+
</ng-diagram-port>
42+
</ng-diagram-node-resize-adornment>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
:host {
2+
display: flex;
3+
width: 100%;
4+
height: 100%;
5+
background-color: white;
6+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
7+
border-radius: 16px;
8+
9+
/* Non-applicable port CSS variables for custom styling */
10+
// --ngd-port-size - is not needed for custom styled ports - size is determined by content
11+
12+
/* Applicable port CSS variables for custom styling */
13+
--ngd-port-border-size: 0px;
14+
// --ngd-port-border-radius: 0%; //disable border radius for square ports
15+
// --ngd-port-background-color: yellow;
16+
// --ngd-port-border-color: red;
17+
// --ngd-port-background-color-hover: #1565c0;
18+
// --ngd-port-border-color-hover: #0c373b;
19+
// --ngd-port-border-size-hover: 0.25rem;
20+
21+
.chip-node {
22+
display: flex;
23+
flex-direction: column;
24+
justify-content: center;
25+
width: 100%;
26+
align-items: center;
27+
}
28+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
2+
import {
3+
NgDiagramNodeResizeAdornmentComponent,
4+
NgDiagramNodeSelectedDirective,
5+
NgDiagramNodeTemplate,
6+
NgDiagramPortComponent,
7+
Node,
8+
} from 'ng-diagram';
9+
10+
@Component({
11+
selector: 'app-chip-node',
12+
imports: [NgDiagramPortComponent, NgDiagramNodeResizeAdornmentComponent],
13+
templateUrl: './chip-node.component.html',
14+
styleUrls: ['./chip-node.component.scss'],
15+
changeDetection: ChangeDetectionStrategy.OnPush,
16+
hostDirectives: [{ directive: NgDiagramNodeSelectedDirective, inputs: ['node'] }],
17+
host: {
18+
'[class.ng-diagram-port-hoverable]': 'true',
19+
},
20+
})
21+
export class ChipNodeComponent implements NgDiagramNodeTemplate<{ text: string }> {
22+
text = computed(() => this.node()?.data?.text || '');
23+
node = input.required<Node<{ text: string }>>();
24+
}

apps/angular-demo/src/app/node-template/image-node/image-node.component.scss

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
background-color: white;
88
border-radius: 4px;
99
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
10-
}
1110

12-
img {
13-
width: 150px;
14-
height: 150px;
15-
object-fit: cover;
16-
border-radius: 4px;
11+
& > img {
12+
width: 150px;
13+
height: 150px;
14+
object-fit: cover;
15+
border-radius: 4px;
16+
}
1717
}

0 commit comments

Comments
 (0)