Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ustutt/grapheditor-webcomponent

Package Overview
Dependencies
Maintainers
2
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ustutt/grapheditor-webcomponent - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

17

CHANGELOG.md

@@ -11,4 +11,19 @@ # Changelog

## [0.0.3] - 2019-03-04
### Added
- `updateTextElements` function to update and reflow text with `force` parameter
- `getNode`, `getEdge`, `getEdgesBySource` and `getEdgesByTarget` functions in grapheditor
### Fixed
- First multiline textwrap not rendering the text
- `scaleRelative` not affecting `lineOffset` position of `edge.markerEnd`
## [0.0.2] - 2019-02-25
### Added
- LinkHandles for `path` and `polygon` elements

@@ -21,4 +36,6 @@ - scaleRelative attribute in `Marker` for scaling relative to stroke-width of edge path

## [0.0.1] - 2019-02-15
### Added
- Initial webcomponent
- Documentation

@@ -76,2 +76,8 @@ import { Node } from './node';

/**
* Get the node with the given id.
*
* @param nodeId the id of the node
*/
getNode(nodeId: number | string): Node;
/**
* Remove a single node from the graph.

@@ -98,2 +104,8 @@ *

/**
* Get the edge with the given id.
*
* @param edgeId the id of the edge
*/
getEdge(edgeId: number | string): Edge;
/**
* Remove a single edge from the graph.

@@ -106,2 +118,14 @@ *

/**
* Get all edges that have the given nodeId as source
*
* @param sourceNodeId the node id of the edge source
*/
getEdgesBySource(sourceNodeId: number | string): Set<Edge>;
/**
* Get all edges that have the given nodeId as target
*
* @param targetNodeId the node id of the edge target
*/
getEdgesByTarget(targetNodeId: number | string): Set<Edge>;
/**
* Set the graph interaction mode and cleanup temp data from old interaction mode.

@@ -160,2 +184,9 @@ *

/**
* Updates and reflows all text elements in nodes.
*
* @param force force text rewrap even when text has not changed
* (useful if node classes can change text attributes like size)
*/
updateTextElements(force?: boolean): void;
/**
* Add nodes to graph.

@@ -183,2 +214,8 @@ *

/**
* Update text of existing nodes.
*
* @param nodeSelection d3 selection of nodes to update with bound data
*/
private updateNodeText;
/**
* Update node classes.

@@ -185,0 +222,0 @@ *

125

lib-esm/grapheditor.js

@@ -297,2 +297,10 @@ /*

/**
* Get the node with the given id.
*
* @param nodeId the id of the node
*/
getNode(nodeId) {
return this.objectCache.getNode(nodeId);
}
/**
* Remove a single node from the graph.

@@ -357,2 +365,10 @@ *

/**
* Get the edge with the given id.
*
* @param edgeId the id of the edge
*/
getEdge(edgeId) {
return this.objectCache.getEdge(edgeId);
}
/**
* Remove a single edge from the graph.

@@ -379,2 +395,18 @@ *

/**
* Get all edges that have the given nodeId as source
*
* @param sourceNodeId the node id of the edge source
*/
getEdgesBySource(sourceNodeId) {
return this.objectCache.getEdgesBySource(sourceNodeId);
}
/**
* Get all edges that have the given nodeId as target
*
* @param targetNodeId the node id of the edge target
*/
getEdgesByTarget(targetNodeId) {
return this.objectCache.getEdgesByTarget(targetNodeId);
}
/**
* Set the graph interaction mode and cleanup temp data from old interaction mode.

@@ -604,2 +636,16 @@ *

/**
* Updates and reflows all text elements in nodes.
*
* @param force force text rewrap even when text has not changed
* (useful if node classes can change text attributes like size)
*/
updateTextElements(force = false) {
const svg = this.getSvg();
const graph = svg.select('g.zoom-group');
const nodeSelection = graph.select('.nodes')
.selectAll('g.node')
.data(this._nodes, (d) => d.id.toString());
this.updateNodeText(nodeSelection, force);
}
/**
* Add nodes to graph.

@@ -753,4 +799,11 @@ *

.call(this.updateNodeClasses.bind(this))
.call(this.updateNodeHighligts.bind(this));
// allow node drag and drop
.call(this.updateNodeHighligts.bind(this))
.call(this.updateNodeText.bind(this));
}
/**
* Update text of existing nodes.
*
* @param nodeSelection d3 selection of nodes to update with bound data
*/
updateNodeText(nodeSelection, force = false) {
nodeSelection.each(function (d) {

@@ -765,2 +818,3 @@ const singleNodeSelection = select(this);

if (attr.includes('.')) {
// recursive decend along path
const path = attr.split('.');

@@ -785,3 +839,5 @@ let temp = d;

}
wrapText(this, newText);
// make sure it is a string
newText = newText.toString();
wrapText(this, newText, force);
});

@@ -962,27 +1018,35 @@ });

updateEdgePath(edgeSelection) {
edgeSelection.attr('d', (d) => {
const handles = this.objectCache.getEdgeLinkHandles(d);
const points = [];
points.push(handles.sourceCoordinates);
if (handles.sourceHandle.normal != null) {
points.push({
x: handles.sourceCoordinates.x + (handles.sourceHandle.normal.dx * 10),
y: handles.sourceCoordinates.y + (handles.sourceHandle.normal.dy * 10),
});
}
const offset = (d.markerEnd != null && d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
if (handles.targetHandle.normal != null) {
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * (10 + offset)),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * (10 + offset)),
});
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * offset),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * offset),
});
}
else {
points.push(handles.targetCoordinates);
}
return this.edgeGenerator(points);
const self = this;
edgeSelection.each(function (d) {
const singleEdgeSelection = select(this);
const strokeWidth = parseFloat(singleEdgeSelection.style('stroke-width').replace(/px/, ''));
singleEdgeSelection.attr('d', () => {
const handles = self.objectCache.getEdgeLinkHandles(d);
const points = [];
points.push(handles.sourceCoordinates);
if (handles.sourceHandle.normal != null) {
points.push({
x: handles.sourceCoordinates.x + (handles.sourceHandle.normal.dx * 10),
y: handles.sourceCoordinates.y + (handles.sourceHandle.normal.dy * 10),
});
}
let offset = (d.markerEnd != null && d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
if (d.markerEnd != null && d.markerEnd.scale != null && !(!d.markerEnd.scaleRelative)) {
offset *= strokeWidth;
}
if (handles.targetHandle.normal != null) {
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * (10 + offset)),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * (10 + offset)),
});
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * offset),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * offset),
});
}
else {
points.push(handles.targetCoordinates);
}
return self.edgeGenerator(points);
});
});

@@ -1049,3 +1113,6 @@ }

let transform = '';
const offset = (d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
let offset = (d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
if (d.markerEnd.scale != null && !(!d.markerEnd.scaleRelative)) {
offset *= strokeWidth;
}
const point = {

@@ -1052,0 +1119,0 @@ x: pathEndpoint.x + (edgeNormal.dx * offset),

@@ -159,3 +159,3 @@ /*

}
else if (isNaN(parseInt(linkHandles, 10))) {
else if (!isNaN(parseInt(linkHandles, 10))) {
nrOfHandles = parseInt(linkHandles, 10);

@@ -162,0 +162,0 @@ }

@@ -17,3 +17,3 @@ import { RotationVector } from './rotation-vector';

scale?: number;
/** If true the marker is scaled relative to the stroke width. */
/** If true the marker and lineOffset is scaled relative to the stroke width. */
scaleRelative?: boolean;

@@ -20,0 +20,0 @@ /** Rotation information for the marker. */

@@ -33,3 +33,3 @@ import { Node } from './node';

getEdgesByTarget(targetId: number | string): Set<Edge>;
getEdgesBySource(targetId: number | string): Set<Edge>;
getEdgesBySource(sourceId: number | string): Set<Edge>;
getEdgeLinkHandles(edge: Edge): {

@@ -36,0 +36,0 @@ sourceHandle: LinkHandle;

@@ -119,4 +119,4 @@ /*

}
getEdgesBySource(targetId) {
const edges = this.edgesBySource.get(targetId.toString());
getEdgesBySource(sourceId) {
const edges = this.edgesBySource.get(sourceId.toString());
if (edges == null) {

@@ -123,0 +123,0 @@ return new Set();

@@ -15,3 +15,4 @@ /**

* @param newText text to wrap
* @param force force rewrap
*/
export declare function wrapText(element: SVGTextElement, newText: any): void;
export declare function wrapText(element: SVGTextElement, newText: any, force?: boolean): void;

@@ -32,4 +32,5 @@ /*

* @param newText text to wrap
* @param force force rewrap
*/
export function wrapText(element, newText) {
export function wrapText(element, newText, force = false) {
const text = select(element);

@@ -61,3 +62,3 @@ const x = parseFloat(text.attr('x'));

if (isNaN(height)) {
const overflow = lTrim(wrapSingleLine(element, width, newText, overflowMode, wordBreak));
const overflow = lTrim(wrapSingleLine(element, width, newText, overflowMode, wordBreak, force));
text.attr('data-wrapped', overflow !== '' ? 'true' : 'false');

@@ -72,3 +73,3 @@ return;

const last = index < (lines.length - 1);
newText = lTrim(wrapSingleLine(line, width, newText, last ? 'clip' : overflowMode, last ? wordBreak : 'break-all'));
newText = lTrim(wrapSingleLine(line, width, newText, last ? 'clip' : overflowMode, last ? wordBreak : 'break-all', force));
}

@@ -135,4 +136,3 @@ }

spanSelection.exit().remove();
spanSelection.enter().append('tspan').attr('x', x).attr('y', d => d);
return spanSelection;
return spanSelection.enter().append('tspan').attr('x', x).attr('y', d => d).merge(spanSelection);
}

@@ -147,4 +147,5 @@ /**

* @param wordBreak break mode
* @param force force rewrap
*/
function wrapSingleLine(element, width, newText, mode = 'ellipsis', wordBreak = 'break-word') {
function wrapSingleLine(element, width, newText, mode = 'ellipsis', wordBreak = 'break-word', force = false) {
const text = select(element);

@@ -160,3 +161,3 @@ const oldText = text.text();

// shortcuts (when text is already wrapped)
if (oldText != null && oldText !== '') {
if (!force && oldText != null && oldText !== '') {
if (oldText.startsWith(newText)) {

@@ -167,3 +168,3 @@ // newText is shorter

}
if (mode === 'clip') {
else if (mode === 'clip') {
if (text.attr('data-wrapped') === 'true' && newText.startsWith(oldText)) {

@@ -170,0 +171,0 @@ // odlText was wrapped and newText begins with oldText

@@ -76,2 +76,8 @@ import { Node } from './node';

/**
* Get the node with the given id.
*
* @param nodeId the id of the node
*/
getNode(nodeId: number | string): Node;
/**
* Remove a single node from the graph.

@@ -98,2 +104,8 @@ *

/**
* Get the edge with the given id.
*
* @param edgeId the id of the edge
*/
getEdge(edgeId: number | string): Edge;
/**
* Remove a single edge from the graph.

@@ -106,2 +118,14 @@ *

/**
* Get all edges that have the given nodeId as source
*
* @param sourceNodeId the node id of the edge source
*/
getEdgesBySource(sourceNodeId: number | string): Set<Edge>;
/**
* Get all edges that have the given nodeId as target
*
* @param targetNodeId the node id of the edge target
*/
getEdgesByTarget(targetNodeId: number | string): Set<Edge>;
/**
* Set the graph interaction mode and cleanup temp data from old interaction mode.

@@ -160,2 +184,9 @@ *

/**
* Updates and reflows all text elements in nodes.
*
* @param force force text rewrap even when text has not changed
* (useful if node classes can change text attributes like size)
*/
updateTextElements(force?: boolean): void;
/**
* Add nodes to graph.

@@ -183,2 +214,8 @@ *

/**
* Update text of existing nodes.
*
* @param nodeSelection d3 selection of nodes to update with bound data
*/
private updateNodeText;
/**
* Update node classes.

@@ -185,0 +222,0 @@ *

@@ -299,2 +299,10 @@ "use strict";

/**
* Get the node with the given id.
*
* @param nodeId the id of the node
*/
getNode(nodeId) {
return this.objectCache.getNode(nodeId);
}
/**
* Remove a single node from the graph.

@@ -359,2 +367,10 @@ *

/**
* Get the edge with the given id.
*
* @param edgeId the id of the edge
*/
getEdge(edgeId) {
return this.objectCache.getEdge(edgeId);
}
/**
* Remove a single edge from the graph.

@@ -381,2 +397,18 @@ *

/**
* Get all edges that have the given nodeId as source
*
* @param sourceNodeId the node id of the edge source
*/
getEdgesBySource(sourceNodeId) {
return this.objectCache.getEdgesBySource(sourceNodeId);
}
/**
* Get all edges that have the given nodeId as target
*
* @param targetNodeId the node id of the edge target
*/
getEdgesByTarget(targetNodeId) {
return this.objectCache.getEdgesByTarget(targetNodeId);
}
/**
* Set the graph interaction mode and cleanup temp data from old interaction mode.

@@ -606,2 +638,16 @@ *

/**
* Updates and reflows all text elements in nodes.
*
* @param force force text rewrap even when text has not changed
* (useful if node classes can change text attributes like size)
*/
updateTextElements(force = false) {
const svg = this.getSvg();
const graph = svg.select('g.zoom-group');
const nodeSelection = graph.select('.nodes')
.selectAll('g.node')
.data(this._nodes, (d) => d.id.toString());
this.updateNodeText(nodeSelection, force);
}
/**
* Add nodes to graph.

@@ -755,4 +801,11 @@ *

.call(this.updateNodeClasses.bind(this))
.call(this.updateNodeHighligts.bind(this));
// allow node drag and drop
.call(this.updateNodeHighligts.bind(this))
.call(this.updateNodeText.bind(this));
}
/**
* Update text of existing nodes.
*
* @param nodeSelection d3 selection of nodes to update with bound data
*/
updateNodeText(nodeSelection, force = false) {
nodeSelection.each(function (d) {

@@ -767,2 +820,3 @@ const singleNodeSelection = d3_1.select(this);

if (attr.includes('.')) {
// recursive decend along path
const path = attr.split('.');

@@ -787,3 +841,5 @@ let temp = d;

}
textwrap_1.wrapText(this, newText);
// make sure it is a string
newText = newText.toString();
textwrap_1.wrapText(this, newText, force);
});

@@ -964,27 +1020,35 @@ });

updateEdgePath(edgeSelection) {
edgeSelection.attr('d', (d) => {
const handles = this.objectCache.getEdgeLinkHandles(d);
const points = [];
points.push(handles.sourceCoordinates);
if (handles.sourceHandle.normal != null) {
points.push({
x: handles.sourceCoordinates.x + (handles.sourceHandle.normal.dx * 10),
y: handles.sourceCoordinates.y + (handles.sourceHandle.normal.dy * 10),
});
}
const offset = (d.markerEnd != null && d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
if (handles.targetHandle.normal != null) {
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * (10 + offset)),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * (10 + offset)),
});
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * offset),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * offset),
});
}
else {
points.push(handles.targetCoordinates);
}
return this.edgeGenerator(points);
const self = this;
edgeSelection.each(function (d) {
const singleEdgeSelection = d3_1.select(this);
const strokeWidth = parseFloat(singleEdgeSelection.style('stroke-width').replace(/px/, ''));
singleEdgeSelection.attr('d', () => {
const handles = self.objectCache.getEdgeLinkHandles(d);
const points = [];
points.push(handles.sourceCoordinates);
if (handles.sourceHandle.normal != null) {
points.push({
x: handles.sourceCoordinates.x + (handles.sourceHandle.normal.dx * 10),
y: handles.sourceCoordinates.y + (handles.sourceHandle.normal.dy * 10),
});
}
let offset = (d.markerEnd != null && d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
if (d.markerEnd != null && d.markerEnd.scale != null && !(!d.markerEnd.scaleRelative)) {
offset *= strokeWidth;
}
if (handles.targetHandle.normal != null) {
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * (10 + offset)),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * (10 + offset)),
});
points.push({
x: handles.targetCoordinates.x + (handles.targetHandle.normal.dx * offset),
y: handles.targetCoordinates.y + (handles.targetHandle.normal.dy * offset),
});
}
else {
points.push(handles.targetCoordinates);
}
return self.edgeGenerator(points);
});
});

@@ -1051,3 +1115,6 @@ }

let transform = '';
const offset = (d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
let offset = (d.markerEnd.lineOffset != null) ? d.markerEnd.lineOffset : 0;
if (d.markerEnd.scale != null && !(!d.markerEnd.scaleRelative)) {
offset *= strokeWidth;
}
const point = {

@@ -1054,0 +1121,0 @@ x: pathEndpoint.x + (edgeNormal.dx * offset),

@@ -165,3 +165,3 @@ "use strict";

}
else if (isNaN(parseInt(linkHandles, 10))) {
else if (!isNaN(parseInt(linkHandles, 10))) {
nrOfHandles = parseInt(linkHandles, 10);

@@ -168,0 +168,0 @@ }

@@ -17,3 +17,3 @@ import { RotationVector } from './rotation-vector';

scale?: number;
/** If true the marker is scaled relative to the stroke width. */
/** If true the marker and lineOffset is scaled relative to the stroke width. */
scaleRelative?: boolean;

@@ -20,0 +20,0 @@ /** Rotation information for the marker. */

@@ -33,3 +33,3 @@ import { Node } from './node';

getEdgesByTarget(targetId: number | string): Set<Edge>;
getEdgesBySource(targetId: number | string): Set<Edge>;
getEdgesBySource(sourceId: number | string): Set<Edge>;
getEdgeLinkHandles(edge: Edge): {

@@ -36,0 +36,0 @@ sourceHandle: LinkHandle;

@@ -121,4 +121,4 @@ "use strict";

}
getEdgesBySource(targetId) {
const edges = this.edgesBySource.get(targetId.toString());
getEdgesBySource(sourceId) {
const edges = this.edgesBySource.get(sourceId.toString());
if (edges == null) {

@@ -125,0 +125,0 @@ return new Set();

@@ -15,3 +15,4 @@ /**

* @param newText text to wrap
* @param force force rewrap
*/
export declare function wrapText(element: SVGTextElement, newText: any): void;
export declare function wrapText(element: SVGTextElement, newText: any, force?: boolean): void;

@@ -34,4 +34,5 @@ "use strict";

* @param newText text to wrap
* @param force force rewrap
*/
function wrapText(element, newText) {
function wrapText(element, newText, force = false) {
const text = d3_1.select(element);

@@ -63,3 +64,3 @@ const x = parseFloat(text.attr('x'));

if (isNaN(height)) {
const overflow = lTrim(wrapSingleLine(element, width, newText, overflowMode, wordBreak));
const overflow = lTrim(wrapSingleLine(element, width, newText, overflowMode, wordBreak, force));
text.attr('data-wrapped', overflow !== '' ? 'true' : 'false');

@@ -74,3 +75,3 @@ return;

const last = index < (lines.length - 1);
newText = lTrim(wrapSingleLine(line, width, newText, last ? 'clip' : overflowMode, last ? wordBreak : 'break-all'));
newText = lTrim(wrapSingleLine(line, width, newText, last ? 'clip' : overflowMode, last ? wordBreak : 'break-all', force));
}

@@ -138,4 +139,3 @@ }

spanSelection.exit().remove();
spanSelection.enter().append('tspan').attr('x', x).attr('y', d => d);
return spanSelection;
return spanSelection.enter().append('tspan').attr('x', x).attr('y', d => d).merge(spanSelection);
}

@@ -150,4 +150,5 @@ /**

* @param wordBreak break mode
* @param force force rewrap
*/
function wrapSingleLine(element, width, newText, mode = 'ellipsis', wordBreak = 'break-word') {
function wrapSingleLine(element, width, newText, mode = 'ellipsis', wordBreak = 'break-word', force = false) {
const text = d3_1.select(element);

@@ -163,3 +164,3 @@ const oldText = text.text();

// shortcuts (when text is already wrapped)
if (oldText != null && oldText !== '') {
if (!force && oldText != null && oldText !== '') {
if (oldText.startsWith(newText)) {

@@ -170,3 +171,3 @@ // newText is shorter

}
if (mode === 'clip') {
else if (mode === 'clip') {
if (text.attr('data-wrapped') === 'true' && newText.startsWith(oldText)) {

@@ -173,0 +174,0 @@ // odlText was wrapped and newText begins with oldText

{
"name": "@ustutt/grapheditor-webcomponent",
"version": "0.0.2",
"version": "0.0.3",
"description": "Webcomponent for displaying and editing graphs.",

@@ -5,0 +5,0 @@ "author": "MICO Authors",

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc