@angflow/angular 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,203 +1,205 @@
1
- # @angflow/angular
2
-
3
- An Angular library for building node-based UIs, interactive flow charts, and diagrams. Built on top of `@angflow/system` — a republish of `@xyflow/system`, the same framework-agnostic core that powers [React Flow](https://reactflow.dev/) and [Svelte Flow](https://svelteflow.dev/).
4
-
5
- ## Features
6
-
7
- - **Drag & drop nodes** with snap-to-grid support
8
- - **Multiple edge types** — bezier, straight, step, smooth-step, simple-bezier
9
- - **Custom nodes** — render any Angular component as a node (forms, charts, etc.)
10
- - **Custom edges** — build your own edge components
11
- - **Connections** — drag between handles or click-to-connect
12
- - **Selection** — click, shift-drag box select (partial mode), Ctrl/Cmd multi-select
13
- - **Keyboard shortcuts** — Delete/Backspace, Ctrl+A, Escape, arrow keys
14
- - **Pan & zoom** — scroll, pinch, double-click, or use the controls panel
15
- - **Minimap** — interactive viewport preview with customizable node styling
16
- - **Background** — dots, lines, or cross patterns with configurable gap/size
17
- - **Controls** — zoom in/out, fit view, lock interactivity
18
- - **Node toolbar** — context toolbars positioned relative to nodes
19
- - **Edge toolbar** — context toolbars positioned on edges
20
- - **Node resizer** — drag handles to resize nodes
21
- - **Accessibility** — ARIA labels, keyboard navigation, screen reader announcements
22
- - **Dark mode** — light/dark/system color mode support
23
-
24
- ## Requirements
25
-
26
- - Angular 17+
27
- - Standalone components (no NgModule needed)
28
-
29
- ## Installation
30
-
31
- ```bash
32
- npm install @angflow/angular @angflow/system
33
- ```
34
-
35
- ## Quick Start
36
-
37
- ```typescript
38
- import { Component } from '@angular/core';
39
- import {
40
- NgFlowComponent,
41
- HandleComponent,
42
- BackgroundComponent,
43
- ControlsComponent,
44
- MiniMapComponent,
45
- applyNodeChanges,
46
- applyEdgeChanges,
47
- Position,
48
- } from '@angflow/angular';
49
- import type { Node, Edge, Connection } from '@angflow/angular';
50
- import { addEdge } from '@angflow/system';
51
-
52
- @Component({
53
- selector: 'app-root',
54
- standalone: true,
55
- imports: [NgFlowComponent, BackgroundComponent, ControlsComponent, MiniMapComponent],
56
- template: `
57
- <div style="width: 100vw; height: 100vh;">
58
- <ng-flow
59
- [nodes]="nodes"
60
- [edges]="edges"
61
- [fitView]="true"
62
- (nodesChange)="onNodesChange($event)"
63
- (edgesChange)="onEdgesChange($event)"
64
- (connect)="onConnect($event)"
65
- >
66
- <ng-flow-background variant="dots" />
67
- <ng-flow-controls />
68
- <ng-flow-minimap />
69
- </ng-flow>
70
- </div>
71
- `,
72
- })
73
- export class App {
74
- nodes: Node[] = [
75
- { id: '1', type: 'input', position: { x: 250, y: 0 }, data: { label: 'Start' } },
76
- { id: '2', position: { x: 250, y: 150 }, data: { label: 'Process' } },
77
- { id: '3', type: 'output', position: { x: 250, y: 300 }, data: { label: 'End' } },
78
- ];
79
-
80
- edges: Edge[] = [
81
- { id: 'e1-2', source: '1', target: '2' },
82
- { id: 'e2-3', source: '2', target: '3' },
83
- ];
84
-
85
- onNodesChange(changes: any[]) {
86
- this.nodes = applyNodeChanges(changes, this.nodes);
87
- }
88
-
89
- onEdgesChange(changes: any[]) {
90
- this.edges = applyEdgeChanges(changes, this.edges);
91
- }
92
-
93
- onConnect(connection: Connection) {
94
- this.edges = addEdge(connection, this.edges) as Edge[];
95
- }
96
- }
97
- ```
98
-
99
- ## Example App
100
-
101
- A full example app lives at [`example-app/`](../../../example-app) in this repo. It's the best place to see working code for every feature — custom nodes and edges, sub-flows, node/edge toolbars, drag-from-sidebar, save/restore, connection validation, and more.
102
-
103
- ```bash
104
- cd example-app
105
- npm install
106
- npm start # opens http://localhost:4200
107
- ```
108
-
109
- The app ships three sections:
110
-
111
- - **Gallery** ([`src/app/examples/`](../../../example-app/src/app/examples)) focused, one-feature-per-page demos (overview, custom node/edge, edge types, floating edges, node resizer, connection validation, drag-from-sidebar, sub-flows, node/edge toolbars, custom minimap, background variants, save/restore)
112
- - **Showcase** ([`src/app/showcase/`](../../../example-app/src/app/showcase)) — an end-to-end demo with a node palette, inspector panel, and simulation service; a good template for a real app
113
- - **Kitchen Sink** ([`src/app/kitchen-sink/`](../../../example-app/src/app/kitchen-sink)) — exercises nearly every feature together with a live event log
114
-
115
- ## Custom Nodes
116
-
117
- Create any Angular component and register it as a node type. Use the `nodrag` CSS class on interactive elements (inputs, dropdowns) to prevent drag interference.
118
-
119
- ```typescript
120
- @Component({
121
- selector: 'app-form-node',
122
- standalone: true,
123
- imports: [HandleComponent],
124
- template: `
125
- <ng-flow-handle type="target" [position]="Position.Top" />
126
- <div class="my-node">
127
- <h3>{{ data()?.title }}</h3>
128
- <div class="nodrag">
129
- <input [value]="data()?.name" (input)="onNameChange($event)" />
130
- <select [value]="data()?.type" (change)="onTypeChange($event)">
131
- <option value="string">String</option>
132
- <option value="number">Number</option>
133
- </select>
134
- </div>
135
- </div>
136
- <ng-flow-handle type="source" [position]="Position.Bottom" />
137
- `,
138
- })
139
- export class FormNodeComponent {
140
- readonly Position = Position;
141
- readonly id = input.required<string>();
142
- readonly data = input<any>();
143
- // ... other standard inputs: type, selected, dragging, zIndex, etc.
144
-
145
- private flowService = inject(NgFlowService);
146
-
147
- onNameChange(event: Event) {
148
- this.flowService.updateNodeData(this.id(), { name: (event.target as HTMLInputElement).value });
149
- }
150
- }
151
- ```
152
-
153
- Register it:
154
-
155
- ```typescript
156
- nodeTypes = { formNode: FormNodeComponent };
157
- ```
158
-
159
- ```html
160
- <ng-flow [nodes]="nodes" [edges]="edges" [nodeTypes]="nodeTypes" ...>
161
- ```
162
-
163
- ## Programmatic API
164
-
165
- Inject `NgFlowService` for viewport control, node/edge manipulation, and spatial queries:
166
-
167
- ```typescript
168
- const flowService = inject(NgFlowService);
169
-
170
- flowService.fitView();
171
- flowService.zoomIn();
172
- flowService.addNodes({ id: '4', position: { x: 0, y: 0 }, data: { label: 'New' } });
173
- flowService.updateNodeData('2', { label: 'Updated' });
174
- flowService.deleteElements({ nodes: [{ id: '1' }] });
175
- flowService.screenToFlowPosition({ x: event.clientX, y: event.clientY });
176
- flowService.toObject(); // { nodes, edges, viewport }
177
- ```
178
-
179
- ## Architecture
180
-
181
- - **Signal-based state** — Angular 17+ signals for fine-grained reactivity (no RxJS in the store)
182
- - **OnPush everywhere** — all components use `ChangeDetectionStrategy.OnPush`
183
- - **@angflow/system core** — shares the same drag, pan/zoom, handle, and resize logic as React Flow and Svelte Flow (republished from `@xyflow/system`)
184
- - **Standalone components** — no NgModule, tree-shakeable
185
-
186
- ## Keyboard Shortcuts
187
-
188
- | Shortcut | Action |
189
- |----------|--------|
190
- | Delete / Backspace | Remove selected elements |
191
- | Ctrl+A / Cmd+A | Select all |
192
- | Escape | Deselect all |
193
- | Arrow keys | Move selected nodes |
194
- | Shift + drag | Box select |
195
- | Ctrl/Cmd + click | Multi-select |
196
-
197
- ## Credits
198
-
199
- Built on top of [xyflow](https://github.com/xyflow/xyflow) by [webkid GmbH](https://webkid.io/). The Angular port uses `@angflow/system` (a republish of `@xyflow/system`) for framework-agnostic core logic.
200
-
201
- ## License
202
-
203
- MIT
1
+ # @angflow/angular
2
+
3
+ An Angular library for building node-based UIs, interactive flow charts, and diagrams. Built on top of `@angflow/system` — a republish of `@xyflow/system`, the same framework-agnostic core that powers [React Flow](https://reactflow.dev/) and [Svelte Flow](https://svelteflow.dev/).
4
+
5
+ ## Features
6
+
7
+ - **Drag & drop nodes** with snap-to-grid support
8
+ - **Multiple edge types** — bezier, straight, step, smooth-step, simple-bezier
9
+ - **Custom nodes** — render any Angular component as a node (forms, charts, etc.)
10
+ - **Custom edges** — build your own edge components
11
+ - **Connections** — drag between handles or click-to-connect
12
+ - **Selection** — click, shift-drag box select (partial mode), Ctrl/Cmd multi-select
13
+ - **Keyboard shortcuts** — Delete/Backspace, Ctrl+A, Escape, arrow keys
14
+ - **Pan & zoom** — scroll, pinch, double-click, or use the controls panel
15
+ - **Minimap** — interactive viewport preview with customizable node styling
16
+ - **Background** — dots, lines, or cross patterns with configurable gap/size
17
+ - **Controls** — zoom in/out, fit view, lock interactivity
18
+ - **Node toolbar** — context toolbars positioned relative to nodes
19
+ - **Edge toolbar** — context toolbars positioned on edges
20
+ - **Node resizer** — drag handles to resize nodes
21
+ - **Accessibility** — ARIA labels, keyboard navigation, screen reader announcements
22
+ - **Dark mode** — light/dark/system color mode support
23
+
24
+ ## Requirements
25
+
26
+ - Angular 17+
27
+ - Standalone components (no NgModule needed)
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ npm install @angflow/angular @angflow/system
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ```typescript
38
+ import { Component } from '@angular/core';
39
+ import {
40
+ NgFlowComponent,
41
+ HandleComponent,
42
+ BackgroundComponent,
43
+ ControlsComponent,
44
+ MiniMapComponent,
45
+ applyNodeChanges,
46
+ applyEdgeChanges,
47
+ Position,
48
+ } from '@angflow/angular';
49
+ import type { Node, Edge, Connection } from '@angflow/angular';
50
+ import { addEdge } from '@angflow/system';
51
+
52
+ @Component({
53
+ selector: 'app-root',
54
+ standalone: true,
55
+ imports: [NgFlowComponent, BackgroundComponent, ControlsComponent, MiniMapComponent],
56
+ template: `
57
+ <div style="width: 100vw; height: 100vh;">
58
+ <ng-flow
59
+ [nodes]="nodes"
60
+ [edges]="edges"
61
+ [fitView]="true"
62
+ (nodesChange)="onNodesChange($event)"
63
+ (edgesChange)="onEdgesChange($event)"
64
+ (connect)="onConnect($event)"
65
+ >
66
+ <ng-flow-background variant="dots" />
67
+ <ng-flow-controls />
68
+ <ng-flow-minimap />
69
+ </ng-flow>
70
+ </div>
71
+ `,
72
+ })
73
+ export class App {
74
+ nodes: Node[] = [
75
+ { id: '1', type: 'input', position: { x: 250, y: 0 }, data: { label: 'Start' } },
76
+ { id: '2', position: { x: 250, y: 150 }, data: { label: 'Process' } },
77
+ { id: '3', type: 'output', position: { x: 250, y: 300 }, data: { label: 'End' } },
78
+ ];
79
+
80
+ edges: Edge[] = [
81
+ { id: 'e1-2', source: '1', target: '2' },
82
+ { id: 'e2-3', source: '2', target: '3' },
83
+ ];
84
+
85
+ onNodesChange(changes: any[]) {
86
+ this.nodes = applyNodeChanges(changes, this.nodes);
87
+ }
88
+
89
+ onEdgesChange(changes: any[]) {
90
+ this.edges = applyEdgeChanges(changes, this.edges);
91
+ }
92
+
93
+ onConnect(connection: Connection) {
94
+ this.edges = addEdge(connection, this.edges) as Edge[];
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## Example App
100
+
101
+ A full example app lives at [`examples/angular/`](../../examples/angular) in this repo. It's the best place to see working code for every feature — custom nodes and edges, sub-flows, node/edge toolbars, drag-from-sidebar, save/restore, connection validation, and more.
102
+
103
+ ```bash
104
+ pnpm install # from the repo root (first time only)
105
+ cd examples/angular
106
+ npm run dev # opens http://localhost:4200
107
+ ```
108
+
109
+ The example consumes `@angflow/angular` and `@angflow/system` via pnpm `workspace:*`, so local edits in `packages/angular/` are picked up immediately — no rebuild or reinstall step needed.
110
+
111
+ The app ships three sections:
112
+
113
+ - **Gallery** ([`src/app/examples/`](../../examples/angular/src/app/examples)) — focused, one-feature-per-page demos (overview, custom node/edge, edge types, floating edges, node resizer, connection validation, drag-from-sidebar, sub-flows, node/edge toolbars, custom minimap, background variants, save/restore)
114
+ - **Showcase** ([`src/app/showcase/`](../../examples/angular/src/app/showcase)) — an end-to-end demo with a node palette, inspector panel, and simulation service; a good template for a real app
115
+ - **Kitchen Sink** ([`src/app/kitchen-sink/`](../../examples/angular/src/app/kitchen-sink)) — exercises nearly every feature together with a live event log
116
+
117
+ ## Custom Nodes
118
+
119
+ Create any Angular component and register it as a node type. Use the `nodrag` CSS class on interactive elements (inputs, dropdowns) to prevent drag interference.
120
+
121
+ ```typescript
122
+ @Component({
123
+ selector: 'app-form-node',
124
+ standalone: true,
125
+ imports: [HandleComponent],
126
+ template: `
127
+ <ng-flow-handle type="target" [position]="Position.Top" />
128
+ <div class="my-node">
129
+ <h3>{{ data()?.title }}</h3>
130
+ <div class="nodrag">
131
+ <input [value]="data()?.name" (input)="onNameChange($event)" />
132
+ <select [value]="data()?.type" (change)="onTypeChange($event)">
133
+ <option value="string">String</option>
134
+ <option value="number">Number</option>
135
+ </select>
136
+ </div>
137
+ </div>
138
+ <ng-flow-handle type="source" [position]="Position.Bottom" />
139
+ `,
140
+ })
141
+ export class FormNodeComponent {
142
+ readonly Position = Position;
143
+ readonly id = input.required<string>();
144
+ readonly data = input<any>();
145
+ // ... other standard inputs: type, selected, dragging, zIndex, etc.
146
+
147
+ private flowService = inject(NgFlowService);
148
+
149
+ onNameChange(event: Event) {
150
+ this.flowService.updateNodeData(this.id(), { name: (event.target as HTMLInputElement).value });
151
+ }
152
+ }
153
+ ```
154
+
155
+ Register it:
156
+
157
+ ```typescript
158
+ nodeTypes = { formNode: FormNodeComponent };
159
+ ```
160
+
161
+ ```html
162
+ <ng-flow [nodes]="nodes" [edges]="edges" [nodeTypes]="nodeTypes" ...>
163
+ ```
164
+
165
+ ## Programmatic API
166
+
167
+ Inject `NgFlowService` for viewport control, node/edge manipulation, and spatial queries:
168
+
169
+ ```typescript
170
+ const flowService = inject(NgFlowService);
171
+
172
+ flowService.fitView();
173
+ flowService.zoomIn();
174
+ flowService.addNodes({ id: '4', position: { x: 0, y: 0 }, data: { label: 'New' } });
175
+ flowService.updateNodeData('2', { label: 'Updated' });
176
+ flowService.deleteElements({ nodes: [{ id: '1' }] });
177
+ flowService.screenToFlowPosition({ x: event.clientX, y: event.clientY });
178
+ flowService.toObject(); // { nodes, edges, viewport }
179
+ ```
180
+
181
+ ## Architecture
182
+
183
+ - **Signal-based state** — Angular 17+ signals for fine-grained reactivity (no RxJS in the store)
184
+ - **OnPush everywhere** — all components use `ChangeDetectionStrategy.OnPush`
185
+ - **@angflow/system core** — shares the same drag, pan/zoom, handle, and resize logic as React Flow and Svelte Flow (republished from `@xyflow/system`)
186
+ - **Standalone components** — no NgModule, tree-shakeable
187
+
188
+ ## Keyboard Shortcuts
189
+
190
+ | Shortcut | Action |
191
+ |----------|--------|
192
+ | Delete / Backspace | Remove selected elements |
193
+ | Ctrl+A / Cmd+A | Select all |
194
+ | Escape | Deselect all |
195
+ | Arrow keys | Move selected nodes |
196
+ | Shift + drag | Box select |
197
+ | Ctrl/Cmd + click | Multi-select |
198
+
199
+ ## Credits
200
+
201
+ Built on top of [xyflow](https://github.com/xyflow/xyflow) by [webkid GmbH](https://webkid.io/). The Angular port uses `@angflow/system` (a republish of `@xyflow/system`) for framework-agnostic core logic.
202
+
203
+ ## License
204
+
205
+ MIT
@@ -14,7 +14,10 @@ export declare class ControlsComponent {
14
14
  readonly zoomOutClick: import("@angular/core").OutputEmitterRef<void>;
15
15
  readonly fitViewClick: import("@angular/core").OutputEmitterRef<void>;
16
16
  readonly interactiveChange: import("@angular/core").OutputEmitterRef<boolean>;
17
- readonly isLocked: import("@angular/core").WritableSignal<boolean>;
17
+ readonly isInteractive: import("@angular/core").Signal<boolean>;
18
+ readonly isLocked: import("@angular/core").Signal<boolean>;
19
+ readonly maxZoomReached: import("@angular/core").Signal<boolean>;
20
+ readonly minZoomReached: import("@angular/core").Signal<boolean>;
18
21
  onZoomIn(): void;
19
22
  onZoomOut(): void;
20
23
  onFitView(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"controls.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/controls/controls.component.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;;AAKzE,qBAgEa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,aAAa,CAAyB;IAE9C,QAAQ,CAAC,QAAQ,qDAAuC;IACxD,QAAQ,CAAC,QAAQ,+CAAe;IAChC,QAAQ,CAAC,WAAW,+CAAe;IACnC,QAAQ,CAAC,eAAe,+CAAe;IACvC,QAAQ,CAAC,cAAc,2EAAoC;IAC3D,QAAQ,CAAC,WAAW,iEAAgD;IACpE,QAAQ,CAAC,SAAS,8CAA0C;IAG5D,QAAQ,CAAC,WAAW,iDAAkB;IACtC,QAAQ,CAAC,YAAY,iDAAkB;IACvC,QAAQ,CAAC,YAAY,iDAAkB;IACvC,QAAQ,CAAC,iBAAiB,oDAAqB;IAE/C,QAAQ,CAAC,QAAQ,kDAAiB;IAElC,QAAQ;IAKR,SAAS;IAKT,SAAS;IAKT,YAAY;yCAnCD,iBAAiB;2CAAjB,iBAAiB;CA2C7B"}
1
+ {"version":3,"file":"controls.component.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/controls/controls.component.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;;AAKzE,qBAkEa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,aAAa,CAAyB;IAE9C,QAAQ,CAAC,QAAQ,qDAAuC;IACxD,QAAQ,CAAC,QAAQ,+CAAe;IAChC,QAAQ,CAAC,WAAW,+CAAe;IACnC,QAAQ,CAAC,eAAe,+CAAe;IACvC,QAAQ,CAAC,cAAc,2EAAoC;IAC3D,QAAQ,CAAC,WAAW,iEAAgD;IACpE,QAAQ,CAAC,SAAS,8CAA0C;IAG5D,QAAQ,CAAC,WAAW,iDAAkB;IACtC,QAAQ,CAAC,YAAY,iDAAkB;IACvC,QAAQ,CAAC,YAAY,iDAAkB;IACvC,QAAQ,CAAC,iBAAiB,oDAAqB;IAK/C,QAAQ,CAAC,aAAa,0CAKpB;IACF,QAAQ,CAAC,QAAQ,0CAAyC;IAG1D,QAAQ,CAAC,cAAc,0CAAqE;IAC5F,QAAQ,CAAC,cAAc,0CAAqE;IAE5F,QAAQ;IAKR,SAAS;IAKT,SAAS;IAKT,YAAY;yCAhDD,iBAAiB;2CAAjB,iBAAiB;CAuD7B"}