Skip to content

Commit

Permalink
feat: add plugin support to ngu-flow
Browse files Browse the repository at this point in the history
  • Loading branch information
sheikalthaf committed Feb 14, 2024
1 parent a30c971 commit d8e2fb9
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 65 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"start": "ng serve --port 52666",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"gh": "ng deploy --dir=dist/angular-flow/browser --base-href=/ngu-flow/",
"test": "jest"
},
"private": true,
Expand Down
4 changes: 2 additions & 2 deletions projects/flow/src/lib/flow-child.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ export class FlowChildComponent implements OnInit, OnChanges, OnDestroy {
});

this.positionChange.subscribe((x) => {
const { left, top } = this.flow.zRect;
// const { left, top } = this.flow.zRect;
// if (!this.position) console.log(this.position);
this.updatePosition(this.position.x + left, this.position.y + top);
this.updatePosition(this.position.x, this.position.y);
});
}

Expand Down
8 changes: 8 additions & 0 deletions projects/flow/src/lib/flow-interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { FlowComponent } from './flow.component';

export interface ChildInfo {
position: FlowOptions;
dots?: DOMRect[];
Expand Down Expand Up @@ -26,6 +28,7 @@ export interface DotOptions extends FlowOptions {
export class FlowConfig {
Arrows = true;
ArrowSize = 20;
Plugins: FlowPlugin[] = [];
}

export type FlowDirection = 'horizontal' | 'vertical';
Expand All @@ -36,3 +39,8 @@ export type ArrowPathFn = (
arrowSize: number,
strokeWidth: number
) => string;

export interface FlowPlugin {
onInit?(data: FlowComponent): void;
afterInit?(data: FlowComponent): void;
}
35 changes: 13 additions & 22 deletions projects/flow/src/lib/flow.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import {
ElementRef,
NgZone,
ChangeDetectionStrategy,
Input,
OnInit,
} from '@angular/core';
import { startWith } from 'rxjs';
import { Arrangements2 as Arrangements } from './arrangements';
import { Arrangements2 as Arrangements } from './plugins/arrangements';
import { Connections } from './connections';
import { FlowChildComponent } from './flow-child.component';
import { FlowService } from './flow.service';
Expand All @@ -22,9 +24,9 @@ import {
FlowDirection,
DotOptions,
ArrowPathFn,
FlowConfig,
} from './flow-interface';
import { blendCorners, flowPath, bezierPath, blendCorners1 } from './svg';
import { FitToWindow } from './fit-to-window';

const BASE_SCALE_AMOUNT = 0.05;

Expand Down Expand Up @@ -125,10 +127,11 @@ const BASE_SCALE_AMOUNT = 0.05;
],
})
export class FlowComponent
implements AfterContentInit, AfterViewInit, OnDestroy
implements OnInit, AfterContentInit, AfterViewInit, OnDestroy
{
@ContentChildren(FlowChildComponent) children: QueryList<FlowChildComponent> =
new QueryList();
@Input() config: FlowConfig = new FlowConfig();
@ContentChildren(FlowChildComponent) children =
new QueryList<FlowChildComponent>();

// @ViewChildren('arrowPaths') arrowPaths: QueryList<ElementRef<SVGPathElement>>;
@ViewChild('zoomContainer') zoomContainer: ElementRef<HTMLDivElement>;
Expand All @@ -143,7 +146,9 @@ export class FlowComponent
public el: ElementRef<HTMLElement>,
public flow: FlowService,
private ngZone: NgZone
) {
) {}

ngOnInit(): void {
this.flow.zoomContainer = this.el.nativeElement;
this.flow.arrowsChange.subscribe((e) => this.updateArrows(e));
this.ngZone.runOutsideAngular(() => {
Expand All @@ -166,6 +171,7 @@ export class FlowComponent

ngAfterViewInit(): void {
this.createArrows();
this.config.Plugins.forEach((x) => x.afterInit?.(this));
}

ngAfterContentInit() {
Expand Down Expand Up @@ -281,22 +287,7 @@ export class FlowComponent
return { scale: newScale, panX: newPanX, panY: newPanY };
}

fitToWindow() {
const ftw = new FitToWindow(
this.list,
this.zoomContainer.nativeElement.getBoundingClientRect(),
this.flow.scale,
this.flow.panX,
this.flow.panY
);
const { scale, panX, panY } = ftw.fitToWindow();
this.flow.scale = scale;
this.flow.panX = panX;
this.flow.panY = panY;
this.updateZoomContainer();
}

private updateZoomContainer() {
updateZoomContainer() {
this.zoomContainer.nativeElement.style.transform = `translate3d(${this.flow.panX}px, ${this.flow.panY}px, 0) scale(${this.flow.scale})`;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Arrangements, Arrangements2 } from './arrangements';
import { ChildInfo } from './flow-interface';
import { ChildInfo } from '../flow-interface';

export const FLOW_LIST = [
{ x: 40, y: 40, id: '1', deps: [] },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { FlowOptions, ChildInfo, FlowDirection } from './flow-interface';
import {
FlowOptions,
ChildInfo,
FlowDirection,
FlowPlugin,
} from '../flow-interface';
import { FlowComponent } from '../flow.component';

export class Arrangements {
constructor(
Expand Down Expand Up @@ -122,7 +128,7 @@ const ROOT_DEPS = new Map<string, string[]>();
const HORIZONTAL_PADDING = 100;
const VERTICAL_PADDING = 20;

export class Arrangements2 {
export class Arrangements2 implements FlowPlugin {
root: string[] = [];

constructor(
Expand Down Expand Up @@ -151,6 +157,10 @@ export class Arrangements2 {
});
}

onInit(data: FlowComponent): void {
this.autoArrange();
}

public autoArrange(): Map<string, FlowOptions> {
this.root.forEach((id) => {
const node = ROOT_DATA.get(id)!;
Expand All @@ -162,6 +172,7 @@ export class Arrangements2 {
for (const item of this.list) {
newItems.set(item.position.id, item.position);
}
console.log([...newItems.values()]);
return newItems;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,21 @@ describe('FitToWindow', () => {
scale = 1;
panX = 0;
panY = 0;
fitToWindow = new FitToWindow(list, containerRect, scale, panX, panY);
fitToWindow = new FitToWindow();
fitToWindow.onInit({
list,
zoomContainer: {
nativeElement: { getBoundingClientRect: () => containerRect },
},
flow: {
scale,
panX,
panY,
zRect: containerRect,
},
updateZoomContainer: () => {},
} as any);
fitToWindow.run(list, containerRect, scale, panX, panY);
});

it('should return positions', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,64 @@
import { ChildInfo } from './flow-interface';
import { ChildInfo, FlowPlugin } from '../flow-interface';
import { FlowComponent } from '../flow.component';

export class FitToWindow {
export class FitToWindow implements FlowPlugin {
cRect: CPosition;
containerPadding = 0;
data: FlowComponent;

constructor(
private list: ChildInfo[],
private containerRect: DOMRect,
private scale: number,
private panX: number,
private panY: number
private list: ChildInfo[];
private containerRect: DOMRect;
private scale: number;
private panX: number;
private panY: number;

constructor(private init = false) {}

onInit(data: FlowComponent): void {
this.data = data;
}

afterInit(data: FlowComponent): void {
this.data = data;
if (this.init) {
this.run(
this.data.list,
this.data.zoomContainer.nativeElement.getBoundingClientRect(),
this.data.flow.scale,
this.data.flow.panX,
this.data.flow.panY
);
}
}

run(
list: ChildInfo[],
cRect: DOMRect,
scale: number,
panX: number,
panY: number
) {
const tt = { list, containerRect, scale, panX, panY };
this.list = list;
this.containerRect = cRect;
this.scale = scale;
this.panX = panX;
this.panY = panY;
this.fitToWindowInternal();
}

fitToWindowInternal() {
this.containerPadding = 30 / this.scale;
this.cRect = {
x: this.containerRect.x / this.scale - this.panX,
y: this.containerRect.y / this.scale - this.panY,
width: this.containerRect.width / this.scale,
height: this.containerRect.height / this.scale,
};
const { scale, panX, panY } = this.fitToWindow();
this.data.flow.scale = scale;
this.data.flow.panX = panX;
this.data.flow.panY = panY;
this.data.updateZoomContainer();
}

fitToWindow() {
Expand Down Expand Up @@ -66,24 +106,6 @@ export class FitToWindow {
return Math.min(scaleX, scaleY);
}

// getPanValues(
// adjMaxX: number,
// adjMaxY: number,
// newScale: number,
// minX: number,
// minY: number
// ) {
// const panX =
// this.cRect.x +
// (this.cRect.width - (adjMaxX - this.containerPadding) * newScale) / 2 -
// minX * newScale;
// const panY =
// this.cRect.y +
// (this.cRect.height - (adjMaxY - this.containerPadding) * newScale) / 2 -
// minY * newScale;
// return { panX, panY };
// }
// }
getPanValues(
adjMaxX: number,
adjMaxY: number,
Expand Down
33 changes: 33 additions & 0 deletions projects/flow/src/lib/plugins/scroll-into-view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FlowPlugin } from '../flow-interface';
import { FlowComponent } from '../flow.component';

export class ScrollIntoView implements FlowPlugin {
data: FlowComponent;
constructor(private id: string) {}

afterInit(data: FlowComponent): void {
this.data = data;
this.focus(this.id);
}

focus(id: string) {
const item = this.data.list.find((x) => x.position.id === id);
if (item) {
const { x, y } = item.position;
const { width, height } = item.elRect;
// this.flow.panX = -x * this.flow.scale + this.flow.zRect.width / 2;
if (x + width * this.data.flow.scale > this.data.flow.zRect.width) {
this.data.flow.panX =
-x * this.data.flow.scale + (this.data.flow.zRect.width - width);
} else if (
this.data.flow.panX + x * this.data.flow.scale <
this.data.flow.zRect.width
) {
this.data.flow.panX = -x * this.data.flow.scale;
}
this.data.flow.panY =
-y * this.data.flow.scale + (this.data.flow.zRect.height - height) / 2;
this.data.updateZoomContainer();
}
}
}
2 changes: 2 additions & 0 deletions projects/flow/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ export {
FlowConfig,
} from './lib/flow-interface';
export * from './lib/svg';
export { FitToWindow } from './lib/plugins/fit-to-window';
export { ScrollIntoView } from './lib/plugins/scroll-into-view';
Loading

0 comments on commit d8e2fb9

Please sign in to comment.