Compare commits

...

48 Commits

Author SHA1 Message Date
Dylan Vorster
cd3bdd1193 Merge pull request #1043 from sergkot2020/right-angle-link-fix
Update RightAngleLinkWidget.tsx
2025-04-03 11:33:04 -06:00
Dylan Vorster
7941080b78 Merge pull request #1047 from Braun-IT-Solutions/react-19
Update for React 19
2025-04-03 11:32:39 -06:00
Daniel Spindler
18bc961caa Updated lock 2025-04-03 11:27:29 +02:00
Daniel Spindler
03916ffae1 Fixed errornous dependency 2025-04-03 11:27:01 +02:00
Daniel Spindler
f81d9c20ed Fixed typo 2025-04-03 11:24:20 +02:00
Daniel Spindler
d8284aa8a4 Fixed formatting 2025-03-27 14:06:15 +01:00
Daniel Spindler
3499a6ca75 Updated babel in demo project 2025-03-27 14:04:37 +01:00
Daniel Spindler
7d2156217b Updated babel and fixed storybook 2025-03-27 14:02:45 +01:00
Daniel Spindler
ffc5ca5cf0 Updated storybook config 2025-03-27 13:31:37 +01:00
Daniel Spindler
3f8fb35f2d Updated @storybook/addons 2025-03-27 13:29:24 +01:00
Daniel Spindler
94d31f357e Reverted event change 2025-03-27 13:25:00 +01:00
Daniel Spindler
430e922fca Added changeset 2025-03-27 13:16:20 +01:00
Daniel Spindler
53215dca92 Removed old overrides. Added overrides to root package.json. 2025-03-27 12:09:23 +01:00
Daniel Spindler
cb643abc66 Added overrides which don't seem to work 2025-03-26 15:45:38 +01:00
Daniel Spindler
c74178a9ed Updated more things 2025-03-26 15:05:09 +01:00
Daniel Spindler
a7ea1d22d2 Removed wrong dependency 2025-03-26 14:07:32 +01:00
Daniel Spindler
8affa65ffa Updated react 2025-03-26 14:00:27 +01:00
Sergey Novozhilov
eb24c088c2 Update RightAngleLinkWidget.tsx
The getRenderedPath method returns an empty array all the time. for RightAngle links. And this edit fix this problem.
2024-11-05 12:56:00 +03:00
Dylan Vorster
999f4902e2 Merge pull request #1030 from projectstorm/changeset-release/master
Version Packages
2024-02-19 15:11:00 -07:00
github-actions[bot]
a3affc4ff2 Version Packages 2024-02-19 22:10:50 +00:00
Dylan Vorster
79bdc80910 Merge pull request #1029 from projectstorm/fix_demos
fix the demos
2024-02-19 15:10:22 -07:00
Dylan Vorster
adb441536f changeset 2024-02-19 15:09:37 -07:00
Dylan Vorster
1e84a03aa5 fix the demos 2024-02-19 15:07:14 -07:00
Dylan Vorster
e497715520 Merge pull request #1028 from projectstorm/changeset-release/master
Version Packages
2024-02-15 00:24:48 -07:00
github-actions[bot]
42d43519d2 Version Packages 2024-02-15 07:23:36 +00:00
Dylan Vorster
78d10b8ff0 Merge pull request #1021 from LynchyC/master
Update lodash imports to use individual functions
2024-02-15 00:23:03 -07:00
Dylan Vorster
5045968abd Merge pull request #1014 from marian2js/master
fix: default link widget with react strict mode
2024-02-15 00:20:51 -07:00
Dylan Vorster
633d03a831 Merge pull request #1025 from TenTakano/remove_settimeout_from_demo_dagre
Remove setTimeout from demo-dagre to avoid layout breaks
2024-02-15 00:16:09 -07:00
Dylan Vorster
8031008e71 Merge pull request #1022 from jeevcat/master
Allow more derived State classes to be parameterized with a generic type
2024-02-15 00:14:11 -07:00
TenTakano
1be40737f5 Add changeset 2023-12-28 14:13:18 +09:00
TenTakano
7ab3572ea1 Remove setTimeout from demo-dagre to avoid layout breaks 2023-12-28 14:13:18 +09:00
Sam Jeeves
09ed60ff64 changeset 2023-12-16 15:00:41 +01:00
Sam Jeeves
8c2577703f Allow more derived State classes to provide a generic type 2023-12-16 14:55:13 +01:00
Charlie Lynch
80285feee5 release: add changeset 2023-11-08 21:14:26 +00:00
Charlie Lynch
cd8049dad1 refactor: update lodash imports to use individual functions 2023-11-08 21:07:46 +00:00
Dylan Vorster
a457385a8c storybook build fixes 2023-09-23 14:28:19 -06:00
Dylan Vorster
63b39cba79 Merge pull request #1019 from projectstorm/changeset-release/master
Version Packages
2023-09-23 14:24:05 -06:00
github-actions[bot]
a671b50e09 Version Packages 2023-09-23 20:22:45 +00:00
Dylan Vorster
7a664d5b64 Merge pull request #1018 from projectstorm/pnpm_upgrade
Maintenance
2023-09-23 14:22:03 -06:00
Dylan Vorster
66c687afc6 changeset 2023-09-23 14:18:27 -06:00
Dylan Vorster
23b5467806 upgrade everything 2023-09-23 14:16:35 -06:00
Dylan Vorster
1889c7cb40 lockfile 2023-09-23 14:00:39 -06:00
Dylan Vorster
c3146e1aa8 Update README.md 2023-09-23 13:57:22 -06:00
Dylan Vorster
8fb8d04885 Update README.md
missed a few
2023-09-23 13:56:44 -06:00
Dylan Vorster
74e814ab5a Update README.md
This project uses pnpm instead of yarn
2023-09-23 13:56:17 -06:00
marian2js
20766f539e fix: default link widget with react strict mode 2023-08-10 15:34:16 +01:00
Dylan Vorster
3d4e0b24d7 Merge pull request #1007 from projectstorm/dylanvorster-patch-1
Update CHANGELOG.md
2023-06-04 15:32:08 -06:00
Dylan Vorster
efd64ad278 Update CHANGELOG.md 2023-06-04 15:32:01 -06:00
86 changed files with 7640 additions and 11886 deletions

View File

@@ -0,0 +1,11 @@
---
'@projectstorm/react-diagrams-defaults': patch
'@projectstorm/react-diagrams-routing': patch
'@projectstorm/react-diagrams-core': patch
'@projectstorm/react-canvas-core': patch
'@projectstorm/react-diagrams-gallery': patch
'@projectstorm/react-diagrams-demo': patch
'@projectstorm/geometry': patch
---
Updated packages to support React v19

View File

@@ -157,7 +157,7 @@ __5.1.0__
* (refactor) consistently use lodash where possible
* (maintenance) upgrade node modules
__5.0.0__ http://dylanv.blog/2018/03/03/storm-react-diagrams-5-0-0/
__5.0.0__ [http://dylanv.blog/2018/03/03/storm-react-diagrams-5-0-0/](https://dylanvorster.com/storm-react-diagrams-v5-0/)
PR: https://github.com/projectstorm/react-diagrams/pull/145
@@ -174,7 +174,7 @@ PR: https://github.com/projectstorm/react-diagrams/pull/145
* (tests) automatically load JEST Snapshots
* (feature) Link labels!
__4.0.0__ http://dylanv.blog/2018/01/18/storm-react-diagrams-v4-0-0/
__4.0.0__ [http://dylanv.blog/2018/01/18/storm-react-diagrams-v4-0-0/](https://dylanvorster.com/storm-react-diagrams-v4-0/)
* (refactor) Events system was completely overhauled
* (demo) Custom Link Sizes
@@ -188,7 +188,7 @@ __4.0.0__ http://dylanv.blog/2018/01/18/storm-react-diagrams-v4-0-0/
* (demo) Cloning
* (feature) models control isLocked
__3.2.0__ http://dylanv.blog/2017/11/22/storm-react-diagrams-3-2-0/
__3.2.0__ [http://dylanv.blog/2017/11/22/storm-react-diagrams-3-2-0/](https://dylanvorster.com/storm-react-diagrams-3-2-0/)
* (feature) zoom to fit
* added Circle CI tests
* (demo) dagre automatic layouts
@@ -211,14 +211,14 @@ __3.1.2__
* Hotfix: fix zooming when canvas not in the top left corner
(https://github.com/projectstorm/react-diagrams/pull/88)
__3.1.0__ http://dylanv.blog/2017/09/15/storm-react-diagrams-3-1-0/
__3.1.0__ [http://dylanv.blog/2017/09/15/storm-react-diagrams-3-1-0/](https://dylanvorster.com/storm-react-diagrams-3-1-0/)
* Zoom relative to mouse location
* Fixed links not connecting when grid is larger than port size
* Prevented points from dragging when connected to a port and the node itself is not selected
* API fixes
* Code cleanup
__3.0.0__ http://dylanv.blog/2017/09/13/storm-react-diagrams-v3/
__3.0.0__ [http://dylanv.blog/2017/09/13/storm-react-diagrams-v3/](https://dylanvorster.com/storm-react-diagrams-3-0/)
* Massive performance updates
* Complete rewrite
* Started a changelog and design documents for each revision

View File

@@ -70,7 +70,7 @@ yarn add @projectstorm/react-diagrams-routing
## How to use
Before running any of the examples, please run `yarn build` in the root. This project is a monorepo, and the packages (including the demos) require the packages to first be built.
Before running any of the examples, please run `pnpm build` in the root. This project is a monorepo, and the packages (including the demos) require the packages to first be built.
Take a look at the [diagram demos](https://github.com/projectstorm/react-diagrams/tree/master/diagrams-demo-gallery/demos)
@@ -85,11 +85,11 @@ Take a look at the [demo project](https://github.com/projectstorm/react-diagrams
## Run the demos
After running `yarn install` and `yarn build`, you must then run: `cd diagrams-demo-gallery && yarn run start`
After running `pnpm install` and `pnpm build`, you must then run: `cd diagrams-demo-gallery && pnpm run start`
## Building from source
Simply run `yarn` then `yarn build` or `yarn build:prod` in the root directory and it will spit out the transpiled code and typescript definitions into the dist directory as a single file.
Simply run `pnpm` then `pnpm build` or `pnpm build:prod` in the root directory and it will spit out the transpiled code and typescript definitions into the dist directory as a single file.
## Built with react-diagrams

View File

@@ -0,0 +1,18 @@
{
"sourceType": "unambiguous",
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": 100,
"safari": 15,
"firefox": 91
}
}
],
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": []
}

View File

@@ -1,7 +1,5 @@
module.exports = {
stories: ['../demos/*.stories.tsx'],
core: {
builder: 'webpack5'
},
addons: ['@storybook/addon-actions']
addons: ['@storybook/addon-actions', '@storybook/addon-webpack5-compiler-babel'],
framework: '@storybook/react-webpack5'
};

View File

@@ -1,4 +1,4 @@
import { addons } from '@storybook/addons';
import { addons } from '@storybook/manager-api';
import diagramsTheme from './theme';

View File

@@ -0,0 +1,5 @@
<style>
html, body, #storybook-root {
height: 100%;
}
</style>

View File

@@ -1,5 +1,39 @@
# @projectstorm/react-diagrams-gallery
## 7.2.1
### Patch Changes
- adb4415: Fixed the demos
## 7.2.0
### Minor Changes
- 1be4073: Remove setTimeout from demo-dagre to avoid layout breaks
### Patch Changes
- 80285fe: refactor: update lodash imports to use individual functions
- Updated dependencies [09ed60f]
- Updated dependencies [20766f5]
- Updated dependencies [80285fe]
- @projectstorm/react-canvas-core@7.0.3
- @projectstorm/react-diagrams-core@7.0.3
- @projectstorm/react-diagrams-defaults@7.1.3
- @projectstorm/react-diagrams@7.0.4
## 7.1.2
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
- Updated dependencies [66c687a]
- @projectstorm/react-diagrams-defaults@7.1.2
- @projectstorm/react-diagrams-core@7.0.2
- @projectstorm/react-canvas-core@7.0.2
- @projectstorm/react-diagrams@7.0.3
## 7.1.1
### Patch Changes

View File

@@ -1,5 +1,5 @@
import createEngine, { DiagramModel, DefaultNodeModel, LinkModel, NodeModel } from '@projectstorm/react-diagrams';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import * as React from 'react';
import { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';
import { BaseModel, CanvasWidget } from '@projectstorm/react-canvas-core';
@@ -20,7 +20,7 @@ class CloneSelected extends React.Component<any, any> {
let model = engine.getModel();
let itemMap = {};
_.forEach(model.getSelectedEntities(), (item: BaseModel<any>) => {
_forEach(model.getSelectedEntities(), (item: BaseModel<any>) => {
let newItem = item.clone(itemMap);
// offset the nodes slightly

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import createEngine, { DiagramModel, DefaultNodeModel, DefaultLinkModel } from '@projectstorm/react-diagrams';
import { CanvasWidget, Action, ActionEvent, InputType } from '@projectstorm/react-canvas-core';
import { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';
@@ -26,7 +26,7 @@ class CustomDeleteItemsAction extends Action {
const confirm = window.confirm('Are you sure you want to delete?');
if (confirm) {
_.forEach(selectedEntities, (model) => {
_forEach(selectedEntities, (model) => {
// only delete items which are not locked
if (!model.isLocked()) {
model.remove();

View File

@@ -4,6 +4,7 @@ import { DiagramEngine } from '@projectstorm/react-diagrams';
import { EditableLabelModel } from './EditableLabelModel';
import { EditableLabelWidget } from './EditableLabelWidget';
import { JSX } from 'react';
export class EditableLabelFactory extends AbstractReactFactory<EditableLabelModel, DiagramEngine> {
constructor() {

View File

@@ -10,7 +10,9 @@ import { LinkWidget, PointModel } from '@projectstorm/react-diagrams-core';
import * as React from 'react';
import { CanvasWidget } from '@projectstorm/react-canvas-core';
import { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';
import { MouseEvent } from 'react';
import { JSX, MouseEvent } from 'react';
import { DefaultLinkPointWidget, DefaultLinkSegmentWidget } from '@projectstorm/react-diagrams-defaults/dist';
import { DiagramEngine } from '@projectstorm/react-diagrams-core/dist';
export class AdvancedLinkModel extends DefaultLinkModel {
constructor() {
@@ -56,7 +58,56 @@ const CustomLinkArrowWidget = (props) => {
);
};
export class AdvancedLinkWidget extends DefaultLinkWidget {
export interface AdvancedLinkWWidgetProps {
link: DefaultLinkModel;
diagramEngine: DiagramEngine;
pointAdded?: (point: PointModel, event: MouseEvent) => any;
renderPoints?: boolean;
selected?: (event: MouseEvent) => any;
}
export class AdvancedLinkWidget extends React.Component<AdvancedLinkWWidgetProps> {
generatePoint = (point: PointModel): JSX.Element => {
return (
<DefaultLinkPointWidget
key={point.getID()}
point={point as any}
colorSelected={this.props.link.getOptions().selectedColor ?? ''}
color={this.props.link.getOptions().color}
/>
);
};
generateLink = (path: string, extraProps: any, id: string | number): JSX.Element => {
return (
<DefaultLinkSegmentWidget
key={`link-${id}`}
path={path}
diagramEngine={this.props.diagramEngine}
factory={this.props.diagramEngine.getFactoryForLink(this.props.link)}
link={this.props.link}
extras={extraProps}
/>
);
};
addPointToLink = (event: MouseEvent, index: number) => {
if (
!event.shiftKey &&
!this.props.link.isLocked() &&
this.props.link.getPoints().length - 1 <= this.props.diagramEngine.getMaxNumberPointsPerLink()
) {
const position = this.props.diagramEngine.getRelativeMousePoint(event);
const point = this.props.link.point(position.x, position.y, index);
event.persist();
event.stopPropagation();
this.props.diagramEngine.getActionEventBus().fireAction({
event,
model: point
});
}
};
generateArrow(point: PointModel, previousPoint: PointModel): JSX.Element {
return (
<CustomLinkArrowWidget
@@ -73,7 +124,6 @@ export class AdvancedLinkWidget extends DefaultLinkWidget {
//ensure id is present for all points on the path
var points = this.props.link.getPoints();
var paths = [];
this.refPaths = [];
//draw the multiple anchors and complex line instead
for (let j = 0; j < points.length - 1; j++) {

View File

@@ -3,6 +3,7 @@ import { DiamondNodeModel } from './DiamondNodeModel';
import * as React from 'react';
import { AbstractReactFactory } from '@projectstorm/react-canvas-core';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { JSX } from 'react';
export class DiamondNodeFactory extends AbstractReactFactory<DiamondNodeModel, DiagramEngine> {
constructor() {

View File

@@ -7,7 +7,7 @@ import createEngine, {
DiagramEngine,
PathFindingLinkFactory
} from '@projectstorm/react-diagrams';
import * as React from 'react';
import { useLayoutEffect, useRef } from 'react';
import { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';
import { CanvasWidget } from '@projectstorm/react-canvas-core';
import { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';
@@ -33,72 +33,79 @@ function connectNodes(nodeFrom, nodeTo, engine: DiagramEngine) {
/**
* Tests auto distribution
*/
class DemoWidget extends React.Component<{ model: DiagramModel; engine: DiagramEngine }, any> {
engine: DagreEngine;
function genDagreEngine() {
return new DagreEngine({
graph: {
rankdir: 'RL',
ranker: 'longest-path',
marginx: 25,
marginy: 25
},
includeLinks: true,
nodeMargin: 25
});
}
constructor(props) {
super(props);
this.engine = new DagreEngine({
graph: {
rankdir: 'RL',
ranker: 'longest-path',
marginx: 25,
marginy: 25
},
includeLinks: true,
nodeMargin: 25
});
}
function autoDistribute(engine: DiagramEngine) {
const model = engine.getModel();
autoDistribute = () => {
this.engine.redistribute(this.props.model);
const dagreEngine = genDagreEngine();
dagreEngine.redistribute(model);
// only happens if pathfing is enabled (check line 25)
this.reroute();
this.props.engine.repaintCanvas();
reroute(engine);
engine.repaintCanvas();
}
function autoRefreshLinks(engine: DiagramEngine) {
const model = engine.getModel();
const dagreEngine = genDagreEngine();
dagreEngine.refreshLinks(model);
// only happens if pathfing is enabled (check line 29)
reroute(engine);
engine.repaintCanvas();
}
function reroute(engine: DiagramEngine) {
engine.getLinkFactories().getFactory<PathFindingLinkFactory>(PathFindingLinkFactory.NAME).calculateRoutingMatrix();
}
function DemoWidget(props) {
const engine = props.engine;
useLayoutEffect(() => {
autoDistribute(engine);
}, []);
const redistribute = () => {
autoDistribute(engine);
};
autoRefreshLinks = () => {
this.engine.refreshLinks(this.props.model);
// only happens if pathfing is enabled (check line 25)
this.reroute();
this.props.engine.repaintCanvas();
const refreshLinks = () => {
autoRefreshLinks(engine);
};
componentDidMount(): void {
setTimeout(() => {
this.autoDistribute();
}, 500);
}
reroute() {
this.props.engine
.getLinkFactories()
.getFactory<PathFindingLinkFactory>(PathFindingLinkFactory.NAME)
.calculateRoutingMatrix();
}
render() {
return (
<DemoWorkspaceWidget
buttons={
<div>
<DemoButton onClick={this.autoDistribute}>Re-distribute</DemoButton>
<DemoButton onClick={this.autoRefreshLinks}>Refresh Links</DemoButton>
</div>
}
>
<DemoCanvasWidget>
<CanvasWidget engine={this.props.engine} />
</DemoCanvasWidget>
</DemoWorkspaceWidget>
);
}
return (
<DemoWorkspaceWidget
buttons={
<div>
<DemoButton onClick={redistribute}>Re-distribute</DemoButton>
<DemoButton onClick={refreshLinks}>Refresh Links</DemoButton>
</div>
}
>
<DemoCanvasWidget>
<CanvasWidget engine={engine} />
</DemoCanvasWidget>
</DemoWorkspaceWidget>
);
}
export default () => {
//1) setup the diagram engine
let engine = createEngine();
const engineRef = useRef(createEngine());
let engine = engineRef.current;
//2) setup the diagram model
let model = new DiagramModel();

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import * as _ from 'lodash';
import _keys from 'lodash/keys';
import { TrayWidget } from './TrayWidget';
import { Application } from '../Application';
import { TrayItemWidget } from './TrayItemWidget';
@@ -57,7 +57,7 @@ export class BodyWidget extends React.Component<BodyWidgetProps> {
<S.Layer
onDrop={(event) => {
var data = JSON.parse(event.dataTransfer.getData('storm-diagram-node'));
var nodesCount = _.keys(this.props.app.getDiagramEngine().getModel().getNodes()).length;
var nodesCount = _keys(this.props.app.getDiagramEngine().getModel().getNodes()).length;
var node: DefaultNodeModel = null;
if (data.type === 'in') {

View File

@@ -1,5 +1,5 @@
import createEngine, { DiagramModel, DefaultNodeModel, DiagramEngine } from '@projectstorm/react-diagrams';
import * as _ from 'lodash';
import _values from 'lodash/values';
import * as React from 'react';
import { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';
import { CanvasWidget } from '@projectstorm/react-canvas-core';
@@ -7,7 +7,7 @@ import { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';
class CloneSelected extends React.Component<{ model: DiagramModel; engine: DiagramEngine }, any> {
addPorts = () => {
const nodes: DefaultNodeModel[] = _.values(this.props.model.getNodes()) as DefaultNodeModel[];
const nodes: DefaultNodeModel[] = _values(this.props.model.getNodes()) as DefaultNodeModel[];
for (let node of nodes) {
if (node.getOptions().name === 'Node 2') {
node.addInPort(`in-${node.getInPorts().length + 1}`, false);

View File

@@ -1,6 +1,6 @@
import createEngine, { DiagramModel, DefaultNodeModel, NodeModel } from '@projectstorm/react-diagrams';
import * as React from 'react';
import * as _ from 'lodash';
import _values from 'lodash/values';
import { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';
import { CanvasWidget } from '@projectstorm/react-canvas-core';
import { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';
@@ -30,7 +30,7 @@ class NodeDelayedPosition extends React.Component<any, any> {
let str = JSON.stringify(model.serialize());
let model2 = new DiagramModel();
let obj: ReturnType<DiagramModel['serialize']> = JSON.parse(str);
let node: ReturnType<NodeModel['serialize']> = _.values(obj.layers[1].models)[0] as any;
let node: ReturnType<NodeModel['serialize']> = _values(obj.layers[1].models)[0] as any;
node.x += 30;
node.y += 30;

View File

@@ -1,6 +1,6 @@
html,
body,
#root {
#storybook-root {
height: 100%;
padding: 0;
margin: 0;

View File

@@ -1,48 +1,54 @@
{
"name": "@projectstorm/react-diagrams-gallery",
"version": "7.1.1",
"author": "dylanvorster",
"license": "MIT",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/projectstorm/react-diagrams.git"
},
"scripts": {
"start": "./node_modules/.bin/start-storybook",
"storybook:build": "./node_modules/.bin/build-storybook -c .storybook -o .out"
},
"keywords": [
"web",
"diagram",
"diagrams",
"react",
"typescript",
"flowchart",
"simple",
"links",
"nodes"
],
"dependencies": {
"lodash": "^4.17.21",
"@projectstorm/react-canvas-core": "workspace:*",
"@projectstorm/react-diagrams": "workspace:*",
"@projectstorm/react-diagrams-core": "workspace:*",
"@projectstorm/react-diagrams-defaults": "workspace:*",
"gsap": "^3.11.4",
"json-beautify": "^1.1.1",
"react": "^18.2.0"
},
"devDependencies": {
"@types/lodash": "^4.14.191",
"@types/react": "^18.0.27",
"@storybook/addons": "^6.5.15",
"@storybook/addon-actions": "^6.5.15",
"@storybook/addon-options": "^5.3.21",
"@storybook/builder-webpack5": "^6.5.15",
"@storybook/manager-webpack5": "^6.5.15",
"@storybook/react": "^6.5.15",
"@storybook/storybook-deployer": "^2.8.16",
"@storybook/theming": "^6.5.15"
}
"name": "@projectstorm/react-diagrams-gallery",
"version": "7.2.1",
"author": "dylanvorster",
"license": "MIT",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/projectstorm/react-diagrams.git"
},
"scripts": {
"start": "pnpm storybook dev",
"storybook:build": "pnpm storybook build -c .storybook -o .out"
},
"keywords": [
"web",
"diagram",
"diagrams",
"react",
"typescript",
"flowchart",
"simple",
"links",
"nodes"
],
"dependencies": {
"@projectstorm/react-canvas-core": "workspace:*",
"@projectstorm/react-diagrams": "workspace:*",
"@projectstorm/react-diagrams-core": "workspace:*",
"@projectstorm/react-diagrams-defaults": "workspace:*",
"gsap": "^3.12.2",
"json-beautify": "^1.1.1",
"lodash": "^4.17.21",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@babel/preset-env": "^7.26.9",
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.27.0",
"@storybook/addon-actions": "^8.6.9",
"@storybook/addon-webpack5-compiler-babel": "^3.0.5",
"@storybook/manager-api": "^8.6.10",
"@storybook/preview-api": "^8.6.10",
"@storybook/react": "^8.6.9",
"@storybook/react-webpack5": "^8.6.9",
"@storybook/storybook-deployer": "^2.8.16",
"@storybook/theming": "^8.6.9",
"@types/lodash": "^4.14.200",
"@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4",
"storybook": "^8.6.9"
}
}

View File

@@ -1,7 +1,7 @@
{
"compileOnSave": false,
"compilerOptions": {
"suppressExcessPropertyErrors": true,
"esModuleInterop": true,
"declaration": true,
"composite": true,
"incremental": true,

View File

@@ -1,5 +1,18 @@
# @projectstorm/react-diagrams-demo
## 7.0.4
### Patch Changes
- @projectstorm/react-diagrams@7.0.4
## 7.0.3
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
- @projectstorm/react-diagrams@7.0.3
## 7.0.2
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/react-diagrams-demo",
"version": "7.0.2",
"version": "7.0.4",
"author": "dylanvorster",
"license": "MIT",
"private": true,
@@ -26,21 +26,21 @@
"typings": "./dist/@types/index",
"dependencies": {
"@projectstorm/react-diagrams": "workspace:*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@babel/core": "^7.26.10",
"@babel/preset-react": "^7.26.3",
"@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.3",
"source-map-loader": "^4.0.1",
"html-webpack-plugin": "^5.5.0",
"@babel/core": "^7.20.12",
"@babel/preset-react": "^7.18.6",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"babel-loader": "^9.1.2",
"css-loader": "^6.7.3",
"style-loader": "^3.3.1",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
"style-loader": "^3.3.3",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}

View File

@@ -3,6 +3,7 @@ import { TSCustomNodeModel } from './TSCustomNodeModel';
import { TSCustomNodeWidget } from './TSCustomNodeWidget';
import { AbstractReactFactory } from '@projectstorm/react-diagrams';
import { DiagramEngine } from '@projectstorm/react-diagrams';
import { JSX } from 'react';
export class TSCustomNodeFactory extends AbstractReactFactory<TSCustomNodeModel, DiagramEngine> {
constructor() {

View File

@@ -18,31 +18,36 @@
"nodes"
],
"scripts": {
"ncu": "ncu -u && pnpm recursive exec -- ncu -u",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx}\"",
"clean": "rm -rf packages/*/dist",
"test": "pnpm run -r test",
"build": "tsc --build && pnpm run -r build",
"build:prod": "NODE_ENV=production pnpm build",
"release": "pnpm build:prod && pnpm changeset publish",
"release:storybook": "tsc --build && cd diagrams-demo-gallery && pnpm storybook:build && ./node_modules/.bin/storybook-to-ghpages --existing-output-dir .out"
"ncu": "ncu -u && pnpm recursive exec -- ncu -u",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx}\"",
"clean": "rm -rf packages/*/dist",
"test": "pnpm run -r test",
"build": "tsc --build && pnpm run -r build",
"build:prod": "NODE_ENV=production pnpm build",
"release": "pnpm build:prod && pnpm changeset publish",
"release:storybook": "tsc --build && cd diagrams-demo-gallery && pnpm storybook:build && ./node_modules/.bin/storybook-to-ghpages --existing-output-dir .out"
},
"devDependencies": {
"@changesets/cli": "^2.26.0",
"@types/jest": "^29.2.6",
"@types/node": "^18.11.18",
"jest": "^29.4.0",
"jest-cli": "^29.4.0",
"prettier": "^2.8.3",
"rimraf": "^4.1.2",
"@changesets/cli": "^2.26.2",
"@types/jest": "^29.5.5",
"@types/node": "^20.6.3",
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"prettier": "^3.0.3",
"rimraf": "^5.0.1",
"source-map-loader": "^4.0.1",
"terser-webpack-plugin": "^5.3.6",
"ts-jest": "^29.0.5",
"ts-loader": "^9.4.2",
"typescript": "^4.9.4",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1",
"terser-webpack-plugin": "^5.3.9",
"ts-jest": "^29.1.1",
"ts-loader": "^9.4.4",
"typescript": "^5.2.2",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-node-externals": "^3.0.0"
},
"pnpm": {
"overrides": {
"react": "^19.0.0"
}
}
}

View File

@@ -1,5 +1,17 @@
# @projectstorm/geometry
## 7.0.3
### Patch Changes
- 80285fe: refactor: update lodash imports to use individual functions
## 7.0.2
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
## 7.0.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/geometry",
"version": "7.0.1",
"version": "7.0.3",
"author": "dylanvorster",
"license": "MIT",
"repository": {
@@ -32,6 +32,6 @@
"lodash": "^4.17.21"
},
"devDependencies": {
"@types/lodash": "^4.14.191"
"@types/lodash": "^4.14.200"
}
}

View File

@@ -1,5 +1,6 @@
import { Point } from './Point';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import _map from 'lodash/map';
import { Matrix } from './Matrix';
import { boundingBoxFromPoints } from './toolkit';
import { Bounds, BoundsCorner } from './Bounds';
@@ -12,26 +13,26 @@ export class Polygon {
}
serialize() {
return _.map(this.points, (point) => {
return _map(this.points, (point) => {
return [point.x, point.y];
});
}
deserialize(data: any) {
this.points = _.map(data, (point) => {
this.points = _map(data, (point) => {
return new Point(point[0], point[1]);
});
}
scale(x, y, origin: Point) {
let matrix = Matrix.createScaleMatrix(x, y, origin);
_.forEach(this.points, (point) => {
_forEach(this.points, (point) => {
point.transform(matrix);
});
}
transform(matrix: Matrix) {
_.forEach(this.points, (point) => {
_forEach(this.points, (point) => {
point.transform(matrix);
});
}
@@ -49,13 +50,13 @@ export class Polygon {
}
translate(offsetX: number, offsetY: number) {
_.forEach(this.points, (point) => {
_forEach(this.points, (point) => {
point.translate(offsetX, offsetY);
});
}
doClone(ob: this) {
this.points = _.map(ob.points, (point) => {
this.points = _map(ob.points, (point) => {
return point.clone();
});
}

View File

@@ -1,5 +1,5 @@
import { Point } from './Point';
import * as _ from 'lodash';
import _flatMap from 'lodash/flatMap';
import { Polygon } from './Polygon';
import { Bounds, BoundsCorner, createEmptyBounds } from './Bounds';
@@ -38,7 +38,7 @@ export const boundingBoxFromPoints = (points: Point[]): Bounds => {
export const boundingBoxFromPolygons = (polygons: Polygon[]): Bounds => {
return boundingBoxFromPoints(
_.flatMap(polygons, (polygon) => {
_flatMap(polygons, (polygon) => {
return polygon.getPoints();
})
);

View File

@@ -1,13 +1,12 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"outDir": "dist",
"rootDir": "src",
"sourceMap": true,
"declarationDir": "dist/@types",
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
},
"include": [
"./src"
]
"include": ["./src"]
}

View File

@@ -1,5 +1,22 @@
# @projectstorm/react-canvas-core
## 7.0.3
### Patch Changes
- 09ed60f: Allow more derived State classes to provide a generic type
- 80285fe: refactor: update lodash imports to use individual functions
- Updated dependencies [80285fe]
- @projectstorm/geometry@7.0.3
## 7.0.2
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
- Updated dependencies [66c687a]
- @projectstorm/geometry@7.0.2
## 7.0.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/react-canvas-core",
"version": "7.0.1",
"version": "7.0.3",
"author": "dylanvorster",
"license": "MIT",
"repository": {
@@ -29,14 +29,14 @@
"module": "./dist/index.js",
"typings": "./dist/@types/index",
"dependencies": {
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.11.0",
"@projectstorm/geometry": "workspace:*",
"react": "^18.2.0",
"lodash": "^4.17.21"
"lodash": "^4.17.21",
"react": "^19.0.0"
},
"devDependencies": {
"@types/react": "^18.0.27",
"@types/lodash": "^4.14.191"
"@types/lodash": "^4.14.200",
"@types/react": "^19.0.12"
}
}

View File

@@ -1,4 +1,4 @@
import { debounce } from 'lodash';
import _debounce from 'lodash/debounce';
import { CanvasModel } from './entities/canvas/CanvasModel';
import { FactoryBank } from './core/FactoryBank';
import { AbstractReactFactory } from './core/AbstractReactFactory';
@@ -148,7 +148,7 @@ export class CanvasEngine<
let repaintFn = repaint;
if (repaintDebounceMs > 0) {
repaintFn = debounce(repaint, repaintDebounceMs);
repaintFn = _debounce(repaint, repaintDebounceMs);
}
if (promise) {

View File

@@ -1,6 +1,7 @@
import { Action, ActionEvent, InputType } from '../core-actions/Action';
import { KeyboardEvent } from 'react';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import _isEqual from 'lodash/isEqual';
export interface DeleteItemsActionOptions {
keyCodes?: number[];
@@ -31,8 +32,8 @@ export class DeleteItemsAction extends Action {
fire: (event: ActionEvent<KeyboardEvent>) => {
const { keyCode, ctrlKey, shiftKey, altKey, metaKey } = event.event;
if (keyCodes.indexOf(keyCode) !== -1 && _.isEqual({ ctrlKey, shiftKey, altKey, metaKey }, modifiers)) {
_.forEach(this.engine.getModel().getSelectedEntities(), (model) => {
if (keyCodes.indexOf(keyCode) !== -1 && _isEqual({ ctrlKey, shiftKey, altKey, metaKey }, modifiers)) {
_forEach(this.engine.getModel().getSelectedEntities(), (model) => {
// only delete items which are not locked
if (!model.isLocked()) {
model.remove();

View File

@@ -1,6 +1,7 @@
import { Action, ActionEvent, InputType } from './Action';
import { KeyboardEvent, MouseEvent } from 'react';
import * as _ from 'lodash';
import _filter from 'lodash/filter';
import _keys from 'lodash/keys';
import { CanvasEngine } from '../CanvasEngine';
import { BaseModel } from '../core-models/BaseModel';
@@ -16,7 +17,7 @@ export class ActionEventBus {
}
getKeys(): string[] {
return _.keys(this.keys);
return _keys(this.keys);
}
registerAction(action: Action): () => void {
@@ -33,7 +34,7 @@ export class ActionEventBus {
}
getActionsForType(type: InputType): Action[] {
return _.filter(this.actions, (action) => {
return _filter(this.actions, (action) => {
return action.options.type === type;
});
}

View File

@@ -1,5 +1,5 @@
import { Toolkit } from '../Toolkit';
import * as _ from 'lodash';
import _cloneDeep from 'lodash/cloneDeep';
import { CanvasEngine } from '../CanvasEngine';
import { BaseEvent, BaseListener, BaseObserver } from '../core/BaseObserver';
import { BaseModel } from './BaseModel';
@@ -62,7 +62,7 @@ export class BaseEntity<T extends BaseEntityGenerics = BaseEntityGenerics> exten
if (lookupTable[this.options.id]) {
return lookupTable[this.options.id];
}
let clone = _.cloneDeep(this);
let clone = _cloneDeep(this);
clone.options = {
...this.options,
id: Toolkit.UID()

View File

@@ -1,7 +1,7 @@
import { CanvasEngine } from '../CanvasEngine';
import { Action, ActionEvent, InputType } from '../core-actions/Action';
import { SyntheticEvent } from 'react';
import * as _ from 'lodash';
import _intersection from 'lodash/intersection';
export interface StateOptions {
name: string;
@@ -73,7 +73,7 @@ export abstract class State<E extends CanvasEngine = CanvasEngine> {
}
isKeysFullfilled(keys: string[]) {
return _.intersection(this.keys, keys).length === this.keys.length;
return _intersection(this.keys, keys).length === this.keys.length;
}
activated(previous: State) {

View File

@@ -1,5 +1,5 @@
import { State } from './State';
import * as _ from 'lodash';
import _last from 'lodash/last';
import { CanvasEngine } from '../CanvasEngine';
import { BaseEvent, BaseListener, BaseObserver } from '../core/BaseObserver';
@@ -29,7 +29,7 @@ export class StateMachine extends BaseObserver<StateMachineListener> {
popState() {
this.stateStack.pop();
this.setState(_.last(this.stateStack));
this.setState(_last(this.stateStack));
}
setState(state: State) {

View File

@@ -1,6 +1,7 @@
import { BaseModel } from '../core-models/BaseModel';
import { AbstractModelFactory } from './AbstractModelFactory';
import { CanvasEngine } from '../CanvasEngine';
import { JSX } from 'react';
export interface GenerateWidgetEvent<T extends BaseModel> {
model: T;

View File

@@ -1,6 +1,6 @@
import { BaseEvent, BaseListener, BaseObserver } from './BaseObserver';
import { AbstractFactory } from './AbstractFactory';
import * as _ from 'lodash';
import _values from 'lodash/values';
export interface FactoryBankListener<F extends AbstractFactory = AbstractFactory> extends BaseListener {
/**
@@ -29,7 +29,7 @@ export class FactoryBank<
}
getFactories(): F[] {
return _.values(this.factories);
return _values(this.factories);
}
clearFactories() {

View File

@@ -1,4 +1,8 @@
import * as _ from 'lodash';
import _filter from 'lodash/filter';
import _flatMap from 'lodash/flatMap';
import _forEach from 'lodash/forEach';
import _map from 'lodash/map';
import _values from 'lodash/values';
import {
BaseEntity,
BaseEntityEvent,
@@ -47,26 +51,26 @@ export class CanvasModel<G extends CanvasModelGenerics = CanvasModelGenerics> ex
}
getSelectionEntities(): BaseModel[] {
return _.flatMap(this.layers, (layer) => {
return _flatMap(this.layers, (layer) => {
return layer.getSelectionEntities();
});
}
getSelectedEntities(): BaseModel[] {
return _.filter(this.getSelectionEntities(), (ob) => {
return _filter(this.getSelectionEntities(), (ob) => {
return ob.isSelected();
});
}
clearSelection() {
_.forEach(this.getSelectedEntities(), (element) => {
_forEach(this.getSelectedEntities(), (element) => {
element.setSelected(false);
});
}
getModels(): BaseModel[] {
return _.flatMap(this.layers, (layer) => {
return _.values(layer.getModels());
return _flatMap(this.layers, (layer) => {
return _values(layer.getModels());
});
}
@@ -144,7 +148,7 @@ export class CanvasModel<G extends CanvasModelGenerics = CanvasModelGenerics> ex
this.options.offsetY = event.data.offsetY;
this.options.zoom = event.data.zoom;
this.options.gridSize = event.data.gridSize;
_.forEach(event.data.layers, (layer) => {
_forEach(event.data.layers, (layer) => {
const layerOb = event.engine.getFactoryForLayer(layer.type).generateModel({
initialConfig: layer
});
@@ -163,7 +167,7 @@ export class CanvasModel<G extends CanvasModelGenerics = CanvasModelGenerics> ex
offsetY: this.options.offsetY,
zoom: this.options.zoom,
gridSize: this.options.gridSize,
layers: _.map(this.layers, (layer) => {
layers: _map(this.layers, (layer) => {
return layer.serialize();
})
};

View File

@@ -1,6 +1,8 @@
import { BaseModel, BaseModelGenerics, BaseModelOptions } from '../../core-models/BaseModel';
import { CanvasModel } from '../canvas/CanvasModel';
import * as _ from 'lodash';
import _flatMap from 'lodash/flatMap';
import _forEach from 'lodash/forEach';
import _mapValues from 'lodash/mapValues';
import { CanvasEngine } from '../../CanvasEngine';
import { FactoryBank } from '../../core/FactoryBank';
import { AbstractModelFactory } from '../../core/AbstractModelFactory';
@@ -37,7 +39,7 @@ export abstract class LayerModel<G extends LayerModelGenerics = LayerModelGeneri
super.deserialize(event);
this.options.isSvg = !!event.data.isSvg;
this.options.transformed = !!event.data.transformed;
_.forEach(event.data.models, (model) => {
_forEach(event.data.models, (model) => {
const modelOb = this.getChildModelFactoryBank(event.engine).getFactory(model.type).generateModel({
initialConfig: model
});
@@ -54,7 +56,7 @@ export abstract class LayerModel<G extends LayerModelGenerics = LayerModelGeneri
...super.serialize(),
isSvg: this.options.isSvg,
transformed: this.options.transformed,
models: _.mapValues(this.models, (model) => {
models: _mapValues(this.models, (model) => {
return model.serialize();
})
};
@@ -81,7 +83,7 @@ export abstract class LayerModel<G extends LayerModelGenerics = LayerModelGeneri
}
getSelectionEntities(): Array<BaseModel> {
return _.flatMap(this.models, (model) => {
return _flatMap(this.models, (model) => {
return model.getSelectionEntities();
});
}

View File

@@ -3,6 +3,7 @@ import { AbstractReactFactory, GenerateWidgetEvent } from '../../core/AbstractRe
import { SelectionLayerModel } from './SelectionLayerModel';
import { GenerateModelEvent } from '../../core/AbstractModelFactory';
import { SelectionBoxWidget } from './SelectionBoxWidget';
import { JSX } from 'react';
export class SelectionBoxLayerFactory extends AbstractReactFactory<SelectionLayerModel> {
constructor() {

View File

@@ -1,3 +1,4 @@
import { CanvasEngine } from '../CanvasEngine';
import { AbstractDisplacementState, AbstractDisplacementStateEvent } from '../core-state/AbstractDisplacementState';
import { State } from '../core-state/State';
@@ -8,7 +9,7 @@ export interface DragCanvasStateOptions {
allowDrag?: boolean;
}
export class DragCanvasState extends AbstractDisplacementState {
export class DragCanvasState<E extends CanvasEngine = CanvasEngine> extends AbstractDisplacementState<E> {
// store this as we drag the canvas
initialCanvasX: number;
initialCanvasY: number;

View File

@@ -2,8 +2,9 @@ import { State } from '../core-state/State';
import { Action, ActionEvent, InputType } from '../core-actions/Action';
import { SelectionBoxState } from './SelectionBoxState';
import { MouseEvent } from 'react';
import { CanvasEngine } from '../CanvasEngine';
export class SelectingState extends State {
export class SelectingState<E extends CanvasEngine = CanvasEngine> extends State<E> {
constructor() {
super({
name: 'selecting'

View File

@@ -4,6 +4,7 @@ import { SelectionLayerModel } from '../entities/selection/SelectionLayerModel';
import { Point, Rectangle } from '@projectstorm/geometry';
import { BasePositionModel } from '../core-models/BasePositionModel';
import { ModelGeometryInterface } from '../core/ModelGeometryInterface';
import { CanvasEngine } from '../CanvasEngine';
export interface SimpleClientRect {
left: number;
@@ -14,7 +15,7 @@ export interface SimpleClientRect {
bottom: number;
}
export class SelectionBoxState extends AbstractDisplacementState {
export class SelectionBoxState<E extends CanvasEngine = CanvasEngine> extends AbstractDisplacementState<E> {
layer: SelectionLayerModel;
constructor() {

View File

@@ -1,6 +1,7 @@
import * as React from 'react';
import * as _ from 'lodash';
import _isEqual from 'lodash/isEqual';
import { BaseModel } from '../core-models/BaseModel';
import { JSX } from 'react';
export interface PeformanceWidgetProps {
children: () => JSX.Element;
@@ -25,7 +26,7 @@ export class PeformanceWidget extends React.Component<PeformanceWidgetProps, Pef
}
// change event
return !_.isEqual(this.props.serialized, nextProps.serialized);
return !_isEqual(this.props.serialized, nextProps.serialized);
}
render() {

View File

@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"outDir": "dist",
"rootDir": "src",
"declarationDir": "dist/@types",

View File

@@ -1,5 +1,25 @@
# Changelog
## 7.0.3
### Patch Changes
- 09ed60f: Allow more derived State classes to provide a generic type
- 80285fe: refactor: update lodash imports to use individual functions
- Updated dependencies [09ed60f]
- Updated dependencies [80285fe]
- @projectstorm/react-canvas-core@7.0.3
- @projectstorm/geometry@7.0.3
## 7.0.2
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
- Updated dependencies [66c687a]
- @projectstorm/react-canvas-core@7.0.2
- @projectstorm/geometry@7.0.2
## 7.0.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/react-diagrams-core",
"version": "7.0.1",
"version": "7.0.3",
"author": "dylanvorster",
"license": "MIT",
"repository": {
@@ -31,15 +31,15 @@
"module": "./dist/index.js",
"typings": "./dist/@types/index",
"dependencies": {
"@emotion/styled": "^11.10.5",
"@emotion/styled": "^11.11.0",
"@projectstorm/geometry": "workspace:*",
"@projectstorm/react-canvas-core": "workspace:*",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react": "^19.0.0",
"resize-observer-polyfill": "^1.5.1"
},
"devDependencies": {
"@types/react": "^18.0.27",
"@types/lodash": "^4.14.191"
"@types/lodash": "^4.14.200",
"@types/react": "^19.0.12"
}
}

View File

@@ -3,7 +3,7 @@ import { PortModel } from './entities/port/PortModel';
import { LinkModel } from './entities/link/LinkModel';
import { LabelModel } from './entities/label/LabelModel';
import { boundingBoxFromPolygons, Point, Rectangle } from '@projectstorm/geometry';
import { MouseEvent } from 'react';
import { JSX, MouseEvent } from 'react';
import {
AbstractModelFactory,
AbstractReactFactory,
@@ -123,9 +123,9 @@ export class DiagramEngine extends CanvasEngine<CanvasEngineListener, DiagramMod
getFactoryForLabel<F extends AbstractReactFactory<LabelModel, DiagramEngine>>(label: LabelModel) {
if (typeof label === 'string') {
return this.labelFactories.getFactory(label);
return this.labelFactories.getFactory<F>(label);
}
return this.labelFactories.getFactory(label.getType());
return this.labelFactories.getFactory<F>(label.getType());
}
getFactoryForPort<F extends AbstractModelFactory<PortModel, DiagramEngine>>(port: PortModel) {

View File

@@ -3,6 +3,7 @@ import { AbstractReactFactory, GenerateModelEvent, GenerateWidgetEvent } from '@
import { DiagramEngine } from '../../DiagramEngine';
import { LinkLayerModel } from './LinkLayerModel';
import { LinkLayerWidget } from './LinkLayerWidget';
import { JSX } from 'react';
export class LinkLayerFactory extends AbstractReactFactory<LinkLayerModel, DiagramEngine> {
constructor() {

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import styled from '@emotion/styled';
import * as _ from 'lodash';
import _map from 'lodash/map';
import { LinkWidget } from '../link/LinkWidget';
import { LinkLayerModel } from './LinkLayerModel';
import { DiagramEngine } from '../../DiagramEngine';
@@ -20,7 +20,7 @@ export class LinkLayerWidget extends React.Component<LinkLayerWidgetProps> {
<>
{
//only perform these actions when we have a diagram
_.map(this.props.layer.getLinks(), (link) => {
_map(this.props.layer.getLinks(), (link) => {
return <LinkWidget key={link.getID()} link={link} diagramEngine={this.props.engine} />;
})
}

View File

@@ -1,6 +1,8 @@
import { PortModel } from '../port/PortModel';
import { PointModel } from './PointModel';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import _map from 'lodash/map';
import _slice from 'lodash/slice';
import { LabelModel } from '../label/LabelModel';
import { DiagramEngine } from '../../DiagramEngine';
import { DiagramModel } from '../../models/DiagramModel';
@@ -56,7 +58,7 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>
getBoundingBox(): Rectangle {
return new Rectangle(
boundingBoxFromPoints(
_.map(this.points, (point: PointModel) => {
_map(this.points, (point: PointModel) => {
return point.getPosition();
})
)
@@ -65,22 +67,22 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>
getSelectionEntities(): Array<BaseModel> {
if (this.getTargetPort() && this.getSourcePort()) {
return super.getSelectionEntities().concat(_.slice(this.points, 1, this.points.length - 1));
return super.getSelectionEntities().concat(_slice(this.points, 1, this.points.length - 1));
}
// allow selection of the first point
if (!this.getSourcePort()) {
return super.getSelectionEntities().concat(_.slice(this.points, 0, this.points.length - 1));
return super.getSelectionEntities().concat(_slice(this.points, 0, this.points.length - 1));
}
// allow selection of the last point
if (!this.getTargetPort()) {
return super.getSelectionEntities().concat(_.slice(this.points, 1, this.points.length));
return super.getSelectionEntities().concat(_slice(this.points, 1, this.points.length));
}
return super.getSelectionEntities().concat(this.points);
}
deserialize(event: DeserializeEvent<this>) {
super.deserialize(event);
this.points = _.map(event.data.points || [], (point) => {
this.points = _map(event.data.points || [], (point) => {
var p = new PointModel({
link: this,
position: new Point(point.x, point.y)
@@ -93,7 +95,7 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>
});
//deserialize labels
_.forEach(event.data.labels || [], (label: any) => {
_forEach(event.data.labels || [], (label: any) => {
let labelOb = (event.engine as DiagramEngine).getFactoryForLabel(label.type).generateModel({});
labelOb.deserialize({
...event,
@@ -131,10 +133,10 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>
sourcePort: this.sourcePort ? this.sourcePort.getID() : null,
target: this.targetPort ? this.targetPort.getParent().getID() : null,
targetPort: this.targetPort ? this.targetPort.getID() : null,
points: _.map(this.points, (point) => {
points: _map(this.points, (point) => {
return point.serialize();
}),
labels: _.map(this.labels, (label) => {
labels: _map(this.labels, (label) => {
return label.serialize();
})
};
@@ -142,7 +144,7 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>
doClone(lookupTable = {}, clone) {
clone.setPoints(
_.map(this.getPoints(), (point: PointModel) => {
_map(this.getPoints(), (point: PointModel) => {
return point.clone(lookupTable);
})
);
@@ -274,7 +276,7 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>
}
setPoints(points: PointModel[]) {
_.forEach(points, (point) => {
_forEach(points, (point) => {
point.setParent(this);
});
this.points = points;

View File

@@ -2,7 +2,7 @@ import * as React from 'react';
import { DiagramEngine } from '../../DiagramEngine';
import { LinkModel } from './LinkModel';
import { PointModel } from './PointModel';
import * as _ from 'lodash';
import _map from 'lodash/map';
import { LabelWidget } from '../label/LabelWidget';
import { BaseEntityEvent, BasePositionModel, ListenerHandle, PeformanceWidget } from '@projectstorm/react-canvas-core';
import { PortModel } from '../port/PortModel';
@@ -107,7 +107,7 @@ export class LinkWidget extends React.Component<LinkProps, LinkState> {
return (
<g data-linkid={this.props.link.getID()}>
{this.props.diagramEngine.generateWidgetForLink(link)}
{_.map(this.props.link.getLabels(), (labelModel, index) => {
{_map(this.props.link.getLabels(), (labelModel, index) => {
return (
<LabelWidget
key={labelModel.getID()}

View File

@@ -3,6 +3,7 @@ import { AbstractReactFactory, GenerateModelEvent, GenerateWidgetEvent } from '@
import { DiagramEngine } from '../../DiagramEngine';
import { NodeLayerModel } from './NodeLayerModel';
import { NodeLayerWidget } from './NodeLayerWidget';
import { JSX } from 'react';
export class NodeLayerFactory extends AbstractReactFactory<NodeLayerModel, DiagramEngine> {
constructor() {

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import * as _ from 'lodash';
import _map from 'lodash/map';
import { NodeModel } from '../node/NodeModel';
import { NodeWidget } from '../node/NodeWidget';
import { NodeLayerModel } from './NodeLayerModel';
@@ -14,7 +14,7 @@ export class NodeLayerWidget extends React.Component<NodeLayerWidgetProps> {
render() {
return (
<>
{_.map(this.props.layer.getNodes(), (node: NodeModel) => {
{_map(this.props.layer.getNodes(), (node: NodeModel) => {
return <NodeWidget key={node.getID()} diagramEngine={this.props.engine} node={node} />;
})}
</>

View File

@@ -1,4 +1,6 @@
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import _map from 'lodash/map';
import _values from 'lodash/values';
import { DiagramModel } from '../../models/DiagramModel';
import { PortModel } from '../port/PortModel';
import { LinkModel } from '../link/LinkModel';
@@ -51,7 +53,7 @@ export class NodeModel<G extends NodeModelGenerics = NodeModelGenerics> extends
}
//also update the port co-ordinates (for make glorious speed)
_.forEach(this.ports, (port) => {
_forEach(this.ports, (port) => {
port.setPosition(port.getX() + this.position.x - old.x, port.getY() + this.position.y - old.y);
});
}
@@ -60,7 +62,7 @@ export class NodeModel<G extends NodeModelGenerics = NodeModelGenerics> extends
super.deserialize(event);
//deserialize ports
_.forEach(event.data.ports, (port: any) => {
_forEach(event.data.ports, (port: any) => {
let portOb = (event.engine as DiagramEngine).getFactoryForPort(port.type).generateModel({});
portOb.deserialize({
...event,
@@ -75,7 +77,7 @@ export class NodeModel<G extends NodeModelGenerics = NodeModelGenerics> extends
serialize() {
return {
...super.serialize(),
ports: _.map(this.ports, (port) => {
ports: _map(this.ports, (port) => {
return port.serialize();
})
};
@@ -84,15 +86,15 @@ export class NodeModel<G extends NodeModelGenerics = NodeModelGenerics> extends
doClone(lookupTable = {}, clone) {
// also clone the ports
clone.ports = {};
_.forEach(this.ports, (port) => {
_forEach(this.ports, (port) => {
clone.addPort(port.clone(lookupTable));
});
}
remove() {
super.remove();
_.forEach(this.ports, (port) => {
_.forEach(port.getLinks(), (link) => {
_forEach(this.ports, (port) => {
_forEach(port.getLinks(), (link) => {
link.remove();
});
});
@@ -126,7 +128,7 @@ export class NodeModel<G extends NodeModelGenerics = NodeModelGenerics> extends
removePort(port: PortModel) {
// clear the port from the links
for (let link of _.values(port.getLinks())) {
for (let link of _values(port.getLinks())) {
link.clearPort(port);
}
//clear the parent node reference

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import { DiagramEngine } from '../../DiagramEngine';
import { NodeModel } from './NodeModel';
import { BaseEntityEvent, BaseModel, ListenerHandle, PeformanceWidget } from '@projectstorm/react-canvas-core';
@@ -61,7 +61,7 @@ export class NodeWidget extends React.Component<NodeProps> {
//now mark the links as dirty
try {
_.forEach(this.props.node.getPorts(), (port) => {
_forEach(this.props.node.getPorts(), (port) => {
port.updateCoords(this.props.diagramEngine.getPortCoords(port));
});
} catch (ex) {}

View File

@@ -1,6 +1,10 @@
import { NodeModel } from '../node/NodeModel';
import { LinkModel } from '../link/LinkModel';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import _isFinite from 'lodash/isFinite';
import _map from 'lodash/map';
import _size from 'lodash/size';
import _values from 'lodash/values';
import { Point, Rectangle } from '@projectstorm/geometry';
import {
BaseEntityEvent,
@@ -64,7 +68,7 @@ export class PortModel<G extends PortModelGenerics = PortModelGenerics> extends
name: this.options.name,
alignment: this.options.alignment,
parentNode: this.parent.getID(),
links: _.map(this.links, (link) => {
links: _map(this.links, (link) => {
return link.getID();
})
};
@@ -75,7 +79,7 @@ export class PortModel<G extends PortModelGenerics = PortModelGenerics> extends
setPosition(x, y?) {
let old = this.position;
super.setPosition(x, y);
_.forEach(this.getLinks(), (link) => {
_forEach(this.getLinks(), (link) => {
let point = link.getPointForPort(this);
point.setPosition(point.getX() + x - old.x, point.getY() + y - old.y);
});
@@ -115,10 +119,10 @@ export class PortModel<G extends PortModelGenerics = PortModelGenerics> extends
}
public createLinkModel(): LinkModel | null {
if (_.isFinite(this.options.maximumLinks)) {
var numberOfLinks: number = _.size(this.links);
if (_isFinite(this.options.maximumLinks)) {
var numberOfLinks: number = _size(this.links);
if (this.options.maximumLinks === 1 && numberOfLinks >= 1) {
return _.values(this.links)[0];
return _values(this.links)[0];
} else if (numberOfLinks >= this.options.maximumLinks) {
return null;
}
@@ -127,7 +131,7 @@ export class PortModel<G extends PortModelGenerics = PortModelGenerics> extends
}
reportPosition() {
_.forEach(this.getLinks(), (link) => {
_forEach(this.getLinks(), (link) => {
link.getPointForPort(this).setPosition(this.getCenter());
});
this.fireEvent(

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import * as _ from 'lodash';
import _keys from 'lodash/keys';
import { PortModel } from './PortModel';
import { DiagramEngine } from '../../DiagramEngine';
import { ListenerHandle, Toolkit } from '@projectstorm/react-canvas-core';
@@ -47,7 +47,7 @@ export class PortWidget extends React.Component<React.PropsWithChildren<PortProp
getExtraProps() {
if (Toolkit.TESTING) {
const links = _.keys(this.props.port.getNode().getPort(this.props.port.getName()).links).join(',');
const links = _keys(this.props.port.getNode().getPort(this.props.port.getName()).links).join(',');
return {
'data-links': links
};

View File

@@ -1,4 +1,8 @@
import * as _ from 'lodash';
import _filter from 'lodash/filter';
import _flatMap from 'lodash/flatMap';
import _forEach from 'lodash/forEach';
import _some from 'lodash/some';
import _values from 'lodash/values';
import { LinkModel } from '../entities/link/LinkModel';
import { NodeModel } from '../entities/node/NodeModel';
import {
@@ -49,13 +53,13 @@ export class DiagramModel<G extends DiagramModelGenerics = DiagramModelGenerics>
}
getLinkLayers(): LinkLayerModel[] {
return _.filter(this.layers, (layer) => {
return _filter(this.layers, (layer) => {
return layer instanceof LinkLayerModel;
}) as LinkLayerModel[];
}
getNodeLayers(): NodeLayerModel[] {
return _.filter(this.layers, (layer) => {
return _filter(this.layers, (layer) => {
return layer instanceof NodeLayerModel;
}) as NodeLayerModel[];
}
@@ -103,7 +107,7 @@ export class DiagramModel<G extends DiagramModelGenerics = DiagramModelGenerics>
}
addAll(...models: BaseModel[]): BaseModel[] {
_.forEach(models, (model) => {
_forEach(models, (model) => {
if (model instanceof LinkModel) {
this.addLink(model);
} else if (model instanceof NodeModel) {
@@ -132,7 +136,7 @@ export class DiagramModel<G extends DiagramModelGenerics = DiagramModelGenerics>
}
removeLink(link: LinkModel) {
const removed = _.some(this.getLinkLayers(), (layer) => {
const removed = _some(this.getLinkLayers(), (layer) => {
return layer.removeModel(link);
});
if (removed) {
@@ -141,7 +145,7 @@ export class DiagramModel<G extends DiagramModelGenerics = DiagramModelGenerics>
}
removeNode(node: NodeModel) {
const removed = _.some(this.getNodeLayers(), (layer) => {
const removed = _some(this.getNodeLayers(), (layer) => {
return layer.removeModel(node);
});
if (removed) {
@@ -150,14 +154,14 @@ export class DiagramModel<G extends DiagramModelGenerics = DiagramModelGenerics>
}
getLinks(): LinkModel[] {
return _.flatMap(this.getLinkLayers(), (layer) => {
return _.values(layer.getModels());
return _flatMap(this.getLinkLayers(), (layer) => {
return _values(layer.getModels());
});
}
getNodes(): NodeModel[] {
return _.flatMap(this.getNodeLayers(), (layer) => {
return _.values(layer.getModels());
return _flatMap(this.getNodeLayers(), (layer) => {
return _values(layer.getModels());
});
}
}

View File

@@ -1,12 +1,12 @@
import { Action, ActionEvent, InputType, MoveItemsState } from '@projectstorm/react-canvas-core';
import * as _ from 'lodash';
import _forEach from 'lodash/forEach';
import { PointModel } from '../entities/link/PointModel';
import { DiagramEngine } from '../DiagramEngine';
import { PortModel } from '../entities/port/PortModel';
import { MouseEvent } from 'react';
import { LinkModel } from '../entities/link/LinkModel';
export class DragDiagramItemsState extends MoveItemsState<DiagramEngine> {
export class DragDiagramItemsState<E extends DiagramEngine = DiagramEngine> extends MoveItemsState<E> {
constructor() {
super();
this.registerAction(
@@ -15,7 +15,7 @@ export class DragDiagramItemsState extends MoveItemsState<DiagramEngine> {
fire: (event: ActionEvent<MouseEvent>) => {
const item = this.engine.getMouseElement(event.event);
if (item instanceof PortModel) {
_.forEach(this.initialPositions, (position) => {
_forEach(this.initialPositions, (position) => {
if (position.item instanceof PointModel) {
const link = position.item.getParent() as LinkModel;

View File

@@ -22,7 +22,7 @@ export interface DragNewLinkStateOptions {
allowLinksFromLockedPorts?: boolean;
}
export class DragNewLinkState extends AbstractDisplacementState<DiagramEngine> {
export class DragNewLinkState<E extends DiagramEngine = DiagramEngine> extends AbstractDisplacementState<E> {
port: PortModel;
link: LinkModel;
config: DragNewLinkStateOptions;

View File

@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"outDir": "dist",
"rootDir": "src",
"declarationDir": "dist/@types",

View File

@@ -1,5 +1,27 @@
# @projectstorm/react-diagrams-defaults
## 7.1.3
### Patch Changes
- 20766f5: fix default link widget with react strict mode
- 80285fe: refactor: update lodash imports to use individual functions
- Updated dependencies [09ed60f]
- Updated dependencies [80285fe]
- @projectstorm/react-canvas-core@7.0.3
- @projectstorm/react-diagrams-core@7.0.3
- @projectstorm/geometry@7.0.3
## 7.1.2
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
- Updated dependencies [66c687a]
- @projectstorm/react-diagrams-core@7.0.2
- @projectstorm/react-canvas-core@7.0.2
- @projectstorm/geometry@7.0.2
## 7.1.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/react-diagrams-defaults",
"version": "7.1.1",
"version": "7.1.3",
"author": "dylanvorster",
"license": "MIT",
"repository": {
@@ -29,16 +29,16 @@
"module": "./dist/index.js",
"typings": "./dist/@types/index",
"dependencies": {
"@emotion/react": "^11.10.5",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.*",
"@projectstorm/geometry": "workspace:*",
"@projectstorm/react-canvas-core": "workspace:*",
"@projectstorm/react-diagrams-core": "workspace:*",
"lodash": "^4.17.21",
"react": "^18.2.0"
"react": "^19.0.0"
},
"devDependencies": {
"@types/lodash": "^4.14.191",
"@types/react": "^18.0.27"
"@types/lodash": "^4.14.200",
"@types/react": "^19.0.12"
}
}

View File

@@ -3,6 +3,7 @@ import { DefaultLabelModel } from './DefaultLabelModel';
import { DefaultLabelWidget } from './DefaultLabelWidget';
import { AbstractReactFactory } from '@projectstorm/react-canvas-core';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { JSX } from 'react';
/**
* @author Dylan Vorster

View File

@@ -5,6 +5,7 @@ import styled from '@emotion/styled';
import { AbstractReactFactory } from '@projectstorm/react-canvas-core';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { css, keyframes } from '@emotion/react';
import { JSX } from 'react';
namespace S {
export const Keyframes = keyframes`

View File

@@ -7,7 +7,7 @@ export interface DefaultLinkSegmentWidgetProps {
path: string;
link: DefaultLinkModel;
selected: boolean;
forwardRef: React.RefObject<SVGPathElement>;
forwardRef: React.RefObject<SVGPathElement | null>;
factory: DefaultLinkFactory;
diagramEngine: DiagramEngine;
onSelection: (selected: boolean) => any;

View File

@@ -1,9 +1,9 @@
import * as React from 'react';
import { DiagramEngine, LinkWidget, PointModel } from '@projectstorm/react-diagrams-core';
import * as React from 'react';
import { JSX, MouseEvent, useEffect, useRef } from 'react';
import { DefaultLinkModel } from './DefaultLinkModel';
import { DefaultLinkPointWidget } from './DefaultLinkPointWidget';
import { DefaultLinkSegmentWidget } from './DefaultLinkSegmentWidget';
import { MouseEvent } from 'react';
export interface DefaultLinkProps {
link: DefaultLinkModel;
@@ -13,150 +13,120 @@ export interface DefaultLinkProps {
selected?: (event: MouseEvent) => any;
}
export interface DefaultLinkState {
selected: boolean;
}
export const DefaultLinkWidget: React.FC<DefaultLinkProps> = (props) => {
const [selected, setSelected] = React.useState(false);
const refPaths = useRef<React.RefObject<SVGPathElement>[]>([]);
export class DefaultLinkWidget extends React.Component<DefaultLinkProps, DefaultLinkState> {
refPaths: React.RefObject<SVGPathElement>[];
const renderPoints = () => {
return props.renderPoints ?? true;
};
constructor(props: DefaultLinkProps) {
super(props);
this.refPaths = [];
this.state = {
selected: false
useEffect(() => {
props.link.setRenderedPaths(refPaths.current.map((ref) => ref.current).filter(Boolean) as SVGPathElement[]);
return () => {
props.link.setRenderedPaths([]);
};
}
}, [props.link]);
renderPoints() {
return this.props.renderPoints ?? true;
}
const generateRef = () => {
const ref = React.createRef<SVGPathElement>();
refPaths.current.push(ref);
return ref;
};
componentDidUpdate(): void {
this.props.link.setRenderedPaths(
this.refPaths.map((ref) => {
return ref.current;
})
);
}
componentDidMount(): void {
this.props.link.setRenderedPaths(
this.refPaths.map((ref) => {
return ref.current;
})
);
}
componentWillUnmount(): void {
this.props.link.setRenderedPaths([]);
}
addPointToLink(event: MouseEvent, index: number) {
const addPointToLink = (event: MouseEvent, index: number) => {
if (
!event.shiftKey &&
!this.props.link.isLocked() &&
this.props.link.getPoints().length - 1 <= this.props.diagramEngine.getMaxNumberPointsPerLink()
!props.link.isLocked() &&
props.link.getPoints().length - 1 <= props.diagramEngine.getMaxNumberPointsPerLink()
) {
const position = this.props.diagramEngine.getRelativeMousePoint(event);
const point = this.props.link.point(position.x, position.y, index);
const position = props.diagramEngine.getRelativeMousePoint(event);
const point = props.link.point(position.x, position.y, index);
event.persist();
event.stopPropagation();
this.forceUpdate(() => {
this.props.diagramEngine.getActionEventBus().fireAction({
event,
model: point
});
props.diagramEngine.getActionEventBus().fireAction({
event,
model: point
});
}
}
};
generatePoint(point: PointModel): JSX.Element {
const generatePoint = (point: PointModel): JSX.Element => {
return (
<DefaultLinkPointWidget
key={point.getID()}
point={point as any}
colorSelected={this.props.link.getOptions().selectedColor}
color={this.props.link.getOptions().color}
colorSelected={props.link.getOptions().selectedColor ?? ''}
color={props.link.getOptions().color}
/>
);
}
};
generateLink(path: string, extraProps: any, id: string | number): JSX.Element {
const ref = React.createRef<SVGPathElement>();
this.refPaths.push(ref);
const generateLink = (path: string, extraProps: any, id: string | number): JSX.Element => {
return (
<DefaultLinkSegmentWidget
key={`link-${id}`}
path={path}
selected={this.state.selected}
diagramEngine={this.props.diagramEngine}
factory={this.props.diagramEngine.getFactoryForLink(this.props.link)}
link={this.props.link}
forwardRef={ref}
onSelection={(selected) => {
this.setState({ selected: selected });
}}
selected={selected}
diagramEngine={props.diagramEngine}
factory={props.diagramEngine.getFactoryForLink(props.link)}
link={props.link}
forwardRef={generateRef()}
onSelection={setSelected}
extras={extraProps}
/>
);
}
};
render() {
//ensure id is present for all points on the path
var points = this.props.link.getPoints();
var paths = [];
this.refPaths = [];
const points = props.link.getPoints();
const paths = [];
refPaths.current = []; // Reset the refPaths for the current render
if (points.length === 2) {
if (points.length === 2) {
paths.push(
generateLink(
props.link.getSVGPath(),
{
onMouseDown: (event: MouseEvent) => {
props.selected?.(event);
addPointToLink(event, 1);
}
},
'0'
)
);
if (props.link.getTargetPort() == null) {
paths.push(generatePoint(points[1]));
}
} else {
for (let j = 0; j < points.length - 1; j++) {
paths.push(
this.generateLink(
this.props.link.getSVGPath(),
generateLink(
LinkWidget.generateLinePath(points[j], points[j + 1]),
{
onMouseDown: (event) => {
this.props.selected?.(event);
this.addPointToLink(event, 1);
'data-linkid': props.link.getID(),
'data-point': j,
onMouseDown: (event: MouseEvent) => {
props.selected?.(event);
addPointToLink(event, j + 1);
}
},
'0'
j
)
);
// draw the link as dangeling
if (this.props.link.getTargetPort() == null) {
paths.push(this.generatePoint(points[1]));
}
} else {
//draw the multiple anchors and complex line instead
for (let j = 0; j < points.length - 1; j++) {
paths.push(
this.generateLink(
LinkWidget.generateLinePath(points[j], points[j + 1]),
{
'data-linkid': this.props.link.getID(),
'data-point': j,
onMouseDown: (event: MouseEvent) => {
this.props.selected?.(event);
this.addPointToLink(event, j + 1);
}
},
j
)
);
}
if (this.renderPoints()) {
//render the circles
for (let i = 1; i < points.length - 1; i++) {
paths.push(this.generatePoint(points[i]));
}
if (this.props.link.getTargetPort() == null) {
paths.push(this.generatePoint(points[points.length - 1]));
}
}
}
return <g data-default-link-test={this.props.link.getOptions().testName}>{paths}</g>;
if (renderPoints()) {
for (let i = 1; i < points.length - 1; i++) {
paths.push(generatePoint(points[i]));
}
if (props.link.getTargetPort() == null) {
paths.push(generatePoint(points[points.length - 1]));
}
}
}
}
return <g data-default-link-test={props.link.getOptions().testName}>{paths}</g>;
};

View File

@@ -3,6 +3,7 @@ import { DefaultNodeModel } from './DefaultNodeModel';
import { DefaultNodeWidget } from './DefaultNodeWidget';
import { AbstractReactFactory } from '@projectstorm/react-canvas-core';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { JSX } from 'react';
export class DefaultNodeFactory extends AbstractReactFactory<DefaultNodeModel, DiagramEngine> {
constructor() {

View File

@@ -1,4 +1,4 @@
import * as _ from 'lodash';
import _map from 'lodash/map';
import { NodeModel, NodeModelGenerics, PortModelAlignment } from '@projectstorm/react-diagrams-core';
import { DefaultPortModel } from '../port/DefaultPortModel';
import { BasePositionModelOptions, DeserializeEvent } from '@projectstorm/react-canvas-core';
@@ -94,10 +94,10 @@ export class DefaultNodeModel extends NodeModel<DefaultNodeModelGenerics> {
super.deserialize(event);
this.options.name = event.data.name;
this.options.color = event.data.color;
this.portsIn = _.map(event.data.portsInOrder, (id) => {
this.portsIn = _map(event.data.portsInOrder, (id) => {
return this.getPortFromID(id);
}) as DefaultPortModel[];
this.portsOut = _.map(event.data.portsOutOrder, (id) => {
this.portsOut = _map(event.data.portsOutOrder, (id) => {
return this.getPortFromID(id);
}) as DefaultPortModel[];
}
@@ -107,10 +107,10 @@ export class DefaultNodeModel extends NodeModel<DefaultNodeModelGenerics> {
...super.serialize(),
name: this.options.name,
color: this.options.color,
portsInOrder: _.map(this.portsIn, (port) => {
portsInOrder: _map(this.portsIn, (port) => {
return port.getID();
}),
portsOutOrder: _.map(this.portsOut, (port) => {
portsOutOrder: _map(this.portsOut, (port) => {
return port.getID();
})
};

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import * as _ from 'lodash';
import _map from 'lodash/map';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { DefaultNodeModel } from './DefaultNodeModel';
import { DefaultPortLabel } from '../port/DefaultPortLabelWidget';
@@ -74,8 +74,8 @@ export class DefaultNodeWidget extends React.Component<DefaultNodeProps> {
<S.TitleName>{this.props.node.getOptions().name}</S.TitleName>
</S.Title>
<S.Ports>
<S.PortsContainer>{_.map(this.props.node.getInPorts(), this.generatePort)}</S.PortsContainer>
<S.PortsContainer>{_.map(this.props.node.getOutPorts(), this.generatePort)}</S.PortsContainer>
<S.PortsContainer>{_map(this.props.node.getInPorts(), this.generatePort)}</S.PortsContainer>
<S.PortsContainer>{_map(this.props.node.getOutPorts(), this.generatePort)}</S.PortsContainer>
</S.Ports>
</S.Node>
);

View File

@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"outDir": "dist",
"rootDir": "src",
"declarationDir": "dist/@types",

View File

@@ -1,5 +1,29 @@
# @projectstorm/react-diagrams-routing
## 7.1.3
### Patch Changes
- 80285fe: refactor: update lodash imports to use individual functions
- Updated dependencies [09ed60f]
- Updated dependencies [20766f5]
- Updated dependencies [80285fe]
- @projectstorm/react-canvas-core@7.0.3
- @projectstorm/react-diagrams-core@7.0.3
- @projectstorm/react-diagrams-defaults@7.1.3
- @projectstorm/geometry@7.0.3
## 7.1.2
### Patch Changes
- 66c687a: Upgrade all dependencies and fix Storybook after upgrade
- Updated dependencies [66c687a]
- @projectstorm/react-diagrams-defaults@7.1.2
- @projectstorm/react-diagrams-core@7.0.2
- @projectstorm/react-canvas-core@7.0.2
- @projectstorm/geometry@7.0.2
## 7.1.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/react-diagrams-routing",
"version": "7.1.1",
"version": "7.1.3",
"author": "dylanvorster",
"license": "MIT",
"repository": {
@@ -38,11 +38,11 @@
"lodash": "^4.17.21",
"pathfinding": "^0.4.18",
"paths-js": "^0.4.11",
"react": "^18.2.0"
"react": "^19.0.0"
},
"devDependencies": {
"@types/dagre": "^0.7.48",
"@types/lodash": "^4.14.191",
"@types/react": "^18.0.27"
"@types/dagre": "^0.7.50",
"@types/lodash": "^4.14.200",
"@types/react": "^19.0.12"
}
}

View File

@@ -1,7 +1,12 @@
import { DiagramModel, PointModel } from '@projectstorm/react-diagrams-core';
import * as dagre from 'dagre';
import { GraphLabel } from 'dagre';
import * as _ from 'lodash';
import _every from 'lodash/every';
import _findIndex from 'lodash/findIndex';
import _forEach from 'lodash/forEach';
import _map from 'lodash/map';
import _range from 'lodash/range';
import _sortBy from 'lodash/sortBy';
import { Point } from '@projectstorm/geometry';
export interface DagreEngineOptions {
@@ -32,11 +37,11 @@ export class DagreEngine {
});
// set nodes
_.forEach(model.getNodes(), (node) => {
_forEach(model.getNodes(), (node) => {
g.setNode(node.getID(), { width: node.width, height: node.height });
});
_.forEach(model.getLinks(), (link) => {
_forEach(model.getLinks(), (link) => {
// set edges
if (link.getSourcePort() && link.getTargetPort()) {
g.setEdge({
@@ -82,11 +87,11 @@ export class DagreEngine {
const chunks: { [id: number]: { [id: number]: boolean } } = {}; // true: occupied, false: blank
const NodeXColumnIndexDictionary: { [id: number]: number } = {};
let verticalLines: number[] = [];
_.forEach(nodes, (node) => {
_forEach(nodes, (node) => {
// find vertical lines. vertical lines go through maximum number of nodes located under each other.
const nodeColumnCenter = node.getX() + node.width / 2;
if (
_.every(verticalLines, (vLine) => {
_every(verticalLines, (vLine) => {
return Math.abs(nodeColumnCenter - vLine) > nodeMargin;
})
) {
@@ -96,29 +101,29 @@ export class DagreEngine {
// sort chunk columns
verticalLines = verticalLines.sort((a, b) => a - b);
_.forEach(verticalLines, (line, index) => {
_forEach(verticalLines, (line, index) => {
chunks[index] = {};
chunks[index + 0.5] = {};
});
// set occupied chunks
_.forEach(nodes, (node) => {
_forEach(nodes, (node) => {
const nodeColumnCenter = node.getX() + node.width / 2;
const startChunkIndex = Math.floor(node.getY() / nodeMargin);
const endChunkIndex = Math.floor((node.getY() + node.height) / nodeMargin);
// find max ChunkRowIndex
if (endChunkIndex > maxChunkRowIndex) maxChunkRowIndex = endChunkIndex;
const nodeColumnIndex = _.findIndex(verticalLines, (vLine) => {
const nodeColumnIndex = _findIndex(verticalLines, (vLine) => {
return Math.abs(nodeColumnCenter - vLine) <= nodeMargin;
});
_.forEach(_.range(startChunkIndex, endChunkIndex + 1), (chunkIndex) => {
_forEach(_range(startChunkIndex, endChunkIndex + 1), (chunkIndex) => {
chunks[nodeColumnIndex][chunkIndex] = true;
});
NodeXColumnIndexDictionary[node.getX()] = nodeColumnIndex;
});
// sort links based on their distances
const edges = _.map(links, (link) => {
const edges = _map(links, (link) => {
if (link.getSourcePort() && link.getTargetPort()) {
const source = link.getSourcePort().getNode();
const target = link.getTargetPort().getNode();
@@ -146,18 +151,18 @@ export class DagreEngine {
};
}
});
const sortedEdges = _.sortBy(edges, (link) => {
const sortedEdges = _sortBy(edges, (link) => {
return Math.abs(link.targetIndex - link.sourceIndex);
});
// set link points
if (this.options.includeLinks) {
_.forEach(sortedEdges, (edge) => {
_forEach(sortedEdges, (edge) => {
const link = diagram.getLink(edge.link.getID());
// re-draw
if (Math.abs(edge.sourceIndex - edge.targetIndex) > 1) {
// get the length of link in column
const columns = _.range(edge.sourceIndex - 1, edge.targetIndex);
const columns = _range(edge.sourceIndex - 1, edge.targetIndex);
const chunkIndex = Math.floor(edge.sourceY / nodeMargin);
const targetChunkIndex = Math.floor(edge.targetY / nodeMargin);
@@ -167,7 +172,7 @@ export class DagreEngine {
let aboveRowIndex = chunkIndex;
for (; aboveRowIndex >= 0; aboveRowIndex--, northCost++) {
if (
_.every(columns, (columnIndex) => {
_every(columns, (columnIndex) => {
return !(
chunks[columnIndex][aboveRowIndex] ||
chunks[columnIndex + 0.5][aboveRowIndex] ||
@@ -184,7 +189,7 @@ export class DagreEngine {
let belowRowIndex = chunkIndex;
for (; belowRowIndex <= maxChunkRowIndex; belowRowIndex++, southCost++) {
if (
_.every(columns, (columnIndex) => {
_every(columns, (columnIndex) => {
return !(
chunks[columnIndex][belowRowIndex] ||
chunks[columnIndex + 0.5][belowRowIndex] ||
@@ -213,7 +218,7 @@ export class DagreEngine {
})
);
_.forEach(columns, (column) => {
_forEach(columns, (column) => {
points.push(
new PointModel({
link: link,

View File

@@ -2,7 +2,16 @@ import * as React from 'react';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { PathFindingLinkModel } from './PathFindingLinkModel';
import { PathFindingLinkWidget } from './PathFindingLinkWidget';
import * as _ from 'lodash';
import _cloneDeep from 'lodash/cloneDeep';
import _concat from 'lodash/concat';
import _defer from 'lodash/defer';
import _flatMap from 'lodash/flatMap';
import _get from 'lodash/get';
import _minBy from 'lodash/minBy';
import _maxBy from 'lodash/maxBy';
import _range from 'lodash/range';
import _reduce from 'lodash/reduce';
import _values from 'lodash/values';
import * as Path from 'paths-js/path';
import { DefaultLinkFactory } from '@projectstorm/react-diagrams-defaults';
import {
@@ -13,6 +22,7 @@ import {
InputType,
ListenerHandle
} from '@projectstorm/react-canvas-core';
import { JSX } from 'react';
export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkModel> {
ROUTING_SCALING_FACTOR: number = 5;
@@ -54,7 +64,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
});
this.listener = engine.registerListener({
canvasReady: () => {
_.defer(() => {
_defer(() => {
this.calculateRoutingMatrix();
engine.repaintCanvas();
});
@@ -112,7 +122,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
const matrixWidth = Math.ceil(canvasWidth / this.ROUTING_SCALING_FACTOR);
const matrixHeight = Math.ceil(canvasHeight / this.ROUTING_SCALING_FACTOR);
this.canvasMatrix = _.range(0, matrixHeight).map(() => {
this.canvasMatrix = _range(0, matrixHeight).map(() => {
return new Array(matrixWidth).fill(0);
});
}
@@ -139,7 +149,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
return this.routingMatrix;
}
calculateRoutingMatrix(): void {
const matrix = _.cloneDeep(this.getCanvasMatrix());
const matrix = _cloneDeep(this.getCanvasMatrix());
// nodes need to be marked as blocked points
this.markNodes(matrix);
@@ -171,15 +181,15 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
height: number;
vAdjustmentFactor: number;
} => {
const allNodesCoords = _.values(this.engine.getModel().getNodes()).map((item) => ({
const allNodesCoords = _values(this.engine.getModel().getNodes()).map((item) => ({
x: item.getX(),
width: item.width,
y: item.getY(),
height: item.height
}));
const allLinks = _.values(this.engine.getModel().getLinks());
const allPortsCoords = _.flatMap(allLinks.map((link) => [link.getSourcePort(), link.getTargetPort()]))
const allLinks = _values(this.engine.getModel().getLinks());
const allPortsCoords = _flatMap(allLinks.map((link) => [link.getSourcePort(), link.getTargetPort()]))
.filter((port) => port !== null)
.map((item) => ({
x: item.getX(),
@@ -187,7 +197,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
y: item.getY(),
height: item.height
}));
const allPointsCoords = _.flatMap(allLinks.map((link) => link.getPoints())).map((item) => ({
const allPointsCoords = _flatMap(allLinks.map((link) => link.getPoints())).map((item) => ({
// points don't have width/height, so let's just use 0
x: item.getX(),
width: 0,
@@ -195,19 +205,19 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
height: 0
}));
const sumProps = (object, props) => _.reduce(props, (acc, prop) => acc + _.get(object, prop, 0), 0);
const sumProps = (object, props) => _reduce(props, (acc, prop) => acc + _get(object, prop, 0), 0);
const canvas = this.engine.getCanvas() as HTMLDivElement;
const concatedCoords = _.concat(allNodesCoords, allPortsCoords, allPointsCoords);
const concatedCoords = _concat(allNodesCoords, allPortsCoords, allPointsCoords);
const minX =
Math.floor(Math.min(_.get(_.minBy(concatedCoords, 'x'), 'x', 0), 0) / this.ROUTING_SCALING_FACTOR) *
Math.floor(Math.min(_get(_minBy(concatedCoords, 'x'), 'x', 0), 0) / this.ROUTING_SCALING_FACTOR) *
this.ROUTING_SCALING_FACTOR;
const maxXElement = _.maxBy(concatedCoords, (item) => sumProps(item, ['x', 'width']));
const maxXElement = _maxBy(concatedCoords, (item) => sumProps(item, ['x', 'width']));
const maxX = Math.max(sumProps(maxXElement, ['x', 'width']), canvas.offsetWidth);
const minYCoords = _.minBy(concatedCoords, 'y');
const minYCoords = _minBy(concatedCoords, 'y');
const minY =
Math.floor(Math.min(_.get(minYCoords, 'y', 0), 0) / this.ROUTING_SCALING_FACTOR) * this.ROUTING_SCALING_FACTOR;
const maxYElement = _.maxBy(concatedCoords, (item) => sumProps(item, ['y', 'height']));
Math.floor(Math.min(_get(minYCoords, 'y', 0), 0) / this.ROUTING_SCALING_FACTOR) * this.ROUTING_SCALING_FACTOR;
const maxYElement = _maxBy(concatedCoords, (item) => sumProps(item, ['y', 'height']));
const maxY = Math.max(sumProps(maxYElement, ['y', 'height']), canvas.offsetHeight);
return {
@@ -222,7 +232,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
* Updates (by reference) where nodes will be drawn on the matrix passed in.
*/
markNodes = (matrix: number[][]): void => {
_.values(this.engine.getModel().getNodes()).forEach((node) => {
_values(this.engine.getModel().getNodes()).forEach((node) => {
const startX = Math.floor(node.getX() / this.ROUTING_SCALING_FACTOR);
const endX = Math.ceil((node.getX() + node.width) / this.ROUTING_SCALING_FACTOR);
const startY = Math.floor(node.getY() / this.ROUTING_SCALING_FACTOR);
@@ -240,8 +250,8 @@ export class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkMo
* Updates (by reference) where ports will be drawn on the matrix passed in.
*/
markPorts = (matrix: number[][]): void => {
const allElements = _.flatMap(
_.values(this.engine.getModel().getLinks()).map((link) => [].concat(link.getSourcePort(), link.getTargetPort()))
const allElements = _flatMap(
_values(this.engine.getModel().getLinks()).map((link) => [].concat(link.getSourcePort(), link.getTargetPort()))
);
allElements
.filter((port) => port !== null)

View File

@@ -1,10 +1,12 @@
import * as React from 'react';
import * as _ from 'lodash';
import _first from 'lodash/first';
import _last from 'lodash/last';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
import { PathFinding } from '../engine/PathFinding';
import { PathFindingLinkFactory } from './PathFindingLinkFactory';
import { PathFindingLinkModel } from './PathFindingLinkModel';
import { DefaultLinkSegmentWidget } from '@projectstorm/react-diagrams-defaults';
import { JSX } from 'react';
export interface PathFindingLinkWidgetProps {
color?: string;
@@ -79,7 +81,7 @@ export class PathFindingLinkWidget extends React.Component<PathFindingLinkWidget
var paths = [];
// first step: calculate a direct path between the points being linked
const directPathCoords = this.pathFinding.calculateDirectPath(_.first(points), _.last(points));
const directPathCoords = this.pathFinding.calculateDirectPath(_first(points), _last(points));
const routingMatrix = this.props.factory.getRoutingMatrix();
// now we need to extract, from the routing matrix, the very first walkable points

View File

@@ -2,6 +2,7 @@ import * as React from 'react';
import { RightAngleLinkWidget } from './RightAngleLinkWidget';
import { DefaultLinkFactory } from '@projectstorm/react-diagrams-defaults';
import { RightAngleLinkModel } from './RightAngleLinkModel';
import { JSX } from 'react';
/**
* @author Daniel Lazar

View File

@@ -3,7 +3,7 @@ import { DiagramEngine, LinkWidget, PointModel } from '@projectstorm/react-diagr
import { RightAngleLinkFactory } from './RightAngleLinkFactory';
import { DefaultLinkModel, DefaultLinkSegmentWidget } from '@projectstorm/react-diagrams-defaults';
import { Point } from '@projectstorm/geometry';
import { MouseEvent } from 'react';
import { JSX, MouseEvent } from 'react';
import { RightAngleLinkModel } from './RightAngleLinkModel';
export interface RightAngleLinkProps {
@@ -188,6 +188,7 @@ export class RightAngleLinkWidget extends React.Component<RightAngleLinkProps, R
//ensure id is present for all points on the path
let points = this.props.link.getPoints();
let paths = [];
this.refPaths = [];
// Get points based on link orientation
let pointLeft = points[0];
@@ -286,7 +287,6 @@ export class RightAngleLinkWidget extends React.Component<RightAngleLinkProps, R
);
}
this.refPaths = [];
return <g data-default-link-test={this.props.link.getOptions().testName}>{paths}</g>;
}
}

View File

@@ -1,14 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"outDir": "dist",
"rootDir": "src",
"declarationDir": "dist/@types",
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
},
"include": [
"./src"
],
"include": ["./src"],
"references": [
{
"path": "../geometry"

View File

@@ -1,5 +1,27 @@
# @projectstorm/react-diagrams
## 7.0.4
### Patch Changes
- Updated dependencies [09ed60f]
- Updated dependencies [20766f5]
- Updated dependencies [80285fe]
- @projectstorm/react-canvas-core@7.0.3
- @projectstorm/react-diagrams-core@7.0.3
- @projectstorm/react-diagrams-defaults@7.1.3
- @projectstorm/react-diagrams-routing@7.1.3
## 7.0.3
### Patch Changes
- Updated dependencies [66c687a]
- @projectstorm/react-diagrams-defaults@7.1.2
- @projectstorm/react-diagrams-routing@7.1.2
- @projectstorm/react-diagrams-core@7.0.2
- @projectstorm/react-canvas-core@7.0.2
## 7.0.2
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@projectstorm/react-diagrams",
"version": "7.0.2",
"version": "7.0.4",
"author": "dylanvorster",
"license": "MIT",
"repository": {

18337
pnpm-lock.yaml generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
{
"compileOnSave": false,
"compilerOptions": {
"suppressExcessPropertyErrors": true,
"declaration": true,
"composite": true,
"incremental": true,