Skip to content

Commit

Permalink
0.4.0 (#58)
Browse files Browse the repository at this point in the history
* Node selection (#55)

* refactor: getters -> computed signals

* feat: implement z-index emulation for nodes

* feat: create node selection logic

* feat: pass selected signal to custom node context

* feat: do not reset selection on pan

* refactor: create separate service for selection management

* fix: disable zoom on dblckick

* fix: fix not reset selection after zoom

* feat: add input to disable selection

* refactor: remove flow.model

* refactor: refactor InjectionContext helper to interface

* feat: add select change type

* fix: remove todo

* refactor: move select method to selection service

* Edge selection (#57)

* feat: make edges selectable

* fix: fix edge selection reset

* feat: create directive for marking element as selectable

* feat: add selected signal to edge context

* feat: make selectable directive work also with nodes

* feat: match flow colors with design

* fix: stop selecting default edge if entitiesSelectable set

* docs: add selecting demo

* docs: remove flag

* docs: add delete-selected workshop

* fix: fix default handles in safari

* up angular version

* fix: add selectable directive to public api

* up version
  • Loading branch information
artem-mangilev authored May 25, 2024
1 parent ea3977b commit 19ef16d
Show file tree
Hide file tree
Showing 40 changed files with 648 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { Node, VflowModule } from 'projects/ngx-vflow-lib/src/public-api';
@Component({
template: `<vflow [nodes]="nodes">
<ng-template nodeHtml let-ctx>
<div class="custom-node-{{ ctx.node.data.customType }}">
<div class="custom-node" [class.custom-node_selected]="ctx.selected()">
{{ ctx.node.data.text }}
</div>
</ng-template>
</vflow>`,
styles: [
`
.custom-node-gradient {
.custom-node {
width: 150px;
height: 100px;
background: linear-gradient(to right, #00d2ff, #3a7bd5);
Expand All @@ -22,6 +22,10 @@ import { Node, VflowModule } from 'projects/ngx-vflow-lib/src/public-api';
align-items: center;
padding-left: 5px;
padding-right: 5px;
&_selected {
border: 2px solid gray;
}
}
`
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<vflow [nodes]="nodes" [edges]="edges">
<ng-template nodeHtml let-ctx>
<div class="custom-node" [class.custom-node_selected]="ctx.selected()">
<button class="custom-node__button" selectable>Select here</button>

<handle type="source" position="right" />
</div>
</ng-template>

<ng-template edge let-ctx>
<svg:path
selectable
[attr.d]="ctx.path()"
[attr.stroke]="ctx.selected() ? '#0f4c75' : '#bbe1fa'"
fill="none"
stroke-width="2"
/>
</ng-template>
</vflow>`
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.custom-node {
width: 150px;
height: 100px;
background: #bbe1fa;
border: 1px solid gray;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;

&__button {
border: 0;
outline: 0;
cursor: pointer;
color: white;
background-color: #1b262c;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
padding: 4px 8px;
display: inline-block;
min-height: 28px;
}

&_selected {
border-color: #1b262c;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Edge, Node, VflowModule } from 'projects/ngx-vflow-lib/src/public-api';

@Component({
templateUrl: './selecting-demo.component.html',
styleUrls: ['./selecting-demo.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [VflowModule]
})
export class SelectingDemoComponent {
public nodes: Node[] = [
{
id: '1',
point: { x: 10, y: 150 },
type: 'html-template',
},
{
id: '2',
point: { x: 290, y: 50 },
type: 'default',
text: 'Selectable'
},
{
id: '3',
point: { x: 290, y: 300 },
type: 'default',
text: 'Selectable'
},
]

public edges: Edge[] = [
{
id: '1 -> 2',
source: '1',
target: '2'
},
{
id: '1 -> 3',
source: '1',
target: '3',
type: 'template'
},
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# {{ NgDocPage.title }}

Nodes and edges could be selected!

1. Default nodes and edges are selectable by default, just click and see that one is selected.
2. Custom nodes and edges are not selected by default, you need to mark element that triggers selection by `selectable` directive.

> Both custom nodes and edges has `selected()` signal in their template context for applying styles based on this state.
### Disable selecting

You can pass `[entitiesSelectable]="false"` to `<vflow />` if you want disable selecting for whole flow.

{{ NgDocActions.demo("SelectingDemoComponent", { expanded: true }) }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgDocPage } from '@ng-doc/core';
import ExamplesCategory from '../../ng-doc.category'
import { SelectingDemoComponent } from './demo/selecting-demo.component';

const TestPage: NgDocPage = {
title: `Selecting`,
mdFile: './index.md',
category: ExamplesCategory,
demos: { SelectingDemoComponent },
order: 2
};

export default TestPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { NgDocCategory } from '@ng-doc/core';

const WorkshopsCategory: NgDocCategory = {
title: 'Workshops',
order: 2
};

export default WorkshopsCategory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<vflow [nodes]="nodes" [edges]="edges">
<ng-template nodeHtml let-ctx>
<div
class="custom-node without-tab-index"
[class.custom-node_selected]="ctx.selected()"
tabindex="0"
(keydown.backspace)="ctx.selected() && deleteNode(ctx.node)"
>
<button class="custom-node__button" selectable>Select here</button>

<handle type="source" position="right" />
<handle type="target" position="left" />
</div>
</ng-template>

<ng-template edge let-ctx>
<svg:path
selectable
class="without-tab-index"
[attr.d]="ctx.path()"
[attr.stroke]="ctx.selected() ? '#0f4c75' : '#bbe1fa'"
fill="none"
stroke-width="2"
tabindex="0"
(keydown.backspace)="ctx.selected() && deleteEdge(ctx.edge)"
/>
</ng-template>
</vflow>`
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.custom-node {
width: 150px;
height: 100px;
background: #bbe1fa;
border: 1px solid gray;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;

&__button {
border: 0;
outline: 0;
cursor: pointer;
color: white;
background-color: #1b262c;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
padding: 4px 8px;
display: inline-block;
min-height: 28px;
}

&_selected {
border-color: #1b262c;
}
}

.without-tab-index {
outline: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Edge, Node, VflowModule } from 'projects/ngx-vflow-lib/src/public-api';

@Component({
templateUrl: './delete-selected-demo.component.html',
styleUrls: ['./delete-selected-demo.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [VflowModule]
})
export class DeleteSelectedDemoComponent {
public nodes: Node[] = [
{
id: '1',
point: { x: 10, y: 150 },
type: 'html-template',
},
{
id: '2',
point: { x: 290, y: 50 },
type: 'html-template',
},
{
id: '3',
point: { x: 290, y: 300 },
type: 'html-template',
},
]

public edges: Edge[] = [
{
id: '1 -> 2',
source: '1',
target: '2',
type: 'template'
},
{
id: '1 -> 3',
source: '1',
target: '3',
type: 'template'
},
]

public deleteNode(node: Node) {
this.nodes = this.nodes.filter(n => n.id !== node.id)
}

public deleteEdge(edge: Edge) {
this.edges = this.edges.filter(e => e.id !== edge.id)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# {{ NgDocPage.title }}

This workshop will show you how to implement deletion of nodes and edges.

{{ NgDocActions.demo("DeleteSelectedDemoComponent", { expanded: true }) }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgDocPage } from '@ng-doc/core';
import WorkshopsCategory from '../../ng-doc.category'
import { DeleteSelectedDemoComponent } from './demo/delete-selected-demo.component';

const TestPage: NgDocPage = {
title: `Delete selected`,
mdFile: './index.md',
category: WorkshopsCategory,
demos: { DeleteSelectedDemoComponent },
order: 2
};

export default TestPage;
6 changes: 3 additions & 3 deletions projects/ngx-vflow-lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-vflow",
"version": "0.3.0",
"version": "0.4.0",
"license": "MIT",
"homepage": "https://www.ngx-vflow.org/",
"author": "Artem Mangilev",
Expand All @@ -21,8 +21,8 @@
"publish:patch": "npm version patch && ng build ngx-vflow-lib && cd ../../dist/ngx-vflow-lib && npm publish"
},
"peerDependencies": {
"@angular/common": "^16.2.0 || 17.x",
"@angular/core": "^16.2.0 || 17.x",
"@angular/common": "^16.2.0 || 17.x || 18.x",
"@angular/core": "^16.2.0 || 17.x || 18.x",
"d3-drag": "^3.0.0",
"d3-path": "^3.1.0",
"d3-selection": "^3.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
<svg:path
*ngIf="model.type === 'default'"
(mousedown)="onEdgeMouseDown()"
[attr.d]="model.path().path"
[attr.marker-start]="markerStartUrl()"
[attr.marker-end]="markerEndUrl()"
[attr.stroke]="defaultColor"
stroke-width="2"
fill="none"
class="edge"
[class.edge_selected]="model.selected()"
/>

<ng-container *ngIf="model.type === 'template' && edgeTemplate">
<ng-container *ngTemplateOutlet="edgeTemplate; context: edgeContext"></ng-container>
<ng-container
[ngTemplateOutlet]="edgeTemplate"
[ngTemplateOutletContext]="edgeContext"
[ngTemplateOutletInjector]="injector"
></ng-container>
</ng-container>

<ng-container *ngIf="model.edgeLabels?.start as label">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.edge {
fill: none;
stroke-width: 2;
stroke: rgb(177, 177, 183);

&_selected {
stroke-width: 2.5;
stroke: #0f4c75;
}
}
Loading

0 comments on commit 19ef16d

Please sign in to comment.