diff --git a/lib-core/index.ts b/lib-core/index.ts deleted file mode 100644 index e63042c..0000000 --- a/lib-core/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import './sass/main.scss'; - -export * from './src/core-actions/AbstractAction'; -export * from './src/core-actions/AbstractActionFactory'; -export * from './src/core-actions/AbstractMouseAction'; - -export * from './src/actions/move-canvas/MoveCanvasActionFactory'; -export * from './src/actions/move-canvas/MoveCanvasAction'; - -export * from './src/actions/selecting-items/SelectingAction'; -export * from './src/actions/selecting-items/SelectingItemsActionFactory'; - -export * from './src/actions/move-items/MoveItemsAction'; -export * from './src/actions/move-items/MoveItemsActionFactory'; - -export * from './src/core/BaseObserver'; -export * from './src/core/FactoryBank'; -export * from './src/core/AbstractFactory'; -export * from './src/core/AbstractModelFactory'; -export * from './src/core/AbstractReactFactory'; - -export * from './src/core-models/BaseModel'; -export * from './src/core-models/BasePositionModel'; -export * from './src/core-models/BaseEntity'; - -export * from './src/models/DiagramModel'; -export * from './src/models/LabelModel'; -export * from './src/models/LinkModel'; -export * from './src/models/PointModel'; -export * from './src/models/PortModel'; -export * from './src/models/SelectionModel'; -export * from './src/models/NodeModel'; - -export * from './src/widgets/BaseWidget'; -export * from './src/widgets/DiagramWidget'; -export * from './src/widgets/layers/LinkLayerWidget'; -export * from './src/widgets/layers/NodeLayerWidget'; -export * from './src/widgets/LinkWidget'; -export * from './src/widgets/NodeWidget'; -export * from './src/widgets/PortWidget'; - -export * from './src/DiagramEngine'; -export * from './src/Toolkit'; diff --git a/lib-core/sass/_DiagramWidget.scss b/lib-core/sass/_DiagramWidget.scss deleted file mode 100644 index 5074b56..0000000 --- a/lib-core/sass/_DiagramWidget.scss +++ /dev/null @@ -1,13 +0,0 @@ -.srd-diagram { - position: relative; - flex-grow: 1; - display: flex; - cursor: move; - overflow: hidden; - - &__selector { - position: absolute; - background-color: rgba(0, 192, 255, 0.2); - border: solid 2px rgb(0, 192, 255); - } -} diff --git a/lib-core/sass/_LinkLayerWidget.scss b/lib-core/sass/_LinkLayerWidget.scss deleted file mode 100644 index 56add9f..0000000 --- a/lib-core/sass/_LinkLayerWidget.scss +++ /dev/null @@ -1,11 +0,0 @@ -.srd-link-layer { - position: absolute; - height: 100%; - width: 100%; - transform-origin: 0 0; - overflow: visible !important; - top: 0; - bottom: 0; - left: 0; - right: 0; -} diff --git a/lib-core/sass/_NodeLayerWidget.scss b/lib-core/sass/_NodeLayerWidget.scss deleted file mode 100644 index a3732e7..0000000 --- a/lib-core/sass/_NodeLayerWidget.scss +++ /dev/null @@ -1,11 +0,0 @@ -.srd-node-layer { - top: 0; - left: 0; - right: 0; - bottom: 0; - position: absolute; - pointer-events: none; - transform-origin: 0 0; - width: 100%; - height: 100%; -} diff --git a/lib-core/sass/_NodeWidget.scss b/lib-core/sass/_NodeWidget.scss deleted file mode 100644 index a5b40eb..0000000 --- a/lib-core/sass/_NodeWidget.scss +++ /dev/null @@ -1,14 +0,0 @@ -.srd-node { - position: absolute; - -webkit-touch-callout: none; /* iOS Safari */ - -webkit-user-select: none; /* Chrome/Safari/Opera */ - user-select: none; - cursor: move; - pointer-events: all; - - &--selected { - > * { - border-color: rgb(0, 192, 255) !important; - } - } -} diff --git a/lib-core/sass/_PortWidget.scss b/lib-core/sass/_PortWidget.scss deleted file mode 100644 index 4e2c819..0000000 --- a/lib-core/sass/_PortWidget.scss +++ /dev/null @@ -1,10 +0,0 @@ -.srd-port { - width: 15px; - height: 15px; - background: rgba(white, 0.1); - - &:hover, - &.selected { - background: rgb(192, 255, 0); - } -} diff --git a/lib-core/sass/main.scss b/lib-core/sass/main.scss deleted file mode 100644 index 8f59e63..0000000 --- a/lib-core/sass/main.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import 'DiagramWidget'; -@import 'LinkLayerWidget'; -@import 'NodeLayerWidget'; -@import 'NodeWidget'; -@import 'PortWidget'; diff --git a/lib-core/src/actions/move-canvas/MoveCanvasAction.ts b/lib-core/src/actions/move-canvas/MoveCanvasAction.ts deleted file mode 100644 index d0aca28..0000000 --- a/lib-core/src/actions/move-canvas/MoveCanvasAction.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { AbstractMouseAction } from '../../core-actions/AbstractMouseAction'; -import { MouseEvent } from 'react'; -import { DiagramEngine } from '../../DiagramEngine'; - -export class MoveCanvasAction extends AbstractMouseAction { - initialOffsetX: number; - initialOffsetY: number; - - constructor(mouseX: number, mouseY: number, engine: DiagramEngine) { - super(mouseX, mouseY, engine); - this.initialOffsetX = this.model.getOffsetX(); - this.initialOffsetY = this.model.getOffsetY(); - } - - fireMouseMove(event: MouseEvent) { - //translate the actual canvas - this.model.setOffset( - this.initialOffsetX + (event.clientX - this.mouseX), - this.initialOffsetY + (event.clientY - this.mouseY) - ); - } - - fireMouseUp(event) {} - - fireMouseDown(event) { - this.model.clearSelection(); - } -} diff --git a/lib-core/src/actions/move-canvas/MoveCanvasActionFactory.ts b/lib-core/src/actions/move-canvas/MoveCanvasActionFactory.ts deleted file mode 100644 index 34e5f58..0000000 --- a/lib-core/src/actions/move-canvas/MoveCanvasActionFactory.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AbstractActionFactory, ActionFactoryActivationEvent } from '../../core-actions/AbstractActionFactory'; -import { MoveCanvasAction } from './MoveCanvasAction'; -import { MouseEvent } from 'react'; - -export class MoveCanvasActionFactory extends AbstractActionFactory { - constructor() { - super('move-canvas'); - } - - generateAction(event: MouseEvent): MoveCanvasAction { - return new MoveCanvasAction(event.clientX, event.clientY, this.engine); - } - - activate(event: ActionFactoryActivationEvent): boolean { - return !event.selectedEntity && !event.mouseEvent.shiftKey; - } -} diff --git a/lib-core/src/actions/move-items/MoveItemsAction.ts b/lib-core/src/actions/move-items/MoveItemsAction.ts deleted file mode 100644 index 155b975..0000000 --- a/lib-core/src/actions/move-items/MoveItemsAction.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { AbstractMouseAction } from '../../core-actions/AbstractMouseAction'; -import { SelectionModel } from '../../models/SelectionModel'; -import { PointModel } from '../../models/PointModel'; -import { NodeModel } from '../../models/NodeModel'; -import { DiagramEngine } from '../../DiagramEngine'; -import { BasePositionModel } from '../../core-models/BasePositionModel'; -import * as _ from 'lodash'; -import { PortModel } from '../../models/PortModel'; -import { LinkModel } from '../../models/LinkModel'; -import { MouseEvent } from 'react'; -import { ActionFactoryActivationEvent } from '../../core-actions/AbstractActionFactory'; - -export class MoveItemsAction extends AbstractMouseAction { - selectionModels: SelectionModel[]; - moved: boolean; - allowLooseLinks: boolean; - - constructor(mouseX: number, mouseY: number, diagramEngine: DiagramEngine, allowLooseLinks: boolean) { - super(mouseX, mouseY, diagramEngine); - this.allowLooseLinks = allowLooseLinks; - this.moved = false; - } - - fireMouseMove(event: MouseEvent) { - let amountX = event.clientX - this.mouseX; - let amountY = event.clientY - this.mouseY; - let amountZoom = this.model.getZoomLevel() / 100; - - _.forEach(this.selectionModels, model => { - // in this case we need to also work out the relative grid position - if (model.model instanceof NodeModel || (model.model instanceof PointModel && !model.model.isConnectedToPort())) { - model.model.setPosition( - this.model.getGridPosition(model.initialX + amountX / amountZoom), - this.model.getGridPosition(model.initialY + amountY / amountZoom) - ); - } else if (model.model instanceof PointModel) { - // we want points that are connected to ports, to not necessarily snap to grid - // this stuff needs to be pixel perfect, dont touch it - model.model.setPosition( - model.initialX + this.model.getGridPosition(amountX / amountZoom), - model.initialY + this.model.getGridPosition(amountY / amountZoom) - ); - } - }); - this.moved = true; - } - - fireMouseUp(event: MouseEvent) { - const element = this.engine.getMouseElement(event); - _.forEach(this.selectionModels, model => { - //only care about points connecting to things - if (!(model.model instanceof PointModel)) { - return; - } - if (element && element.model instanceof PortModel && !this.engine.isModelLocked(element.model)) { - let link = model.model.getLink(); - - //if this was a valid link already and we are adding a node in the middle, create 2 links from the original - if (link.getTargetPort()) { - if (link.getTargetPort() !== element.model && link.getSourcePort() !== element.model) { - const targetPort = link.getTargetPort(); - let newLink = link.clone({}); - newLink.setSourcePort(element.model); - newLink.setTargetPort(targetPort); - link.setTargetPort(element.model); - link.getLastPoint().setPosition(this.engine.getPortCenter(element.model)); - targetPort.removeLink(link); - newLink.removePointsBefore(newLink.getPoints()[link.getPointIndex(model.model)]); - link.removePointsAfter(model.model); - this.engine.getDiagramModel().addLink(newLink); - //if we are connecting to the same target or source, remove tweener points - } else if (link.getTargetPort() === element.model) { - link.removePointsAfter(model.model); - } else if (link.getSourcePort() === element.model) { - link.removePointsBefore(model.model); - } - } - - // set the target port - else { - link.setTargetPort(element.model); - link.getLastPoint().setPosition(this.engine.getPortCenter(element.model)); - } - } - }); - - //check for / remove any loose links in any models which have been moved - if (!this.allowLooseLinks && this.moved) { - _.forEach(this.selectionModels, model => { - //only care about points connecting to things - if (!(model.model instanceof PointModel)) { - return; - } - - let selectedPoint: PointModel = model.model; - let link: LinkModel = selectedPoint.getLink(); - if (link.getSourcePort() === null || link.getTargetPort() === null) { - link.remove(); - } - }); - } - - //remove any invalid links - _.forEach(this.selectionModels, model => { - //only care about points connecting to things - if (!(model.model instanceof PointModel)) { - return; - } - - let link: LinkModel = model.model.getLink(); - let sourcePort: PortModel = link.getSourcePort(); - let targetPort: PortModel = link.getTargetPort(); - if (sourcePort !== null && targetPort !== null) { - if (!sourcePort.canLinkToPort(targetPort)) { - //link not allowed - link.remove(); - } else if ( - _.some( - _.values(targetPort.getLinks()), - (l: LinkModel) => l !== link && (l.getSourcePort() === sourcePort || l.getTargetPort() === sourcePort) - ) - ) { - //link is a duplicate - link.remove(); - } - } - }); - } - - fireMouseDown(event: ActionFactoryActivationEvent) { - // clear selection first? - if (!event.selectedModel.isSelected()) { - this.model.clearSelection(); - } - - if (event.selectedModel instanceof PortModel) { - //its a port element, we want to drag a link - if (!this.engine.isModelLocked(event.selectedModel)) { - const portCenter = this.engine.getPortCenter(event.selectedModel); - const sourcePort = event.selectedModel; - const link = sourcePort.createLinkModel(); - link.setSourcePort(sourcePort); - - if (link) { - link.removeMiddlePoints(); - if (link.getSourcePort() !== sourcePort) { - link.setSourcePort(sourcePort); - } - link.setTargetPort(null); - - link.getFirstPoint().setPosition(portCenter); - link.getLastPoint().setPosition(portCenter); - - this.model.clearSelection(); - link.getLastPoint().setSelected(true); - this.model.addLink(link); - } - } - } else { - event.selectedModel.setSelected(true); - } - const selectedItems = this.model.getSelectedItems().filter(item => { - if (!(item instanceof BasePositionModel)) { - return false; - } - return !this.engine.isModelLocked(item); - }); - - this.selectionModels = selectedItems.map((item: PointModel | NodeModel) => { - return { - model: item, - initialX: item.getX(), - initialY: item.getY() - }; - }); - } -} diff --git a/lib-core/src/actions/move-items/MoveItemsActionFactory.ts b/lib-core/src/actions/move-items/MoveItemsActionFactory.ts deleted file mode 100644 index f3b72b8..0000000 --- a/lib-core/src/actions/move-items/MoveItemsActionFactory.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { AbstractActionFactory, ActionFactoryActivationEvent } from '../../core-actions/AbstractActionFactory'; -import { MouseEvent } from 'react'; -import { MoveItemsAction } from './MoveItemsAction'; - -export interface MoveItemsActionFactoryOptions { - allowLooseLinks?: boolean; -} - -export class MoveItemsActionFactory extends AbstractActionFactory { - options: MoveItemsActionFactoryOptions; - - static NAME = 'move-items'; - - constructor(options: MoveItemsActionFactoryOptions = {}) { - super(MoveItemsActionFactory.NAME); - this.options = { - ...options, - allowLooseLinks: options.allowLooseLinks == null ? true : options.allowLooseLinks - }; - } - - generateAction(event: MouseEvent): MoveItemsAction { - return new MoveItemsAction(event.clientX, event.clientY, this.engine, this.options.allowLooseLinks); - } - - activate(event: ActionFactoryActivationEvent): boolean { - if (event.selectedModel) { - return !this.engine.isModelLocked(event.selectedModel); - } - return false; - } -} diff --git a/lib-core/src/actions/selecting-items/SelectingAction.ts b/lib-core/src/actions/selecting-items/SelectingAction.ts deleted file mode 100644 index e8d5677..0000000 --- a/lib-core/src/actions/selecting-items/SelectingAction.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { AbstractMouseAction } from '../../core-actions/AbstractMouseAction'; -import { DiagramModel } from '../../models/DiagramModel'; -import * as _ from 'lodash'; -import { DiagramEngine } from '../../DiagramEngine'; -import { MouseEvent } from 'react'; - -export class SelectingAction extends AbstractMouseAction { - mouseX2: number; - mouseY2: number; - - constructor(mouseX: number, mouseY: number, engine: DiagramEngine) { - super(mouseX, mouseY, engine); - this.mouseX2 = mouseX; - this.mouseY2 = mouseY; - } - - getBoxDimensions() { - return { - left: this.mouseX2 > this.mouseX ? this.mouseX : this.mouseX2, - top: this.mouseY2 > this.mouseY ? this.mouseY : this.mouseY2, - width: Math.abs(this.mouseX2 - this.mouseX), - height: Math.abs(this.mouseY2 - this.mouseY), - right: this.mouseX2 < this.mouseX ? this.mouseX : this.mouseX2, - bottom: this.mouseY2 < this.mouseY ? this.mouseY : this.mouseY2 - }; - } - - containsElement(x: number, y: number, diagramModel: DiagramModel): boolean { - var z = diagramModel.getZoomLevel() / 100.0; - let dimensions = this.getBoxDimensions(); - - return ( - x * z + diagramModel.getOffsetX() > dimensions.left && - x * z + diagramModel.getOffsetX() < dimensions.right && - y * z + diagramModel.getOffsetY() > dimensions.top && - y * z + diagramModel.getOffsetY() < dimensions.bottom - ); - } - - fireMouseMove(event: MouseEvent) { - var relative = this.engine.getRelativePoint(event.clientX, event.clientY); - - _.forEach(this.model.getNodes(), node => { - // TODO use geometry instead - if (this.containsElement(node.getX(), node.getY(), this.model)) { - node.setSelected(true); - } - }); - - _.forEach(this.model.getLinks(), link => { - var allSelected = true; - _.forEach(link.getPoints(), point => { - if (this.containsElement(point.getX(), point.getY(), this.model)) { - point.setSelected(true); - } else { - allSelected = false; - } - }); - - if (allSelected) { - link.setSelected(true); - } - }); - - this.mouseX2 = relative.x; - this.mouseY2 = relative.y; - } - - fireMouseUp(event) {} - - fireMouseDown(event) {} -} diff --git a/lib-core/src/actions/selecting-items/SelectingItemsActionFactory.ts b/lib-core/src/actions/selecting-items/SelectingItemsActionFactory.ts deleted file mode 100644 index 2f0c158..0000000 --- a/lib-core/src/actions/selecting-items/SelectingItemsActionFactory.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AbstractActionFactory, ActionFactoryActivationEvent } from '../../core-actions/AbstractActionFactory'; -import { MouseEvent } from 'react'; -import { SelectingAction } from './SelectingAction'; - -export class SelectingItemsActionFactory extends AbstractActionFactory { - constructor() { - super('select-items'); - } - - generateAction(event: MouseEvent): SelectingAction { - return new SelectingAction(event.clientX, event.clientY, this.engine); - } - - activate(event: ActionFactoryActivationEvent): boolean { - return !event.selectedEntity && event.mouseEvent.shiftKey; - } -} diff --git a/lib-core/src/core-actions/AbstractAction.ts b/lib-core/src/core-actions/AbstractAction.ts deleted file mode 100644 index 43e798b..0000000 --- a/lib-core/src/core-actions/AbstractAction.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { DiagramEngine } from '../DiagramEngine'; -import { DiagramModel } from '../models/DiagramModel'; - -export class AbstractAction { - engine: DiagramEngine; - model: DiagramModel; - - constructor(engine: DiagramEngine) { - this.engine = engine; - this.model = engine.getDiagramModel(); - } -} diff --git a/lib-core/src/core-actions/AbstractActionFactory.ts b/lib-core/src/core-actions/AbstractActionFactory.ts deleted file mode 100644 index d412144..0000000 --- a/lib-core/src/core-actions/AbstractActionFactory.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { AbstractAction } from './AbstractAction'; -import { AbstractFactory } from '../core/AbstractFactory'; -import { MouseEvent } from 'react'; -import { BaseModel } from '../core-models/BaseModel'; - -export interface ActionFactoryActivationEvent { - selectedModel: BaseModel; - selectedEntity: HTMLElement; - mouseEvent: MouseEvent; -} - -export abstract class AbstractActionFactory extends AbstractFactory { - abstract activate(event: ActionFactoryActivationEvent): boolean; - - abstract generateAction(event: MouseEvent): T; -} diff --git a/lib-core/src/core-actions/AbstractMouseAction.ts b/lib-core/src/core-actions/AbstractMouseAction.ts deleted file mode 100644 index d7621bf..0000000 --- a/lib-core/src/core-actions/AbstractMouseAction.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MouseEvent } from 'react'; -import { AbstractAction } from './AbstractAction'; -import { DiagramEngine } from '../DiagramEngine'; -import { ActionFactoryActivationEvent } from './AbstractActionFactory'; - -export abstract class AbstractMouseAction extends AbstractAction { - protected mouseX: number; - protected mouseY: number; - - constructor(mouseX: number, mouseY: number, engine: DiagramEngine) { - super(engine); - this.mouseX = mouseX; - this.mouseY = mouseY; - } - - abstract fireMouseDown(event: ActionFactoryActivationEvent); - - abstract fireMouseMove(event: MouseEvent); - - abstract fireMouseUp(event: MouseEvent); -} diff --git a/lib-core/src/core/AbstractModelFactory.ts b/lib-core/src/core/AbstractModelFactory.ts deleted file mode 100644 index a1bdbaa..0000000 --- a/lib-core/src/core/AbstractModelFactory.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { AbstractFactory } from './AbstractFactory'; -import { BaseModel } from '../core-models/BaseModel'; - -export interface GenerateModelEvent { - initialConfig?: any; -} - -export abstract class AbstractModelFactory extends AbstractFactory { - /** - * Generates new models (the core factory pattern) - */ - abstract generateModel(event: GenerateModelEvent): T; -} diff --git a/lib-core/src/models/DiagramModel.ts b/lib-core/src/models/DiagramModel.ts deleted file mode 100644 index 9c450d3..0000000 --- a/lib-core/src/models/DiagramModel.ts +++ /dev/null @@ -1,285 +0,0 @@ -import { - BaseEntity, - BaseEntityEvent, - BaseEntityGenerics, - BaseEntityListener, - BaseEntityOptions, - BaseEntityType -} from '../core-models/BaseEntity'; -import * as _ from 'lodash'; -import { DiagramEngine } from '../DiagramEngine'; -import { LinkModel } from './LinkModel'; -import { NodeModel } from './NodeModel'; -import { PortModel } from './PortModel'; -import { BaseModel } from '../core-models/BaseModel'; -import { PointModel } from './PointModel'; - -export interface DiagramListener extends BaseEntityListener { - nodesUpdated?(event: BaseEntityEvent & { node: NodeModel; isCreated: boolean }): void; - - linksUpdated?(event: BaseEntityEvent & { link: LinkModel; isCreated: boolean }): void; - - offsetUpdated?(event: BaseEntityEvent & { offsetX: number; offsetY: number }): void; - - zoomUpdated?(event: BaseEntityEvent & { zoom: number }): void; - - gridUpdated?(event: BaseEntityEvent & { size: number }): void; -} - -export interface DiagramModelOptions extends BaseEntityOptions { - offsetX?: number; - offsetY?: number; - zoom?: number; - gridSize?: number; -} - -export interface DiagramModelGenerics extends BaseEntityGenerics { - LISTENER: DiagramListener; - OPTIONS: DiagramModelOptions; -} - -export class DiagramModel extends BaseEntity { - //models - protected links: { [s: string]: LinkModel }; - protected nodes: { [s: string]: NodeModel }; - - rendered: boolean; - - constructor(options: G['OPTIONS'] = {}) { - super({ - zoom: 100, - gridSize: 0, - offsetX: 0, - offsetY: 0, - ...options - }); - - this.links = {}; - this.nodes = {}; - this.rendered = false; - } - - setGridSize(size: number = 0) { - this.options.gridSize = size; - this.fireEvent({ size: size }, 'gridUpdated'); - } - - getGridPosition(pos) { - if (this.options.gridSize === 0) { - return pos; - } - return this.options.gridSize * Math.floor((pos + this.options.gridSize / 2) / this.options.gridSize); - } - - deSerializeDiagram(object: any, diagramEngine: DiagramEngine) { - this.deSerialize(object, diagramEngine); - - this.options.offsetX = object.offsetX; - this.options.offsetY = object.offsetY; - this.options.zoom = object.zoom; - this.options.gridSize = object.gridSize; - - // deserialize nodes - _.forEach(object.nodes, (node: any) => { - let nodeOb = diagramEngine.getFactoryForNode(node.type).generateModel({ initialConfig: node }); - nodeOb.setParent(this); - nodeOb.deSerialize(node, diagramEngine); - this.addNode(nodeOb); - }); - - // deserialze links - _.forEach(object.links, (link: any) => { - let linkOb = diagramEngine.getFactoryForLink(link.type).generateModel({ initialConfig: link }); - linkOb.setParent(this); - linkOb.deSerialize(link, diagramEngine); - this.addLink(linkOb); - }); - } - - serializeDiagram() { - return { - ...this.serialize(), - offsetX: this.options.offsetX, - offsetY: this.options.offsetY, - zoom: this.options.zoom, - gridSize: this.options.gridSize, - links: _.map(this.links, link => { - return link.serialize(); - }), - nodes: _.map(this.nodes, node => { - return node.serialize(); - }) - }; - } - - clearSelection(ignore: BaseModel | null = null) { - _.forEach(this.getSelectedItems(), element => { - if (ignore && ignore.getID() === element.getID()) { - return; - } - element.setSelected(false); //TODO dont fire the listener - }); - } - - getSelectedItems(...filters: BaseEntityType[]): BaseModel[] { - if (!Array.isArray(filters)) { - filters = [filters]; - } - var items = []; - - // run through nodes - items = items.concat( - _.flatMap(this.nodes, node => { - return node.getSelectedEntities(); - }) - ); - - // find all the links - items = items.concat( - _.flatMap(this.links, link => { - return link.getSelectedEntities(); - }) - ); - - //find all points - items = items.concat( - _.flatMap(this.links, link => { - return _.flatMap(link.getPoints(), point => { - return point.getSelectedEntities(); - }); - }) - ); - - items = _.uniq(items); - - if (filters.length > 0) { - items = _.filter(_.uniq(items), (item: BaseModel) => { - if (_.includes(filters, 'node') && item instanceof NodeModel) { - return true; - } - if (_.includes(filters, 'link') && item instanceof LinkModel) { - return true; - } - if (_.includes(filters, 'port') && item instanceof PortModel) { - return true; - } - if (_.includes(filters, 'point') && item instanceof PointModel) { - return true; - } - return false; - }); - } - - return items; - } - - setZoomLevel(zoom: number) { - this.options.zoom = zoom; - this.fireEvent({ zoom }, 'zoomUpdated'); - } - - setOffset(offsetX: number, offsetY: number) { - this.options.offsetX = offsetX; - this.options.offsetY = offsetY; - this.fireEvent({ offsetX, offsetY }, 'offsetUpdated'); - } - - setOffsetX(offsetX: number) { - this.setOffset(offsetX, this.options.offsetY); - } - - setOffsetY(offsetY: number) { - this.setOffset(this.options.offsetX, offsetY); - } - - getOffsetY() { - return this.options.offsetY; - } - - getOffsetX() { - return this.options.offsetX; - } - - getZoomLevel() { - return this.options.zoom; - } - - getNode(node: string | NodeModel): NodeModel | null { - if (node instanceof NodeModel) { - return node; - } - if (!this.nodes[node]) { - return null; - } - return this.nodes[node]; - } - - getLink(link: string | LinkModel): LinkModel | null { - if (link instanceof LinkModel) { - return link; - } - if (!this.links[link]) { - return null; - } - return this.links[link]; - } - - addAll(...models: BaseModel[]): BaseModel[] { - _.forEach(models, model => { - if (model instanceof LinkModel) { - this.addLink(model); - } else if (model instanceof NodeModel) { - this.addNode(model); - } - }); - return models; - } - - addLink(link: LinkModel): LinkModel { - link.registerListener({ - entityRemoved: () => { - this.removeLink(link); - } - }); - this.links[link.getID()] = link; - this.fireEvent( - { - link, - isCreated: true - }, - 'linksUpdated' - ); - return link; - } - - addNode(node: NodeModel): NodeModel { - node.registerListener({ - entityRemoved: () => { - this.removeNode(node); - } - }); - this.nodes[node.getID()] = node; - this.fireEvent({ node, isCreated: true }, 'nodesUpdated'); - return node; - } - - removeLink(link: LinkModel | string) { - link = this.getLink(link); - delete this.links[link.getID()]; - this.fireEvent({ link, isCreated: false }, 'linksUpdated'); - } - - removeNode(node: NodeModel | string) { - node = this.getNode(node); - delete this.nodes[node.getID()]; - this.fireEvent({ node, isCreated: false }, 'nodesUpdated'); - } - - getLinks(): { [s: string]: LinkModel } { - return this.links; - } - - getNodes(): { [s: string]: NodeModel } { - return this.nodes; - } -} diff --git a/lib-core/src/models/SelectionModel.ts b/lib-core/src/models/SelectionModel.ts deleted file mode 100644 index ac616cd..0000000 --- a/lib-core/src/models/SelectionModel.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { BaseModel } from '../core-models/BaseModel'; - -export interface SelectionModel { - model: BaseModel; - initialX: number; - initialY: number; -} diff --git a/lib-core/src/widgets/ActionManager.ts b/lib-core/src/widgets/ActionManager.ts deleted file mode 100644 index a4a3e96..0000000 --- a/lib-core/src/widgets/ActionManager.ts +++ /dev/null @@ -1 +0,0 @@ -export class ActionManager {} diff --git a/lib-core/src/widgets/BaseWidget.tsx b/lib-core/src/widgets/BaseWidget.tsx deleted file mode 100644 index ab7ecab..0000000 --- a/lib-core/src/widgets/BaseWidget.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as React from 'react'; - -export interface BaseWidgetProps { - /** - * Override the base class name - */ - baseClass?: string; - /** - * append additional classes - */ - className?: string; - - /** - * Additional props to add - */ - extraProps?: any; -} - -export class BaseWidget

extends React.Component { - className: string; - - constructor(name: string, props: P) { - super(props); - this.className = name; - } - - bem(selector: string): string { - return (this.props.baseClass || this.className) + selector + ' '; - } - - getClassName(): string { - return (this.props.baseClass || this.className) + ' ' + (this.props.className ? this.props.className + ' ' : ''); - } - - getProps(): any { - return { - ...((this.props.extraProps as any) || {}), - className: this.getClassName() - }; - } -} diff --git a/lib-core/src/widgets/DiagramWidget.tsx b/lib-core/src/widgets/DiagramWidget.tsx deleted file mode 100644 index d9bd8d9..0000000 --- a/lib-core/src/widgets/DiagramWidget.tsx +++ /dev/null @@ -1,288 +0,0 @@ -import * as React from 'react'; -import { DiagramEngine } from '../DiagramEngine'; -import * as _ from 'lodash'; -import { LinkLayerWidget } from './layers/LinkLayerWidget'; -import { NodeLayerWidget } from './layers/NodeLayerWidget'; -import { AbstractMouseAction } from '../core-actions/AbstractMouseAction'; -import { MoveItemsAction } from '../actions/move-items/MoveItemsAction'; -import { SelectingAction } from '../actions/selecting-items/SelectingAction'; -import { PointModel } from '../models/PointModel'; -import { BaseWidget, BaseWidgetProps } from './BaseWidget'; -import { MouseEvent } from 'react'; -import { ActionFactoryActivationEvent } from '../core-actions/AbstractActionFactory'; -import { AbstractAction } from '../core-actions/AbstractAction'; -import { MoveItemsActionFactory } from '../actions/move-items/MoveItemsActionFactory'; - -export interface DiagramProps extends BaseWidgetProps { - diagramEngine: DiagramEngine; - - // zoom - allowCanvasZoom?: boolean; - inverseZoom?: boolean; - - actionStartedFiring?: (action: AbstractAction) => boolean; - actionStillFiring?: (action: AbstractAction) => void; - actionStoppedFiring?: (action: AbstractAction) => void; - - deleteKeys?: number[]; -} - -export interface DiagramState { - action: AbstractAction; - diagramEngineListener: any; -} - -export class DiagramWidget extends BaseWidget { - onKeyUpPointer: (this: Window, ev: KeyboardEvent) => void = null; - ref: React.RefObject; - - constructor(props: DiagramProps) { - super('srd-diagram', props); - - this.ref = React.createRef(); - this.state = { - action: null, - diagramEngineListener: null - }; - } - - componentWillUnmount() { - this.props.diagramEngine.deregisterListener(this.state.diagramEngineListener); - this.props.diagramEngine.setCanvas(null); - window.removeEventListener('keyup', this.onKeyUpPointer); - window.removeEventListener('mouseUp', this.onMouseUp); - window.removeEventListener('mouseMove', this.onMouseMove); - } - - componentWillReceiveProps(nextProps: DiagramProps) { - if (this.props.diagramEngine !== nextProps.diagramEngine) { - this.props.diagramEngine.deregisterListener(this.state.diagramEngineListener); - const diagramEngineListener = nextProps.diagramEngine.registerListener({ - repaintCanvas: () => this.forceUpdate() - }); - this.setState({ diagramEngineListener }); - } - } - - registerCanvas() { - this.props.diagramEngine.setCanvas(this.ref.current); - this.props.diagramEngine.iterateListeners(list => { - list.rendered && list.rendered(); - }); - } - - componentDidUpdate() { - this.registerCanvas(); - } - - componentDidMount() { - this.onKeyUpPointer = this.onKeyUp.bind(this); - - //add a keyboard listener - this.setState({ - diagramEngineListener: this.props.diagramEngine.registerListener({ - repaintCanvas: () => { - this.forceUpdate(); - } - }) - }); - - window.addEventListener('keyup', this.onKeyUpPointer, false); - - // dont focus the window when in test mode - jsdom fails - if (process.env.NODE_ENV !== 'test') { - window.focus(); - } - - this.registerCanvas(); - } - - fireAction() { - if (this.state.action && this.props.actionStillFiring) { - this.props.actionStillFiring(this.state.action); - } - } - - stopFiringAction(shouldSkipEvent?: boolean) { - if (this.props.actionStoppedFiring && !shouldSkipEvent) { - this.props.actionStoppedFiring(this.state.action); - } - this.setState({ action: null }); - } - - startFiringAction(action: AbstractAction) { - var setState = true; - if (this.props.actionStartedFiring) { - setState = this.props.actionStartedFiring(action); - } - if (setState) { - this.setState({ action: action }); - } - } - - onMouseUp = event => { - if (this.state.action && this.state.action instanceof AbstractMouseAction) { - this.state.action.fireMouseUp(event); - } - this.stopFiringAction(); - document.removeEventListener('mousemove', this.onMouseMove); - document.removeEventListener('mouseup', this.onMouseUp); - }; - - onMouseMove = event => { - //select items so draw a bounding box - if (this.state.action) { - if (this.state.action && this.state.action instanceof AbstractMouseAction) { - this.state.action.fireMouseMove(event); - } - this.fireAction(); - this.forceUpdate(); - } - }; - - onKeyUp = event => { - //delete all selected - if ((this.props.deleteKeys || [46, 8]).indexOf(event.keyCode) !== -1) { - _.forEach(this.props.diagramEngine.getDiagramModel().getSelectedItems(), element => { - //only delete items which are not locked - if (!this.props.diagramEngine.isModelLocked(element)) { - element.remove(); - } - }); - this.forceUpdate(); - } - }; - - drawSelectionBox() { - let dimensions = (this.state.action as SelectingAction).getBoxDimensions(); - return ( -

- ); - } - - getActionForEvent(event: MouseEvent): AbstractAction { - event.persist(); - const { diagramEngine } = this.props; - const model = diagramEngine.getMouseElement(event); - - const activateEvent: ActionFactoryActivationEvent = { - selectedModel: model && model.model, - selectedEntity: model && (model.element as HTMLElement), - mouseEvent: event - }; - - for (let factory of diagramEngine.getActionFactories().getFactories()) { - if (factory.activate(activateEvent)) { - return factory.generateAction(event); - } - } - return null; - } - - render() { - const diagramEngine = this.props.diagramEngine; - const diagramModel = diagramEngine.getDiagramModel(); - - return ( -
{ - const allow = this.props.allowCanvasZoom == null ? true : this.props.allowCanvasZoom; - if (allow) { - event.stopPropagation(); - const oldZoomFactor = diagramModel.getZoomLevel() / 100; - let scrollDelta = this.props.inverseZoom ? -event.deltaY : event.deltaY; - //check if it is pinch gesture - if (event.ctrlKey && scrollDelta % 1 !== 0) { - /*Chrome and Firefox sends wheel event with deltaY that - have fractional part, also `ctrlKey` prop of the event is true - though ctrl isn't pressed - */ - scrollDelta /= 3; - } else { - scrollDelta /= 60; - } - if (diagramModel.getZoomLevel() + scrollDelta > 10) { - diagramModel.setZoomLevel(diagramModel.getZoomLevel() + scrollDelta); - } - - const zoomFactor = diagramModel.getZoomLevel() / 100; - - const boundingRect = event.currentTarget.getBoundingClientRect(); - const clientWidth = boundingRect.width; - const clientHeight = boundingRect.height; - // compute difference between rect before and after scroll - const widthDiff = clientWidth * zoomFactor - clientWidth * oldZoomFactor; - const heightDiff = clientHeight * zoomFactor - clientHeight * oldZoomFactor; - // compute mouse coords relative to canvas - const clientX = event.clientX - boundingRect.left; - const clientY = event.clientY - boundingRect.top; - - // compute width and height increment factor - const xFactor = (clientX - diagramModel.getOffsetX()) / oldZoomFactor / clientWidth; - const yFactor = (clientY - diagramModel.getOffsetY()) / oldZoomFactor / clientHeight; - - diagramModel.setOffset( - diagramModel.getOffsetX() - widthDiff * xFactor, - diagramModel.getOffsetY() - heightDiff * yFactor - ); - - this.forceUpdate(); - } - }} - onMouseDown={event => { - // try and get an action for this event - const action = this.getActionForEvent(event); - if (action) { - if (action instanceof AbstractMouseAction) { - const selected = diagramEngine.getMouseElement(event); - action.fireMouseDown({ - mouseEvent: event, - selectedEntity: selected && (selected.element as HTMLElement), - selectedModel: selected && selected.model - }); - } - this.startFiringAction(action); - } - document.addEventListener('mousemove', this.onMouseMove); - document.addEventListener('mouseup', this.onMouseUp); - }}> - { - document.addEventListener('mousemove', this.onMouseMove); - document.addEventListener('mouseup', this.onMouseUp); - event.stopPropagation(); - - // TODO implement this better and more generic - let action: MoveItemsAction = null; - let fac: MoveItemsActionFactory = null; - try { - fac = diagramEngine.getActionFactories().getFactory(MoveItemsActionFactory.NAME); - } catch (e) {} - if (fac) { - action = fac.generateAction(event); - action.fireMouseDown({ - selectedModel: point, - selectedEntity: event.target as HTMLElement, - mouseEvent: event - }); - this.startFiringAction(action); - } - }} - /> - - {this.state.action instanceof SelectingAction && this.drawSelectionBox()} -
- ); - } -} diff --git a/lib-core/src/widgets/layers/LinkLayerWidget.tsx b/lib-core/src/widgets/layers/LinkLayerWidget.tsx deleted file mode 100644 index 410aee2..0000000 --- a/lib-core/src/widgets/layers/LinkLayerWidget.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import * as React from 'react'; -import { DiagramEngine } from '../../DiagramEngine'; -import { LinkWidget } from '../LinkWidget'; -import * as _ from 'lodash'; -import { PointModel } from '../../models/PointModel'; -import { BaseWidget, BaseWidgetProps } from '../BaseWidget'; -import { MouseEvent } from 'react'; - -export interface LinkLayerProps extends BaseWidgetProps { - diagramEngine: DiagramEngine; - pointAdded: (point: PointModel, event: MouseEvent) => any; -} - -export class LinkLayerWidget extends BaseWidget { - constructor(props: LinkLayerProps) { - super('srd-link-layer', props); - } - - render() { - var diagramModel = this.props.diagramEngine.getDiagramModel(); - return ( - - {//only perform these actions when we have a diagram - _.map(diagramModel.getLinks(), link => { - return ( - - ); - })} - - ); - } -} diff --git a/lib-core/src/widgets/layers/NodeLayerWidget.tsx b/lib-core/src/widgets/layers/NodeLayerWidget.tsx deleted file mode 100644 index eb130ec..0000000 --- a/lib-core/src/widgets/layers/NodeLayerWidget.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from 'react'; -import { DiagramEngine } from '../../DiagramEngine'; -import * as _ from 'lodash'; -import { NodeWidget } from '../NodeWidget'; -import { NodeModel } from '../../models/NodeModel'; -import { BaseWidget, BaseWidgetProps } from '../BaseWidget'; - -export interface NodeLayerProps extends BaseWidgetProps { - diagramEngine: DiagramEngine; -} - -export class NodeLayerWidget extends BaseWidget { - constructor(props: NodeLayerProps) { - super('srd-node-layer', props); - } - - render() { - var diagramModel = this.props.diagramEngine.getDiagramModel(); - return ( -
- {_.map(diagramModel.getNodes(), (node: NodeModel) => { - return ; - })} -
- ); - } -} diff --git a/lib-core/webpack.config.js b/lib-core/webpack.config.js deleted file mode 100644 index 2c82003..0000000 --- a/lib-core/webpack.config.js +++ /dev/null @@ -1,8 +0,0 @@ -const config = require('../webpack.shared')(__dirname); -module.exports = { - ...config, - output: { - ...config.output, - library: 'projectstorm/react-diagrams-core' - } -}; diff --git a/lib-demo-project/src/BodyWidget.tsx b/lib-demo-project/src/BodyWidget.tsx deleted file mode 100644 index d52ced8..0000000 --- a/lib-demo-project/src/BodyWidget.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from 'react'; -import { DiagramEngine, DiagramWidget } from '@projectstorm/react-diagrams'; - -export interface BodyWidgetProps { - engine: DiagramEngine; -} - -export class BodyWidget extends React.Component { - render() { - return ; - } -} diff --git a/package.json b/package.json index b63612d..6f19af6 100644 --- a/package.json +++ b/package.json @@ -7,15 +7,7 @@ "type": "git", "url": "https://github.com/projectstorm/react-diagrams.git" }, - "workspaces": [ - "lib-all", - "lib-core", - "lib-defaults", - "lib-routing", - "lib-geometry", - "lib-demo-project", - "lib-demo-gallery" - ], + "workspaces": ["packages/*"], "keywords": [ "web", "diagram", @@ -33,11 +25,11 @@ "watch": "yarn build:clean && lerna run watch --stream", "publish:dev": "yarn build:prod && lerna publish --force-publish --dist-tag=next", "publish:prod": "yarn build:prod && lerna publish --force-publish", - "publish:storybook": "cd lib-demo-gallery && yarn storybook:build && ../node_modules/.bin/storybook-to-ghpages --existing-output-dir .out", + "publish:storybook": "cd packages/diagrams-demo-gallery && yarn storybook:build && ../../node_modules/.bin/storybook-to-ghpages --existing-output-dir .out", "build:clean": "lerna run clean --stream", "test": "lerna run test --stream", "test:ci": "lerna run test --stream -- --runInBand --ci ", - "pretty": "prettier --write \"lib-*/**/*.{ts,tsx,scss,js,jsx}\"" + "pretty": "prettier --write \"packages/**/*.{ts,tsx,scss,js,jsx}\"" }, "peerDependencies": { "closest": "^0.0.1", diff --git a/lib-demo-gallery/.storybook/addons.js b/packages/diagrams-demo-gallery/.storybook/addons.js similarity index 100% rename from lib-demo-gallery/.storybook/addons.js rename to packages/diagrams-demo-gallery/.storybook/addons.js diff --git a/lib-demo-gallery/.storybook/config.js b/packages/diagrams-demo-gallery/.storybook/config.js similarity index 100% rename from lib-demo-gallery/.storybook/config.js rename to packages/diagrams-demo-gallery/.storybook/config.js diff --git a/lib-demo-gallery/.storybook/webpack.config.js b/packages/diagrams-demo-gallery/.storybook/webpack.config.js similarity index 100% rename from lib-demo-gallery/.storybook/webpack.config.js rename to packages/diagrams-demo-gallery/.storybook/webpack.config.js diff --git a/lib-demo-gallery/demos/demo-cloning/index.tsx b/packages/diagrams-demo-gallery/demos/demo-cloning/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-cloning/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-cloning/index.tsx diff --git a/lib-demo-gallery/demos/demo-custom-link1/index.tsx b/packages/diagrams-demo-gallery/demos/demo-custom-link1/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-custom-link1/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-custom-link1/index.tsx diff --git a/lib-demo-gallery/demos/demo-custom-node1/DiamondNodeFactory.tsx b/packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeFactory.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-custom-node1/DiamondNodeFactory.tsx rename to packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeFactory.tsx diff --git a/lib-demo-gallery/demos/demo-custom-node1/DiamondNodeModel.ts b/packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeModel.ts similarity index 100% rename from lib-demo-gallery/demos/demo-custom-node1/DiamondNodeModel.ts rename to packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeModel.ts diff --git a/lib-demo-gallery/demos/demo-custom-node1/DiamondNodeWidget.tsx b/packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeWidget.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-custom-node1/DiamondNodeWidget.tsx rename to packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeWidget.tsx diff --git a/lib-demo-gallery/demos/demo-custom-node1/DiamondPortModel.ts b/packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondPortModel.ts similarity index 100% rename from lib-demo-gallery/demos/demo-custom-node1/DiamondPortModel.ts rename to packages/diagrams-demo-gallery/demos/demo-custom-node1/DiamondPortModel.ts diff --git a/lib-demo-gallery/demos/demo-custom-node1/SimplePortFactory.ts b/packages/diagrams-demo-gallery/demos/demo-custom-node1/SimplePortFactory.ts similarity index 100% rename from lib-demo-gallery/demos/demo-custom-node1/SimplePortFactory.ts rename to packages/diagrams-demo-gallery/demos/demo-custom-node1/SimplePortFactory.ts diff --git a/lib-demo-gallery/demos/demo-custom-node1/index.tsx b/packages/diagrams-demo-gallery/demos/demo-custom-node1/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-custom-node1/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-custom-node1/index.tsx diff --git a/lib-demo-gallery/demos/demo-dagre/index.tsx b/packages/diagrams-demo-gallery/demos/demo-dagre/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-dagre/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-dagre/index.tsx diff --git a/lib-demo-gallery/demos/demo-drag-and-drop/Application.ts b/packages/diagrams-demo-gallery/demos/demo-drag-and-drop/Application.ts similarity index 100% rename from lib-demo-gallery/demos/demo-drag-and-drop/Application.ts rename to packages/diagrams-demo-gallery/demos/demo-drag-and-drop/Application.ts diff --git a/lib-demo-gallery/demos/demo-drag-and-drop/components/BodyWidget.tsx b/packages/diagrams-demo-gallery/demos/demo-drag-and-drop/components/BodyWidget.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-drag-and-drop/components/BodyWidget.tsx rename to packages/diagrams-demo-gallery/demos/demo-drag-and-drop/components/BodyWidget.tsx diff --git a/lib-demo-gallery/demos/demo-drag-and-drop/components/TrayItemWidget.tsx b/packages/diagrams-demo-gallery/demos/demo-drag-and-drop/components/TrayItemWidget.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-drag-and-drop/components/TrayItemWidget.tsx rename to packages/diagrams-demo-gallery/demos/demo-drag-and-drop/components/TrayItemWidget.tsx diff --git a/lib-demo-gallery/demos/demo-drag-and-drop/components/TrayWidget.tsx b/packages/diagrams-demo-gallery/demos/demo-drag-and-drop/components/TrayWidget.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-drag-and-drop/components/TrayWidget.tsx rename to packages/diagrams-demo-gallery/demos/demo-drag-and-drop/components/TrayWidget.tsx diff --git a/lib-demo-gallery/demos/demo-drag-and-drop/index.tsx b/packages/diagrams-demo-gallery/demos/demo-drag-and-drop/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-drag-and-drop/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-drag-and-drop/index.tsx diff --git a/lib-demo-gallery/demos/demo-drag-and-drop/sass/main.scss b/packages/diagrams-demo-gallery/demos/demo-drag-and-drop/sass/main.scss similarity index 100% rename from lib-demo-gallery/demos/demo-drag-and-drop/sass/main.scss rename to packages/diagrams-demo-gallery/demos/demo-drag-and-drop/sass/main.scss diff --git a/lib-demo-gallery/demos/demo-dynamic-ports/index.tsx b/packages/diagrams-demo-gallery/demos/demo-dynamic-ports/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-dynamic-ports/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-dynamic-ports/index.tsx diff --git a/lib-demo-gallery/demos/demo-grid/index.tsx b/packages/diagrams-demo-gallery/demos/demo-grid/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-grid/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-grid/index.tsx diff --git a/lib-demo-gallery/demos/demo-labelled-links/index.tsx b/packages/diagrams-demo-gallery/demos/demo-labelled-links/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-labelled-links/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-labelled-links/index.tsx diff --git a/lib-demo-gallery/demos/demo-limit-points/index.tsx b/packages/diagrams-demo-gallery/demos/demo-limit-points/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-limit-points/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-limit-points/index.tsx diff --git a/lib-demo-gallery/demos/demo-listeners/index.tsx b/packages/diagrams-demo-gallery/demos/demo-listeners/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-listeners/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-listeners/index.tsx diff --git a/lib-demo-gallery/demos/demo-locks/index.tsx b/packages/diagrams-demo-gallery/demos/demo-locks/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-locks/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-locks/index.tsx diff --git a/lib-demo-gallery/demos/demo-mutate-graph/index.tsx b/packages/diagrams-demo-gallery/demos/demo-mutate-graph/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-mutate-graph/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-mutate-graph/index.tsx diff --git a/lib-demo-gallery/demos/demo-performance/index.tsx b/packages/diagrams-demo-gallery/demos/demo-performance/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-performance/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-performance/index.tsx diff --git a/lib-demo-gallery/demos/demo-serializing/index.tsx b/packages/diagrams-demo-gallery/demos/demo-serializing/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-serializing/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-serializing/index.tsx diff --git a/lib-demo-gallery/demos/demo-simple-flow/index.tsx b/packages/diagrams-demo-gallery/demos/demo-simple-flow/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-simple-flow/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-simple-flow/index.tsx diff --git a/lib-demo-gallery/demos/demo-simple/index.tsx b/packages/diagrams-demo-gallery/demos/demo-simple/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-simple/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-simple/index.tsx diff --git a/lib-demo-gallery/demos/demo-smart-routing/index.tsx b/packages/diagrams-demo-gallery/demos/demo-smart-routing/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-smart-routing/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-smart-routing/index.tsx diff --git a/lib-demo-gallery/demos/demo-zoom-to-fit/index.tsx b/packages/diagrams-demo-gallery/demos/demo-zoom-to-fit/index.tsx similarity index 100% rename from lib-demo-gallery/demos/demo-zoom-to-fit/index.tsx rename to packages/diagrams-demo-gallery/demos/demo-zoom-to-fit/index.tsx diff --git a/lib-demo-gallery/demos/helpers/DemoWorkspaceWidget.tsx b/packages/diagrams-demo-gallery/demos/helpers/DemoWorkspaceWidget.tsx similarity index 100% rename from lib-demo-gallery/demos/helpers/DemoWorkspaceWidget.tsx rename to packages/diagrams-demo-gallery/demos/helpers/DemoWorkspaceWidget.tsx diff --git a/lib-demo-gallery/demos/helpers/Helper.tsx b/packages/diagrams-demo-gallery/demos/helpers/Helper.tsx similarity index 100% rename from lib-demo-gallery/demos/helpers/Helper.tsx rename to packages/diagrams-demo-gallery/demos/helpers/Helper.tsx diff --git a/lib-demo-gallery/demos/helpers/demo.scss b/packages/diagrams-demo-gallery/demos/helpers/demo.scss similarity index 100% rename from lib-demo-gallery/demos/helpers/demo.scss rename to packages/diagrams-demo-gallery/demos/helpers/demo.scss diff --git a/lib-demo-gallery/index.tsx b/packages/diagrams-demo-gallery/index.tsx similarity index 100% rename from lib-demo-gallery/index.tsx rename to packages/diagrams-demo-gallery/index.tsx diff --git a/lib-demo-gallery/jest-puppeteer.config.js b/packages/diagrams-demo-gallery/jest-puppeteer.config.js similarity index 100% rename from lib-demo-gallery/jest-puppeteer.config.js rename to packages/diagrams-demo-gallery/jest-puppeteer.config.js diff --git a/lib-demo-gallery/jest.config.js b/packages/diagrams-demo-gallery/jest.config.js similarity index 100% rename from lib-demo-gallery/jest.config.js rename to packages/diagrams-demo-gallery/jest.config.js diff --git a/lib-demo-gallery/package.json b/packages/diagrams-demo-gallery/package.json similarity index 61% rename from lib-demo-gallery/package.json rename to packages/diagrams-demo-gallery/package.json index 394232e..2e47b47 100644 --- a/lib-demo-gallery/package.json +++ b/packages/diagrams-demo-gallery/package.json @@ -8,10 +8,10 @@ "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", - "github": "../node_modules/.bin/storybook-to-ghpages", - "test:run": "../node_modules/.bin/jest --no-cache", + "start": "../../node_modules/.bin/start-storybook", + "storybook:build": "../../node_modules/.bin/build-storybook -c .storybook -o .out", + "github": "../../node_modules/.bin/storybook-to-ghpages", + "test:run": "../../node_modules/.bin/jest --no-cache", "test": "yarn build && yarn test:run" }, "keywords": [ diff --git a/lib-demo-gallery/postcss.config.js b/packages/diagrams-demo-gallery/postcss.config.js similarity index 100% rename from lib-demo-gallery/postcss.config.js rename to packages/diagrams-demo-gallery/postcss.config.js diff --git a/lib-demo-gallery/tests-e2e/helpers/E2EHelper.ts b/packages/diagrams-demo-gallery/tests-e2e/helpers/E2EHelper.ts similarity index 100% rename from lib-demo-gallery/tests-e2e/helpers/E2EHelper.ts rename to packages/diagrams-demo-gallery/tests-e2e/helpers/E2EHelper.ts diff --git a/lib-demo-gallery/tests-e2e/simple-flow.test.ts b/packages/diagrams-demo-gallery/tests-e2e/simple-flow.test.ts similarity index 100% rename from lib-demo-gallery/tests-e2e/simple-flow.test.ts rename to packages/diagrams-demo-gallery/tests-e2e/simple-flow.test.ts diff --git a/lib-demo-gallery/tests-e2e/simple.test.ts b/packages/diagrams-demo-gallery/tests-e2e/simple.test.ts similarity index 100% rename from lib-demo-gallery/tests-e2e/simple.test.ts rename to packages/diagrams-demo-gallery/tests-e2e/simple.test.ts diff --git a/lib-demo-gallery/tsconfig.json b/packages/diagrams-demo-gallery/tsconfig.json similarity index 52% rename from lib-demo-gallery/tsconfig.json rename to packages/diagrams-demo-gallery/tsconfig.json index 46594d0..ef3fbd9 100644 --- a/lib-demo-gallery/tsconfig.json +++ b/packages/diagrams-demo-gallery/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig", + "extends": "../../tsconfig", "include": [ "./demos" ] diff --git a/lib-demo-project/.babelrc b/packages/diagrams-demo-project/.babelrc similarity index 100% rename from lib-demo-project/.babelrc rename to packages/diagrams-demo-project/.babelrc diff --git a/lib-demo-project/README.md b/packages/diagrams-demo-project/README.md similarity index 100% rename from lib-demo-project/README.md rename to packages/diagrams-demo-project/README.md diff --git a/lib-demo-project/index.html b/packages/diagrams-demo-project/index.html similarity index 100% rename from lib-demo-project/index.html rename to packages/diagrams-demo-project/index.html diff --git a/lib-demo-project/package.json b/packages/diagrams-demo-project/package.json similarity index 91% rename from lib-demo-project/package.json rename to packages/diagrams-demo-project/package.json index d66018e..99f85b3 100644 --- a/lib-demo-project/package.json +++ b/packages/diagrams-demo-project/package.json @@ -8,7 +8,7 @@ "url": "https://github.com/projectstorm/react-diagrams.git" }, "scripts": { - "start": "../node_modules/.bin/webpack-dev-server" + "start": "../../node_modules/.bin/webpack-dev-server" }, "keywords": [ "web", diff --git a/lib-demo-project/screenshot.png b/packages/diagrams-demo-project/screenshot.png similarity index 100% rename from lib-demo-project/screenshot.png rename to packages/diagrams-demo-project/screenshot.png diff --git a/packages/diagrams-demo-project/src/BodyWidget.tsx b/packages/diagrams-demo-project/src/BodyWidget.tsx new file mode 100644 index 0000000..704063c --- /dev/null +++ b/packages/diagrams-demo-project/src/BodyWidget.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import { DiagramEngine } from '@projectstorm/react-diagrams'; +import {CanvasWidget} from "@projectstorm/react-canvas-core"; + +export interface BodyWidgetProps { + engine: DiagramEngine; +} + +export class BodyWidget extends React.Component { + render() { + return ; + } +} diff --git a/lib-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx b/packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx similarity index 86% rename from lib-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx rename to packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx index 2d5309d..edd59f1 100644 --- a/lib-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx +++ b/packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import { AbstractReactFactory } from '@projectstorm/react-diagrams'; import { JSCustomNodeModel } from './JSCustomNodeModel'; import { JSCustomNodeWidget } from './JSCustomNodeWidget'; +import {AbstractReactFactory} from "@projectstorm/react-canvas-core"; export class JSCustomNodeFactory extends AbstractReactFactory { constructor() { diff --git a/lib-demo-project/src/custom-node-js/JSCustomNodeModel.js b/packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeModel.js similarity index 100% rename from lib-demo-project/src/custom-node-js/JSCustomNodeModel.js rename to packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeModel.js diff --git a/lib-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx b/packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx similarity index 75% rename from lib-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx rename to packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx index ad597cb..671945f 100644 --- a/lib-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx +++ b/packages/diagrams-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx @@ -5,8 +5,12 @@ export class JSCustomNodeWidget extends React.Component { render() { return (
- - + +
+ + +
+
); diff --git a/lib-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx b/packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx similarity index 59% rename from lib-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx rename to packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx index 607c2ad..2b52fdc 100644 --- a/lib-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx +++ b/packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; -import { AbstractReactFactory } from '@projectstorm/react-diagrams'; import { TSCustomNodeModel } from './TSCustomNodeModel'; import { TSCustomNodeWidget } from './TSCustomNodeWidget'; +import {AbstractReactFactory} from "@projectstorm/react-canvas-core"; +import {DiagramEngine} from "@projectstorm/react-diagrams-core"; -export class TSCustomNodeFactory extends AbstractReactFactory { +export class TSCustomNodeFactory extends AbstractReactFactory { constructor() { super('ts-custom-node'); } @@ -13,6 +14,6 @@ export class TSCustomNodeFactory extends AbstractReactFactory } generateReactWidget(event): JSX.Element { - return ; + return ; } } diff --git a/lib-demo-project/src/custom-node-ts/TSCustomNodeModel.ts b/packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeModel.ts similarity index 81% rename from lib-demo-project/src/custom-node-ts/TSCustomNodeModel.ts rename to packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeModel.ts index 8833905..c54f343 100644 --- a/lib-demo-project/src/custom-node-ts/TSCustomNodeModel.ts +++ b/packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeModel.ts @@ -1,4 +1,5 @@ -import { DiagramEngine, NodeModel, DefaultPortModel, BaseModelOptions } from '@projectstorm/react-diagrams'; +import { DiagramEngine, NodeModel, DefaultPortModel } from '@projectstorm/react-diagrams'; +import {BaseModelOptions} from "@projectstorm/react-canvas-core"; export interface TSCustomNodeModelOptions extends BaseModelOptions { color?: string; diff --git a/lib-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx b/packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx similarity index 56% rename from lib-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx rename to packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx index 162043f..b7017d3 100644 --- a/lib-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx +++ b/packages/diagrams-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx @@ -1,13 +1,14 @@ import * as React from 'react'; -import { DiagramEngine, PortWidget } from '@projectstorm/react-diagrams-core'; -import { TSCustomNodeModel } from './TSCustomNodeModel'; +import {DiagramEngine, PortWidget} from '@projectstorm/react-diagrams-core'; +import {TSCustomNodeModel} from './TSCustomNodeModel'; export interface TSCustomNodeWidgetProps { node: TSCustomNodeModel; engine: DiagramEngine; } -export interface TSCustomNodeWidgetState {} +export interface TSCustomNodeWidgetState { +} export class TSCustomNodeWidget extends React.Component { constructor(props: TSCustomNodeWidgetProps) { @@ -18,9 +19,13 @@ export class TSCustomNodeWidget extends React.Component - - -
+ +
+ + +
+ +
); } diff --git a/lib-demo-project/src/main.css b/packages/diagrams-demo-project/src/main.css similarity index 74% rename from lib-demo-project/src/main.css rename to packages/diagrams-demo-project/src/main.css index fbbe9b5..1c67096 100644 --- a/lib-demo-project/src/main.css +++ b/packages/diagrams-demo-project/src/main.css @@ -34,3 +34,16 @@ html, body, #application{ transform: translate(-50%, -50%); border-radius: 10px; } + +.circle-port{ + width: 12px; + height: 12px; + margin: 2px; + border-radius: 4px; + background: darkgray; + cursor: pointer; +} + +.circle-port:hover{ + background: mediumpurple; +} diff --git a/lib-demo-project/src/main.tsx b/packages/diagrams-demo-project/src/main.tsx similarity index 97% rename from lib-demo-project/src/main.tsx rename to packages/diagrams-demo-project/src/main.tsx index 895e8df..f893801 100644 --- a/lib-demo-project/src/main.tsx +++ b/packages/diagrams-demo-project/src/main.tsx @@ -12,7 +12,7 @@ import { BodyWidget } from './BodyWidget'; const engine = createEngine(); // register the two engines -engine.getNodeFactories().registerFactory(new JSCustomNodeFactory()); +engine.getNodeFactories().registerFactory(new JSCustomNodeFactory() as any); engine.getNodeFactories().registerFactory(new TSCustomNodeFactory()); // create a diagram model @@ -36,7 +36,7 @@ model.addAll(node1, node2, link1); //#################################################### // install the model into the engine -engine.setDiagramModel(model); +engine.setModel(model); document.addEventListener('DOMContentLoaded', () => { ReactDOM.render(, document.querySelector('#application')); diff --git a/lib-demo-project/tsconfig.json b/packages/diagrams-demo-project/tsconfig.json similarity index 100% rename from lib-demo-project/tsconfig.json rename to packages/diagrams-demo-project/tsconfig.json diff --git a/lib-demo-project/webpack.config.js b/packages/diagrams-demo-project/webpack.config.js similarity index 100% rename from lib-demo-project/webpack.config.js rename to packages/diagrams-demo-project/webpack.config.js diff --git a/lib-all/.npmignore b/packages/geometry/.npmignore similarity index 100% rename from lib-all/.npmignore rename to packages/geometry/.npmignore diff --git a/lib-geometry/index.ts b/packages/geometry/index.ts similarity index 100% rename from lib-geometry/index.ts rename to packages/geometry/index.ts diff --git a/lib-geometry/package.json b/packages/geometry/package.json similarity index 77% rename from lib-geometry/package.json rename to packages/geometry/package.json index 560de6f..52d6514 100644 --- a/lib-geometry/package.json +++ b/packages/geometry/package.json @@ -1,5 +1,5 @@ { - "name": "@projectstorm/react-diagrams-geometry", + "name": "@projectstorm/geometry", "version": "6.0.0-alpha.4.2", "author": "dylanvorster", "repository": { @@ -8,8 +8,8 @@ }, "scripts": { "clean": "rm -rf ./dist", - "build": "../node_modules/.bin/webpack", - "build:prod": "NODE_ENV=production ../node_modules/.bin/webpack" + "build": "../../node_modules/.bin/webpack", + "build:prod": "NODE_ENV=production ../../node_modules/.bin/webpack" }, "publishConfig": { "access": "public" diff --git a/lib-geometry/src/BezierCurve.ts b/packages/geometry/src/BezierCurve.ts similarity index 100% rename from lib-geometry/src/BezierCurve.ts rename to packages/geometry/src/BezierCurve.ts diff --git a/lib-geometry/src/Point.ts b/packages/geometry/src/Point.ts similarity index 100% rename from lib-geometry/src/Point.ts rename to packages/geometry/src/Point.ts diff --git a/lib-geometry/src/Polygon.ts b/packages/geometry/src/Polygon.ts similarity index 100% rename from lib-geometry/src/Polygon.ts rename to packages/geometry/src/Polygon.ts diff --git a/lib-geometry/src/Rectangle.ts b/packages/geometry/src/Rectangle.ts similarity index 100% rename from lib-geometry/src/Rectangle.ts rename to packages/geometry/src/Rectangle.ts diff --git a/lib-core/tsconfig.json b/packages/geometry/tsconfig.json similarity index 82% rename from lib-core/tsconfig.json rename to packages/geometry/tsconfig.json index c46812c..cf8e294 100644 --- a/lib-core/tsconfig.json +++ b/packages/geometry/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig", + "extends": "../../tsconfig", "compilerOptions": { "declaration": true, "declarationDir": "dist/@types" diff --git a/lib-geometry/webpack.config.js b/packages/geometry/webpack.config.js similarity index 66% rename from lib-geometry/webpack.config.js rename to packages/geometry/webpack.config.js index 834eb6a..146e30e 100644 --- a/lib-geometry/webpack.config.js +++ b/packages/geometry/webpack.config.js @@ -1,4 +1,4 @@ -const config = require('../webpack.shared')(__dirname); +const config = require('../../webpack.shared')(__dirname); module.exports = { ...config, output: { diff --git a/lib-core/.npmignore b/packages/react-canvas-core/.npmignore similarity index 100% rename from lib-core/.npmignore rename to packages/react-canvas-core/.npmignore diff --git a/packages/react-canvas-core/index.ts b/packages/react-canvas-core/index.ts new file mode 100644 index 0000000..42852ea --- /dev/null +++ b/packages/react-canvas-core/index.ts @@ -0,0 +1,21 @@ +export * from "./src/CanvasEngine" +export * from "./src/Toolkit" +export * from "./src/entities/canvas/CanvasModel" + +export * from "./src/core/AbstractFactory" +export * from "./src/core/AbstractModelFactory" +export * from "./src/core/AbstractReactFactory" +export * from "./src/core/BaseObserver" +export * from "./src/core/FactoryBank" + +export * from "./src/core-models/BaseEntity" +export * from "./src/core-models/BaseModel" +export * from "./src/core-models/BasePositionModel" + +export * from "./src/entities/canvas/CanvasModel" +export * from "./src/entities/canvas/CanvasWidget" + +export * from "./src/entities/layer/LayerModel" + +export * from "./src/widgets/PeformanceWidget" +export * from "./src/entities/layer/TransformLayerWidget" diff --git a/packages/react-canvas-core/package.json b/packages/react-canvas-core/package.json new file mode 100644 index 0000000..74772b3 --- /dev/null +++ b/packages/react-canvas-core/package.json @@ -0,0 +1,39 @@ +{ + "name": "@projectstorm/react-canvas-core", + "version": "6.0.0-alpha.4.2", + "author": "dylanvorster", + "repository": { + "type": "git", + "url": "https://github.com/projectstorm/react-diagrams.git" + }, + "scripts": { + "clean": "rm -rf ./dist", + "build": "../../node_modules/.bin/webpack", + "build:prod": "NODE_ENV=production ../../node_modules/.bin/webpack" + }, + "publishConfig": { + "access": "public" + }, + "keywords": [ + "web", + "diagram", + "diagrams", + "react", + "typescript", + "flowchart", + "simple", + "links", + "nodes" + ], + "main": "./dist/index.js", + "typings": "./dist/@types/index", + "dependencies": { + "@projectstorm/geometry": "^6.0.0-alpha.4.2" + }, + "peerDependencies": { + "closest": "^0.0.1", + "lodash": "4.*", + "react": "16.*" + }, + "gitHead": "bb878657ba0c2f81764f32901fd96158a0f8352e" +} diff --git a/packages/react-canvas-core/src/CanvasEngine.ts b/packages/react-canvas-core/src/CanvasEngine.ts new file mode 100644 index 0000000..c32d340 --- /dev/null +++ b/packages/react-canvas-core/src/CanvasEngine.ts @@ -0,0 +1,120 @@ +import {CanvasModel} from "./entities/canvas/CanvasModel"; +import {FactoryBank} from "./core/FactoryBank"; +import {AbstractReactFactory} from "./core/AbstractReactFactory"; +import {LayerModel} from "./entities/layer/LayerModel"; +import {BaseListener, BaseObserver} from "./core/BaseObserver"; +import {MouseEvent} from "react"; +import {BaseModel} from "./core-models/BaseModel"; +import {Point} from "@projectstorm/geometry"; +import {ActionEventBus} from "./core-actions/ActionEventBus"; +import {ZoomCanvasAction} from "./actions/ZoomCanvasAction"; +import {DeleteItemsAction} from "./actions/DeleteItemsAction"; + +export interface CanvasEngineListener extends BaseListener { + canvasReady?(): void; + + repaintCanvas?(): void; + + rendered?(): void; +} + +export class CanvasEngine extends BaseObserver { + + protected model: M; + protected layerFactories: FactoryBank>; + protected canvas: HTMLDivElement; + protected eventBus: ActionEventBus; + + constructor() { + super(); + this.model = null; + this.eventBus = new ActionEventBus(this); + this.layerFactories = new FactoryBank(); + + this.registerFactoryBank(this.layerFactories); + this.eventBus.registerAction(new ZoomCanvasAction()); + this.eventBus.registerAction(new DeleteItemsAction()); + } + + getRelativeMousePoint(event): Point { + var point = this.getRelativePoint(event.clientX, event.clientY); + return new Point( + (point.x - this.model.getOffsetX()) / (this.model.getZoomLevel() / 100.0), + (point.y - this.model.getOffsetY()) / (this.model.getZoomLevel() / 100.0) + ); + } + + getRelativePoint(x, y): Point { + var canvasRect = this.canvas.getBoundingClientRect(); + return new Point(x - canvasRect.left, y - canvasRect.top); + } + + registerFactoryBank(factory: FactoryBank) { + factory.registerListener({ + factoryAdded: event => { + event.factory.setDiagramEngine(this); + }, + factoryRemoved: event => { + event.factory.setDiagramEngine(null); + } + }); + } + + getActionEventBus() { + return this.eventBus; + } + + getLayerFactories() { + return this.layerFactories; + } + + getFactoryForLayer>(layer: LayerModel) { + if (typeof layer === 'string') { + return this.layerFactories.getFactory(layer); + } + return this.layerFactories.getFactory(layer.getType()); + } + + setModel(model: M) { + this.model = model; + } + + getModel(): M { + return this.model; + } + + repaintCanvas() { + this.iterateListeners(listener => { + if (listener.repaintCanvas) { + listener.repaintCanvas(); + } + }); + } + + setCanvas(canvas?: HTMLDivElement) { + if (this.canvas !== canvas) { + this.canvas = canvas; + if (canvas) { + this.fireEvent({}, 'canvasReady'); + } + } + } + + getCanvas(){ + return this.canvas; + } + + getMouseElement(event: MouseEvent): { model: BaseModel; element: Element } { + return null; + } + + zoomToFit() { + const xFactor = this.canvas.clientWidth / this.canvas.scrollWidth; + const yFactor = this.canvas.clientHeight / this.canvas.scrollHeight; + const zoomFactor = xFactor < yFactor ? xFactor : yFactor; + + this.model.setZoomLevel(this.model.getZoomLevel() * zoomFactor); + this.model.setOffset(0, 0); + this.repaintCanvas(); + } +} diff --git a/lib-core/src/Toolkit.ts b/packages/react-canvas-core/src/Toolkit.ts similarity index 69% rename from lib-core/src/Toolkit.ts rename to packages/react-canvas-core/src/Toolkit.ts index 8ca00a1..4ccc1cc 100644 --- a/lib-core/src/Toolkit.ts +++ b/packages/react-canvas-core/src/Toolkit.ts @@ -1,5 +1,4 @@ import * as closest from 'closest'; -import { PointModel } from './models/PointModel'; export class Toolkit { static TESTING: boolean = false; @@ -23,9 +22,6 @@ export class Toolkit { /** * Finds the closest element as a polyfill - * - * @param {Element} element [description] - * @param {string} selector [description] */ public static closest(element: Element, selector: string) { if (document.body.closest) { @@ -33,8 +29,4 @@ export class Toolkit { } return closest(element, selector); } - - public static generateLinePath(firstPoint: PointModel, lastPoint: PointModel): string { - return `M${firstPoint.getX()},${firstPoint.getY()} L ${lastPoint.getX()},${lastPoint.getY()}`; - } } diff --git a/packages/react-canvas-core/src/actions/DeleteItemsAction.ts b/packages/react-canvas-core/src/actions/DeleteItemsAction.ts new file mode 100644 index 0000000..2f90606 --- /dev/null +++ b/packages/react-canvas-core/src/actions/DeleteItemsAction.ts @@ -0,0 +1,34 @@ +import {Action, InputType} from "../core-actions/Action"; +import {KeyboardEvent} from "react"; +import * as _ from "lodash"; + +export interface DeleteItemsActionOptions { + keyCodes?: number[]; +} + +/** + * Deletes all selected items + */ +export class DeleteItemsAction extends Action{ + + constructor(options:DeleteItemsActionOptions = {}){ + options = { + keyCodes:[46, 8], + ...options + }; + super({ + type: InputType.KEY_DOWN, + fire:(event: KeyboardEvent) => { + if(options.keyCodes.indexOf(event.keyCode) !== -1) { + _.forEach(this.engine.getModel().getSelectedItems(), model => { + // only delete items which are not locked + if(!model.isLocked){ + model.remove(); + } + }); + this.engine.repaintCanvas(); + } + } + }) + } +} diff --git a/packages/react-canvas-core/src/actions/ZoomCanvasAction.ts b/packages/react-canvas-core/src/actions/ZoomCanvasAction.ts new file mode 100644 index 0000000..22fab82 --- /dev/null +++ b/packages/react-canvas-core/src/actions/ZoomCanvasAction.ts @@ -0,0 +1,57 @@ +import {WheelEvent} from 'react'; +import {Action, InputType} from "../core-actions/Action"; + +export interface ZoomCanvasActionOptions { + inverseZoom?: boolean; +} + +export class ZoomCanvasAction extends Action { + + constructor(options: ZoomCanvasActionOptions = {}){ + super({ + type: InputType.MOUSE_WHEEL, + fire:(event: WheelEvent) => { + const model = this.engine.getModel(); + event.stopPropagation(); + const oldZoomFactor = this.engine.getModel().getZoomLevel() / 100; + let scrollDelta = options.inverseZoom ? -event.deltaY : event.deltaY; + //check if it is pinch gesture + if (event.ctrlKey && scrollDelta % 1 !== 0) { + /* + Chrome and Firefox sends wheel event with deltaY that + have fractional part, also `ctrlKey` prop of the event is true + though ctrl isn't pressed + */ + scrollDelta /= 3; + } else { + scrollDelta /= 60; + } + if (model.getZoomLevel() + scrollDelta > 10) { + model.setZoomLevel(model.getZoomLevel() + scrollDelta); + } + + const zoomFactor = model.getZoomLevel() / 100; + + const boundingRect = event.currentTarget.getBoundingClientRect(); + const clientWidth = boundingRect.width; + const clientHeight = boundingRect.height; + // compute difference between rect before and after scroll + const widthDiff = clientWidth * zoomFactor - clientWidth * oldZoomFactor; + const heightDiff = clientHeight * zoomFactor - clientHeight * oldZoomFactor; + // compute mouse coords relative to canvas + const clientX = event.clientX - boundingRect.left; + const clientY = event.clientY - boundingRect.top; + + // compute width and height increment factor + const xFactor = (clientX - model.getOffsetX()) / oldZoomFactor / clientWidth; + const yFactor = (clientY - model.getOffsetY()) / oldZoomFactor / clientHeight; + + model.setOffset( + model.getOffsetX() - widthDiff * xFactor, + model.getOffsetY() - heightDiff * yFactor + ); + this.engine.repaintCanvas(); + } + }); + } +} diff --git a/packages/react-canvas-core/src/core-actions/Action.ts b/packages/react-canvas-core/src/core-actions/Action.ts new file mode 100644 index 0000000..35fed3a --- /dev/null +++ b/packages/react-canvas-core/src/core-actions/Action.ts @@ -0,0 +1,43 @@ +import {MouseEvent, KeyboardEvent, WheelEvent} from 'react'; +import {Toolkit} from "../Toolkit"; +import {CanvasEngine} from "../CanvasEngine"; + +export enum InputType { + MOUSE_DOWN = 'mouse-down', + MOUSE_UP = 'mouse-up', + MOUSE_MOVE = 'mouse-move', + MOUSE_WHEEL = 'mouse-wheel', + KEY_DOWN = 'key-down', + KEY_UP = 'key-up', +} + +export interface Mapping { + [InputType.MOUSE_DOWN]: MouseEvent; + [InputType.MOUSE_UP]: MouseEvent; + [InputType.MOUSE_MOVE]: MouseEvent; + [InputType.MOUSE_WHEEL]: WheelEvent; + [InputType.KEY_DOWN]: KeyboardEvent; + [InputType.KEY_UP]: KeyboardEvent; +} + +export interface ActionOptions { + type: InputType; + fire(event: Mapping[this['type']]); +} + +export class Action { + + options: ActionOptions; + id: string; + engine: T; + + constructor(options: ActionOptions){ + this.options = options; + this.id = Toolkit.UID(); + } + + setEngine(engine: T){ + this.engine = engine; + } + +} diff --git a/packages/react-canvas-core/src/core-actions/ActionEventBus.ts b/packages/react-canvas-core/src/core-actions/ActionEventBus.ts new file mode 100644 index 0000000..24761f4 --- /dev/null +++ b/packages/react-canvas-core/src/core-actions/ActionEventBus.ts @@ -0,0 +1,59 @@ +import {Action, InputType} from "./Action"; +import {SyntheticEvent} from "react"; +import * as _ from "lodash"; +import {CanvasEngine} from "../CanvasEngine"; + +export class ActionEventBus { + + protected actions: { [id: string]: Action }; + protected engine: CanvasEngine; + + constructor(engine: CanvasEngine) { + this.actions = {}; + this.engine = engine; + } + + registerAction(action: Action) { + action.setEngine(this.engine); + this.actions[action.id] = action; + } + + deregisterAction(action: Action) { + action.setEngine(null); + delete this.actions[action.id]; + } + + getActionsForType(type: InputType): Action[] { + return _.filter(this.actions, (action) => { + return action.options.type === type; + }); + } + + getActionsForEvent(event: SyntheticEvent): Action[] { + if (event.type === 'mousedown') { + return this.getActionsForType(InputType.MOUSE_DOWN) + } else if (event.type === 'mouseup') { + return this.getActionsForType(InputType.MOUSE_UP) + } + else if (event.type === 'keydown') { + return this.getActionsForType(InputType.KEY_DOWN) + } + else if (event.type === 'keyup') { + return this.getActionsForType(InputType.KEY_UP) + } + else if (event.type === 'mousemove') { + return this.getActionsForType(InputType.MOUSE_MOVE) + } + else if (event.type === 'wheel') { + return this.getActionsForType(InputType.MOUSE_WHEEL) + } + return []; + } + + fireAction(event: SyntheticEvent){ + const actions = this.getActionsForEvent(event); + for(let action of actions){ + action.options.fire(event as any) + } + } +} diff --git a/lib-core/src/core-models/BaseEntity.ts b/packages/react-canvas-core/src/core-models/BaseEntity.ts similarity index 92% rename from lib-core/src/core-models/BaseEntity.ts rename to packages/react-canvas-core/src/core-models/BaseEntity.ts index 491fbf5..0fa85b1 100644 --- a/lib-core/src/core-models/BaseEntity.ts +++ b/packages/react-canvas-core/src/core-models/BaseEntity.ts @@ -1,6 +1,6 @@ import { Toolkit } from '../Toolkit'; import * as _ from 'lodash'; -import { DiagramEngine } from '../DiagramEngine'; +import { CanvasEngine } from '../CanvasEngine'; import { BaseEvent, BaseListener, BaseObserver } from '../core/BaseObserver'; export interface BaseEntityEvent extends BaseEvent { @@ -67,7 +67,7 @@ export class BaseEntity exten this.listeners = {}; } - deSerialize(data: ReturnType, engine: DiagramEngine) { + deSerialize(data: ReturnType, engine: CanvasEngine) { this.options.id = data.id; this.options.locked = data.locked; } @@ -90,7 +90,7 @@ export class BaseEntity exten } public isLocked(): boolean { - return this.options.locked; + return this.options.locked; } public setLocked(locked: boolean = true) { diff --git a/lib-core/src/core-models/BaseModel.ts b/packages/react-canvas-core/src/core-models/BaseModel.ts similarity index 82% rename from lib-core/src/core-models/BaseModel.ts rename to packages/react-canvas-core/src/core-models/BaseModel.ts index ce52aa3..70b0704 100644 --- a/lib-core/src/core-models/BaseModel.ts +++ b/packages/react-canvas-core/src/core-models/BaseModel.ts @@ -1,5 +1,5 @@ import { BaseEntity, BaseEntityEvent, BaseEntityGenerics, BaseEntityListener, BaseEntityOptions } from './BaseEntity'; -import { DiagramEngine } from '../DiagramEngine'; +import { CanvasEngine } from '../CanvasEngine'; export interface BaseModelListener extends BaseEntityListener { selectionChanged?(event: BaseEntityEvent & { isSelected: boolean }): void; @@ -41,6 +41,8 @@ export class BaseModel extends return []; } + + serialize() { return { ...super.serialize(), @@ -50,7 +52,7 @@ export class BaseModel extends }; } - deSerialize(data: ReturnType, engine: DiagramEngine) { + deSerialize(data: ReturnType, engine: CanvasEngine) { super.deSerialize(data, engine); this.options.extras = data.extras; this.options.selected = data.selected; @@ -64,6 +66,19 @@ export class BaseModel extends return this.options.selected; } + isLocked(): boolean { + const locked = super.isLocked(); + if(locked){ + return true; + } + + // delegate this call up to the parent + if(this.parent){ + return this.parent.isLocked(); + } + return false; + } + setSelected(selected: boolean = true) { this.options.selected = selected; diff --git a/lib-core/src/core-models/BasePositionModel.ts b/packages/react-canvas-core/src/core-models/BasePositionModel.ts similarity index 89% rename from lib-core/src/core-models/BasePositionModel.ts rename to packages/react-canvas-core/src/core-models/BasePositionModel.ts index 9997681..9899760 100644 --- a/lib-core/src/core-models/BasePositionModel.ts +++ b/packages/react-canvas-core/src/core-models/BasePositionModel.ts @@ -1,7 +1,7 @@ import { BaseModel, BaseModelGenerics, BaseModelListener, BaseModelOptions } from './BaseModel'; -import { DiagramEngine } from '../DiagramEngine'; +import { CanvasEngine } from '../CanvasEngine'; import { BaseEntityEvent } from './BaseEntity'; -import { Point } from '@projectstorm/react-diagrams-geometry'; +import { Point } from '@projectstorm/geometry'; export interface BasePositionModelListener extends BaseModelListener { positionChanged?(event: BaseEntityEvent): void; @@ -35,7 +35,7 @@ export class BasePositionModel { +export abstract class AbstractFactory { /** * Couples the factory with the models it generates */ @@ -13,14 +13,14 @@ export abstract class AbstractFactory { /** * The engine gets injected when the factory is registered */ - protected engine: DiagramEngine; + protected engine: E; protected bank: FactoryBank; constructor(type: string) { this.type = type; } - setDiagramEngine(engine: DiagramEngine) { + setDiagramEngine(engine: E) { this.engine = engine; } diff --git a/packages/react-canvas-core/src/core/AbstractModelFactory.ts b/packages/react-canvas-core/src/core/AbstractModelFactory.ts new file mode 100644 index 0000000..0490beb --- /dev/null +++ b/packages/react-canvas-core/src/core/AbstractModelFactory.ts @@ -0,0 +1,14 @@ +import {AbstractFactory} from './AbstractFactory'; +import {BaseModel} from '../core-models/BaseModel'; +import {CanvasEngine} from "../CanvasEngine"; + +export interface GenerateModelEvent { + initialConfig?: any; +} + +export abstract class AbstractModelFactory extends AbstractFactory { + /** + * Generates new models (the core factory pattern) + */ + abstract generateModel(event: GenerateModelEvent): T; +} diff --git a/lib-core/src/core/AbstractReactFactory.tsx b/packages/react-canvas-core/src/core/AbstractReactFactory.tsx similarity index 60% rename from lib-core/src/core/AbstractReactFactory.tsx rename to packages/react-canvas-core/src/core/AbstractReactFactory.tsx index f54464a..82b6b73 100644 --- a/lib-core/src/core/AbstractReactFactory.tsx +++ b/packages/react-canvas-core/src/core/AbstractReactFactory.tsx @@ -1,5 +1,6 @@ -import { BaseModel } from '../core-models/BaseModel'; -import { AbstractModelFactory } from './AbstractModelFactory'; +import {BaseModel} from '../core-models/BaseModel'; +import {AbstractModelFactory} from './AbstractModelFactory'; +import {CanvasEngine} from "../CanvasEngine"; export interface GenerateWidgetEvent { model: T; @@ -8,7 +9,7 @@ export interface GenerateWidgetEvent { /** * Further extends the AbstractFactory to add widget generation capability. */ -export abstract class AbstractReactFactory extends AbstractModelFactory { +export abstract class AbstractReactFactory extends AbstractModelFactory { /** * Generates React widgets from the model contained in the event object */ diff --git a/lib-core/src/core/BaseObserver.ts b/packages/react-canvas-core/src/core/BaseObserver.ts similarity index 98% rename from lib-core/src/core/BaseObserver.ts rename to packages/react-canvas-core/src/core/BaseObserver.ts index f4da3ef..2917624 100644 --- a/lib-core/src/core/BaseObserver.ts +++ b/packages/react-canvas-core/src/core/BaseObserver.ts @@ -1,5 +1,4 @@ import { Toolkit } from '../Toolkit'; -import { FactoryBankListener } from './FactoryBank'; export interface BaseEvent { firing: boolean; diff --git a/lib-core/src/core/FactoryBank.ts b/packages/react-canvas-core/src/core/FactoryBank.ts similarity index 67% rename from lib-core/src/core/FactoryBank.ts rename to packages/react-canvas-core/src/core/FactoryBank.ts index f4e9dac..09d5734 100644 --- a/lib-core/src/core/FactoryBank.ts +++ b/packages/react-canvas-core/src/core/FactoryBank.ts @@ -1,25 +1,24 @@ -import { BaseEvent, BaseListener, BaseObserver } from './BaseObserver'; -import { AbstractFactory } from './AbstractFactory'; +import {BaseEvent, BaseListener, BaseObserver} from './BaseObserver'; +import {AbstractFactory} from './AbstractFactory'; import * as _ from 'lodash'; export interface FactoryBankListener extends BaseListener { /** * Factory as added to rhe bank */ - factoryAdded?: (event: BaseEvent & { factory: AbstractFactory }) => any; + factoryAdded?: (event: BaseEvent & { factory: F }) => any; /** * Factory was removed from the bank */ - factoryRemoved?: (event: BaseEvent & { factory: AbstractFactory }) => any; + factoryRemoved?: (event: BaseEvent & { factory: F }) => any; } -type Param = Parameters[0]; /** * Store and managed Factories that extend from Abstractfactory */ -export class FactoryBank extends BaseObserver> { +export class FactoryBank = FactoryBankListener> extends BaseObserver { protected factories: { [type: string]: F }; constructor() { @@ -47,13 +46,15 @@ export class FactoryBank extends Ba registerFactory(factory: F) { factory.setFactoryBank(this); this.factories[factory.getType()] = factory; - this.fireEvent<'factoryAdded'>({ factory }, 'factoryAdded'); + // todo fixme + this.fireEvent<'factoryAdded'>({factory} as any, 'factoryAdded'); } deregisterFactory(type: string) { const factory = this.factories[type]; factory.setFactoryBank(null); delete this.factories[type]; - this.fireEvent<'factoryRemoved'>({ factory }, 'factoryRemoved'); + // todo fixme + this.fireEvent<'factoryRemoved'>({factory} as any, 'factoryRemoved'); } } diff --git a/packages/react-canvas-core/src/entities/canvas/CanvasModel.ts b/packages/react-canvas-core/src/entities/canvas/CanvasModel.ts new file mode 100644 index 0000000..c444af1 --- /dev/null +++ b/packages/react-canvas-core/src/entities/canvas/CanvasModel.ts @@ -0,0 +1,141 @@ +import {CanvasEngine} from "../../CanvasEngine"; +import * as _ from "lodash"; +import { + BaseEntity, + BaseEntityEvent, + BaseEntityGenerics, + BaseEntityListener, + BaseEntityOptions +} from "../../core-models/BaseEntity"; +import {LayerModel} from "../layer/LayerModel"; +import {BaseModel} from "../../core-models/BaseModel"; + +export interface DiagramListener extends BaseEntityListener { + + offsetUpdated?(event: BaseEntityEvent & { offsetX: number; offsetY: number }): void; + + zoomUpdated?(event: BaseEntityEvent & { zoom: number }): void; + + gridUpdated?(event: BaseEntityEvent & { size: number }): void; +} + +export interface DiagramModelOptions extends BaseEntityOptions { + offsetX?: number; + offsetY?: number; + zoom?: number; + gridSize?: number; +} + +export interface CanvasModelGenerics extends BaseEntityGenerics { + LISTENER: DiagramListener; + OPTIONS: DiagramModelOptions; + LAYER: LayerModel; +} + +export class CanvasModel extends BaseEntity { + + protected layers: G['LAYER'][]; + + constructor(options: G['OPTIONS'] = {}) { + super({ + zoom: 100, + gridSize: 0, + offsetX: 0, + offsetY: 0, + ...options + }); + this.layers = []; + } + + getSelectedItems(): BaseModel[]{ + return _.flatMap(this.layers, (layer) => { + return layer.getSelectedEntities(); + }) + } + + clearSelection(ignore: BaseModel | null = null) { + _.forEach(this.getSelectedItems(), element => { + if (ignore && ignore.getID() === element.getID()) { + return; + } + element.setSelected(false); + }); + } + + getModels(): BaseModel[]{ + return _.flatMap(this.layers, (layer) => { + return _.values(layer.getModels()); + }); + } + + addLayer(layer: LayerModel){ + layer.setParent(this); + this.layers.push(layer); + } + + getLayers(){ + return this.layers; + } + + setGridSize(size: number = 0) { + this.options.gridSize = size; + this.fireEvent({ size: size }, 'gridUpdated'); + } + + getGridPosition(pos) { + if (this.options.gridSize === 0) { + return pos; + } + return this.options.gridSize * Math.floor((pos + this.options.gridSize / 2) / this.options.gridSize); + } + + deSerializeDiagram(object: any, diagramEngine: CanvasEngine) { + this.deSerialize(object, diagramEngine); + + this.options.offsetX = object.offsetX; + this.options.offsetY = object.offsetY; + this.options.zoom = object.zoom; + this.options.gridSize = object.gridSize; + } + + serializeDiagram() { + return { + ...this.serialize(), + offsetX: this.options.offsetX, + offsetY: this.options.offsetY, + zoom: this.options.zoom, + gridSize: this.options.gridSize + }; + } + + setZoomLevel(zoom: number) { + this.options.zoom = zoom; + this.fireEvent({ zoom }, 'zoomUpdated'); + } + + setOffset(offsetX: number, offsetY: number) { + this.options.offsetX = offsetX; + this.options.offsetY = offsetY; + this.fireEvent({ offsetX, offsetY }, 'offsetUpdated'); + } + + setOffsetX(offsetX: number) { + this.setOffset(offsetX, this.options.offsetY); + } + + setOffsetY(offsetY: number) { + this.setOffset(this.options.offsetX, offsetY); + } + + getOffsetY() { + return this.options.offsetY; + } + + getOffsetX() { + return this.options.offsetX; + } + + getZoomLevel() { + return this.options.zoom; + } +} diff --git a/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx b/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx new file mode 100644 index 0000000..2d4cf38 --- /dev/null +++ b/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx @@ -0,0 +1,106 @@ +import * as React from 'react'; +import {CanvasEngine} from "../../CanvasEngine"; +import {TransformLayerWidget} from "../layer/TransformLayerWidget"; +import styled from "@emotion/styled"; + +export interface DiagramProps extends React.Component { + engine: CanvasEngine; + className?: string; +} + +namespace S{ + export const Canvas = styled.div` + position: relative; + cursor: move; + overflow: hidden; + ` +} + +export class CanvasWidget extends React.Component { + ref: React.RefObject; + keyUp: any; + keyDown: any; + canvasListener: any; + + constructor(props: DiagramProps) { + super(props); + + this.ref = React.createRef(); + this.state = { + action: null, + diagramEngineListener: null + }; + } + + componentWillUnmount() { + this.props.engine.deregisterListener(this.canvasListener); + this.props.engine.setCanvas(null); + + document.removeEventListener('keyup', this.keyUp); + document.removeEventListener('keydown', this.keyDown); + } + + registerCanvas() { + this.props.engine.setCanvas(this.ref.current); + this.props.engine.iterateListeners(list => { + list.rendered && list.rendered(); + }); + } + + componentDidUpdate() { + this.registerCanvas(); + } + + componentDidMount() { + this.canvasListener = this.props.engine.registerListener({ + repaintCanvas: () => { + this.forceUpdate(); + } + }); + + this.keyDown = (event) => { + this.props.engine.getActionEventBus().fireAction(event); + }; + this.keyUp = (event) => { + this.props.engine.getActionEventBus().fireAction(event); + }; + + document.addEventListener('keyup', this.keyUp); + document.addEventListener('keydown', this.keyDown); + this.registerCanvas(); + } + + render() { + const engine = this.props.engine; + const model = engine.getModel(); + + return ( + { + this.props.engine.getActionEventBus().fireAction(event); + }} + onMouseDown={event => { + this.props.engine.getActionEventBus().fireAction(event); + }} + onMouseUp={event => { + this.props.engine.getActionEventBus().fireAction(event); + }} + onMouseMove={event => { + this.props.engine.getActionEventBus().fireAction(event); + }} + > + { + model.getLayers().map((layer) => { + return ( + + {engine.getFactoryForLayer(layer).generateReactWidget({model: layer})} + + ) + }) + } + + ); + } +} diff --git a/packages/react-canvas-core/src/entities/layer/LayerModel.ts b/packages/react-canvas-core/src/entities/layer/LayerModel.ts new file mode 100644 index 0000000..d30f594 --- /dev/null +++ b/packages/react-canvas-core/src/entities/layer/LayerModel.ts @@ -0,0 +1,49 @@ +import {BaseModel, BaseModelGenerics, BaseModelOptions} from "../../core-models/BaseModel"; +import {CanvasModel} from "../canvas/CanvasModel"; + +export interface LayerModelOptions extends BaseModelOptions { + isSvg?: boolean; + transformed?: boolean; +} + +export interface LayerModelGenerics extends BaseModelGenerics { + OPTIONS: LayerModelOptions; + PARENT: CanvasModel; + CHILDREN: BaseModel; +} + +export class LayerModel extends BaseModel{ + + protected models: {[id: string]:G['CHILDREN']}; + + constructor(options:G['OPTIONS'] = {}){ + super(options); + this.models = {}; + } + + addModel(model: G['CHILDREN']){ + model.setParent(this); + this.models[model.getID()] = model; + } + + getModels(){ + return this.models; + } + + getModel(id: string){ + return this.models[id]; + } + + removeModel(id: string | G['CHILDREN']): boolean{ + const _id = typeof id === 'string' ? id : id.getID(); + if(this.models[_id]){ + delete this.models[_id]; + return true; + } + return false; + } + + getSelectedEntities(): Array { + return super.getSelectedEntities(); + } +} diff --git a/packages/react-canvas-core/src/entities/layer/TransformLayerWidget.tsx b/packages/react-canvas-core/src/entities/layer/TransformLayerWidget.tsx new file mode 100644 index 0000000..16ef20f --- /dev/null +++ b/packages/react-canvas-core/src/entities/layer/TransformLayerWidget.tsx @@ -0,0 +1,75 @@ +import * as React from "react"; +import styled from "@emotion/styled"; +import {css} from "@emotion/core"; +import {CSSProperties} from "react"; +import {LayerModel} from "./LayerModel"; + +export interface TransformLayerWidgetProps { + layer: LayerModel; +} + +namespace S { + const shared = css` + top: 0; + left: 0; + right: 0; + bottom: 0; + position: absolute; + pointer-events: none; + transform-origin: 0 0; + width: 100%; + height: 100%; + `; + + export const DivLayer = styled.div` + ${shared} + `; + + export const SvgLayer = styled.svg` + ${shared} + `; +} + +export class TransformLayerWidget extends React.Component { + + constructor(props: TransformLayerWidgetProps) { + super(props); + this.state = {} + } + + getTransform() { + const model = this.props.layer.getParent(); + return ` + translate( + ${model.getOffsetX()}px, + ${model.getOffsetY()}px) + scale( + ${model.getZoomLevel() / 100.0} + ) + ` + } + + getTransformStyle(): CSSProperties { + if (this.props.layer.getOptions().transformed) { + return { + 'transform': this.getTransform() + } + } + return {}; + } + + render() { + if (this.props.layer.getOptions().isSvg) { + return ( + + {this.props.children} + + ) + } + return ( + + {this.props.children} + + ); + } +} diff --git a/packages/react-canvas-core/src/entities/selection/SelectionBoxWidget.tsx b/packages/react-canvas-core/src/entities/selection/SelectionBoxWidget.tsx new file mode 100644 index 0000000..1860748 --- /dev/null +++ b/packages/react-canvas-core/src/entities/selection/SelectionBoxWidget.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import styled from "@emotion/styled"; + +export interface SelectionBoxWidgetProps { + rect: ClientRect; +} + + +namespace S { + export const Container = styled.div` + position: absolute; + background-color: rgba(0, 192, 255, 0.2); + border: solid 2px rgb(0, 192, 255); + `; +} + +export class SelectionBoxWidget extends React.Component { + + render() { + const {rect} = this.props; + return ( + + ); + } +} diff --git a/lib-all/README.md b/packages/react-canvas-core/src/entities/selection/SelectionModel.ts similarity index 100% rename from lib-all/README.md rename to packages/react-canvas-core/src/entities/selection/SelectionModel.ts diff --git a/lib-core/src/widgets/PeformanceWidget.tsx b/packages/react-canvas-core/src/widgets/PeformanceWidget.tsx similarity index 100% rename from lib-core/src/widgets/PeformanceWidget.tsx rename to packages/react-canvas-core/src/widgets/PeformanceWidget.tsx diff --git a/lib-defaults/tsconfig.json b/packages/react-canvas-core/tsconfig.json similarity index 82% rename from lib-defaults/tsconfig.json rename to packages/react-canvas-core/tsconfig.json index c46812c..cf8e294 100644 --- a/lib-defaults/tsconfig.json +++ b/packages/react-canvas-core/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig", + "extends": "../../tsconfig", "compilerOptions": { "declaration": true, "declarationDir": "dist/@types" diff --git a/packages/react-canvas-core/webpack.config.js b/packages/react-canvas-core/webpack.config.js new file mode 100644 index 0000000..16fc237 --- /dev/null +++ b/packages/react-canvas-core/webpack.config.js @@ -0,0 +1,8 @@ +const config = require('../../webpack.shared')(__dirname); +module.exports = { + ...config, + output: { + ...config.output, + library: 'projectstorm/react-canvas-core' + } +}; diff --git a/lib-defaults/.npmignore b/packages/react-diagrams-core/.npmignore similarity index 100% rename from lib-defaults/.npmignore rename to packages/react-diagrams-core/.npmignore diff --git a/lib-core/CHANGELOG.md b/packages/react-diagrams-core/CHANGELOG.md similarity index 100% rename from lib-core/CHANGELOG.md rename to packages/react-diagrams-core/CHANGELOG.md diff --git a/lib-core/README.md b/packages/react-diagrams-core/README.md similarity index 100% rename from lib-core/README.md rename to packages/react-diagrams-core/README.md diff --git a/packages/react-diagrams-core/index.ts b/packages/react-diagrams-core/index.ts new file mode 100644 index 0000000..d49ec17 --- /dev/null +++ b/packages/react-diagrams-core/index.ts @@ -0,0 +1,22 @@ +export * from './src/models/DiagramModel'; +export * from './src/entities/label/LabelModel'; + +export * from './src/entities/link/LinkModel'; +export * from './src/entities/link/PointModel'; +export * from './src/entities/link/LinkWidget' + +export * from './src/entities/link-layer/LinkLayerModel' +export * from './src/entities/link-layer/LinkLayerWidget' +export * from './src/entities/link-layer/LinkLayerFactory' + +export * from './src/entities/node-layer/NodeLayerModel' +export * from './src/entities/node-layer/NodeLayerWidget' +export * from './src/entities/node-layer/NodeLayerFactory' + +export * from './src/entities/node/NodeModel'; +export * from './src/entities/node/NodeWidget'; + ; +export * from './src/entities/port/PortModel'; +export * from './src/entities/port/PortWidget'; + +export * from './src/DiagramEngine'; diff --git a/lib-core/package.json b/packages/react-diagrams-core/package.json similarity index 74% rename from lib-core/package.json rename to packages/react-diagrams-core/package.json index 6be3d86..97086f2 100644 --- a/lib-core/package.json +++ b/packages/react-diagrams-core/package.json @@ -8,8 +8,8 @@ }, "scripts": { "clean": "rm -rf ./dist", - "build": "../node_modules/.bin/webpack", - "build:prod": "NODE_ENV=production ../node_modules/.bin/webpack" + "build": "../../node_modules/.bin/webpack", + "build:prod": "NODE_ENV=production ../../node_modules/.bin/webpack" }, "publishConfig": { "access": "public" @@ -28,7 +28,8 @@ "main": "./dist/index.js", "typings": "./dist/@types/index", "dependencies": { - "@projectstorm/react-diagrams-geometry": "^6.0.0-alpha.4.2" + "@projectstorm/react-canvas-core": "^6.0.0-alpha.4.2", + "@projectstorm/geometry": "^6.0.0-alpha.4.2" }, "peerDependencies": { "closest": "^0.0.1", diff --git a/lib-core/src/DiagramEngine.ts b/packages/react-diagrams-core/src/DiagramEngine.ts similarity index 60% rename from lib-core/src/DiagramEngine.ts rename to packages/react-diagrams-core/src/DiagramEngine.ts index 6990906..0c8aeaa 100644 --- a/lib-core/src/DiagramEngine.ts +++ b/packages/react-diagrams-core/src/DiagramEngine.ts @@ -1,52 +1,41 @@ -import { BaseEntity } from './core-models/BaseEntity'; -import { DiagramModel } from './models/DiagramModel'; -import { BaseModel } from './core-models/BaseModel'; -import { NodeModel } from './models/NodeModel'; -import { PortModel } from './models/PortModel'; -import { LinkModel } from './models/LinkModel'; -import { LabelModel } from './models/LabelModel'; -import { FactoryBank } from './core/FactoryBank'; -import { AbstractReactFactory } from './core/AbstractReactFactory'; -import { BaseListener, BaseObserver } from './core/BaseObserver'; -import { Point } from '@projectstorm/react-diagrams-geometry'; -import { Toolkit } from './Toolkit'; +import { NodeModel } from './entities/node/NodeModel'; +import { PortModel } from './entities/port/PortModel'; +import { LinkModel } from './entities/link/LinkModel'; +import { LabelModel } from './entities/label/LabelModel'; +import { Point } from '@projectstorm/geometry'; import { MouseEvent } from 'react'; -import { AbstractActionFactory } from './core-actions/AbstractActionFactory'; -import { AbstractModelFactory } from './core/AbstractModelFactory'; +import { + AbstractModelFactory, + AbstractReactFactory, + BaseModel, + CanvasEngine, + FactoryBank, + Toolkit +} from "@projectstorm/react-canvas-core"; +import {CanvasEngineListener} from "@projectstorm/react-canvas-core"; +import {DiagramModel} from "./models/DiagramModel"; -export interface DiagramEngineListener extends BaseListener { - canvasReady?(): void; - - repaintCanvas?(): void; - - rendered?(): void; -} /** * Passed as a parameter to the DiagramWidget */ -export class DiagramEngine extends BaseObserver { - protected nodeFactories: FactoryBank>; - protected linkFactories: FactoryBank>; - protected portFactories: FactoryBank>; - protected labelFactories: FactoryBank>; - protected actionFactories: FactoryBank; +export class DiagramEngine extends CanvasEngine { + protected nodeFactories: FactoryBank>; + protected linkFactories: FactoryBank>; + protected portFactories: FactoryBank>; + protected labelFactories: FactoryBank>; - diagramModel: DiagramModel; - canvas: HTMLDivElement; maxNumberPointsPerLink: number; constructor() { super(); this.maxNumberPointsPerLink = 1000; - this.diagramModel = new DiagramModel(); // create banks for the different factory types this.nodeFactories = new FactoryBank(); this.linkFactories = new FactoryBank(); this.portFactories = new FactoryBank(); this.labelFactories = new FactoryBank(); - this.actionFactories = new FactoryBank(); const setup = (factory: FactoryBank) => { factory.registerListener({ @@ -63,26 +52,15 @@ export class DiagramEngine extends BaseObserver { setup(this.linkFactories); setup(this.portFactories); setup(this.labelFactories); - setup(this.actionFactories); - - this.canvas = null; - // this.linksThatHaveInitiallyRendered = {}; } - repaintCanvas() { - this.iterateListeners(listener => { - if (listener.repaintCanvas) { - listener.repaintCanvas(); - } - }); - } /** * Gets a model and element under the mouse cursor */ getMouseElement(event: MouseEvent): { model: BaseModel; element: Element } { var target = event.target as Element; - var diagramModel = this.diagramModel; + var diagramModel = this.model; //is it a port var element = Toolkit.closest(target, '.port[data-name]'); @@ -124,36 +102,6 @@ export class DiagramEngine extends BaseObserver { return null; } - /** - * Checks to see if a model is locked by running through - * its parents to see if they are locked first - */ - isModelLocked(model: BaseEntity) { - //always check the diagram model - if (this.diagramModel.isLocked()) { - return true; - } - - return model.isLocked(); - } - - setCanvas(canvas?: HTMLDivElement) { - if (this.canvas !== canvas) { - this.canvas = canvas; - if (canvas) { - this.fireEvent({}, 'canvasReady'); - } - } - } - - setDiagramModel(model: DiagramModel) { - this.diagramModel = model; - } - - getDiagramModel(): DiagramModel { - return this.diagramModel; - } - //!-------------- FACTORIES ------------ getNodeFactories() { @@ -172,32 +120,28 @@ export class DiagramEngine extends BaseObserver { return this.portFactories; } - getActionFactories() { - return this.actionFactories; - } - - getFactoryForNode>(node: NodeModel | string) { + getFactoryForNode>(node: NodeModel | string) { if (typeof node === 'string') { return this.nodeFactories.getFactory(node); } return this.nodeFactories.getFactory(node.getType()); } - getFactoryForLink>(link: LinkModel | string) { + getFactoryForLink>(link: LinkModel | string) { if (typeof link === 'string') { return this.linkFactories.getFactory(link); } return this.linkFactories.getFactory(link.getType()); } - getFactoryForLabel>(label: LabelModel) { + getFactoryForLabel>(label: LabelModel) { if (typeof label === 'string') { return this.labelFactories.getFactory(label); } return this.labelFactories.getFactory(label.getType()); } - getFactoryForPort>(port: PortModel) { + getFactoryForPort>(port: PortModel) { if (typeof port === 'string') { return this.portFactories.getFactory(port); } @@ -212,19 +156,6 @@ export class DiagramEngine extends BaseObserver { return this.getFactoryForNode(node).generateReactWidget({ model: node }); } - getRelativeMousePoint(event): Point { - var point = this.getRelativePoint(event.clientX, event.clientY); - return new Point( - (point.x - this.diagramModel.getOffsetX()) / (this.diagramModel.getZoomLevel() / 100.0), - (point.y - this.diagramModel.getOffsetY()) / (this.diagramModel.getZoomLevel() / 100.0) - ); - } - - getRelativePoint(x, y): Point { - var canvasRect = this.canvas.getBoundingClientRect(); - return new Point(x - canvasRect.left, y - canvasRect.top); - } - getNodeElement(node: NodeModel): Element { const selector = this.canvas.querySelector(`.node[data-nodeid="${node.getID()}"]`); if (selector === null) { @@ -257,9 +188,9 @@ export class DiagramEngine extends BaseObserver { return new Point( sourceElement.offsetWidth / 2 + - (rel.x - this.diagramModel.getOffsetX()) / (this.diagramModel.getZoomLevel() / 100.0), + (rel.x - this.model.getOffsetX()) / (this.model.getZoomLevel() / 100.0), sourceElement.offsetHeight / 2 + - (rel.y - this.diagramModel.getOffsetY()) / (this.diagramModel.getZoomLevel() / 100.0) + (rel.y - this.model.getOffsetY()) / (this.model.getZoomLevel() / 100.0) ); } @@ -286,10 +217,10 @@ export class DiagramEngine extends BaseObserver { return { x: - (sourceRect.left - this.diagramModel.getOffsetX()) / (this.diagramModel.getZoomLevel() / 100.0) - + (sourceRect.left - this.model.getOffsetX()) / (this.model.getZoomLevel() / 100.0) - canvasRect.left, y: - (sourceRect.top - this.diagramModel.getOffsetY()) / (this.diagramModel.getZoomLevel() / 100.0) - canvasRect.top, + (sourceRect.top - this.model.getOffsetY()) / (this.model.getZoomLevel() / 100.0) - canvasRect.top, width: sourceRect.width, height: sourceRect.height }; @@ -324,13 +255,4 @@ export class DiagramEngine extends BaseObserver { this.maxNumberPointsPerLink = max; } - zoomToFit() { - const xFactor = this.canvas.clientWidth / this.canvas.scrollWidth; - const yFactor = this.canvas.clientHeight / this.canvas.scrollHeight; - const zoomFactor = xFactor < yFactor ? xFactor : yFactor; - - this.diagramModel.setZoomLevel(this.diagramModel.getZoomLevel() * zoomFactor); - this.diagramModel.setOffset(0, 0); - this.repaintCanvas(); - } } diff --git a/lib-core/src/models/LabelModel.ts b/packages/react-diagrams-core/src/entities/label/LabelModel.ts similarity index 79% rename from lib-core/src/models/LabelModel.ts rename to packages/react-diagrams-core/src/entities/label/LabelModel.ts index 3b3aa28..6da8a88 100644 --- a/lib-core/src/models/LabelModel.ts +++ b/packages/react-diagrams-core/src/entities/label/LabelModel.ts @@ -1,6 +1,6 @@ -import { BaseModel, BaseModelGenerics, BaseModelOptions } from '../core-models/BaseModel'; -import { DiagramEngine } from '../DiagramEngine'; -import { LinkModel } from './LinkModel'; +import { DiagramEngine } from '../../DiagramEngine'; +import { LinkModel } from '../link/LinkModel'; +import {BaseModel, BaseModelGenerics, BaseModelOptions} from "@projectstorm/react-canvas-core"; export interface LabelModelOptions extends BaseModelOptions { offsetX?: number; diff --git a/lib-core/src/widgets/LabelWidget.tsx b/packages/react-diagrams-core/src/entities/label/LabelWidget.tsx similarity index 94% rename from lib-core/src/widgets/LabelWidget.tsx rename to packages/react-diagrams-core/src/entities/label/LabelWidget.tsx index 4d070be..efae693 100644 --- a/lib-core/src/widgets/LabelWidget.tsx +++ b/packages/react-diagrams-core/src/entities/label/LabelWidget.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { DiagramEngine } from '../DiagramEngine'; -import { LabelModel } from '../models/LabelModel'; +import { DiagramEngine } from '../../DiagramEngine'; +import { LabelModel } from './LabelModel'; import styled from '@emotion/styled'; export interface LabelWidgetProps { @@ -86,7 +86,7 @@ export class LabelWidget extends React.Component { }; render() { - const canvas = this.props.engine.canvas; + const canvas = this.props.engine.getCanvas(); return ( diff --git a/packages/react-diagrams-core/src/entities/link-layer/LinkLayerFactory.tsx b/packages/react-diagrams-core/src/entities/link-layer/LinkLayerFactory.tsx new file mode 100644 index 0000000..d145203 --- /dev/null +++ b/packages/react-diagrams-core/src/entities/link-layer/LinkLayerFactory.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { + AbstractReactFactory, + GenerateModelEvent, + GenerateWidgetEvent, +} from "@projectstorm/react-canvas-core"; +import {DiagramEngine} from "../../DiagramEngine"; +import {LinkLayerModel} from "./LinkLayerModel"; +import {LinkLayerWidget} from "./LinkLayerWidget"; + +export class LinkLayerFactory extends AbstractReactFactory{ + + constructor(){ + super('diagram-links'); + } + + generateModel(event: GenerateModelEvent): LinkLayerModel { + return new LinkLayerModel(); + } + + generateReactWidget(event: GenerateWidgetEvent): JSX.Element { + return ( + + ); + } + +} diff --git a/packages/react-diagrams-core/src/entities/link-layer/LinkLayerModel.ts b/packages/react-diagrams-core/src/entities/link-layer/LinkLayerModel.ts new file mode 100644 index 0000000..d1517fa --- /dev/null +++ b/packages/react-diagrams-core/src/entities/link-layer/LinkLayerModel.ts @@ -0,0 +1,21 @@ +import {LayerModel, LayerModelGenerics} from "@projectstorm/react-canvas-core"; +import {LinkModel} from "../link/LinkModel"; + +export interface LinkLayerModelGenerics extends LayerModelGenerics{ + CHILDREN: LinkModel; +} + +export class LinkLayerModel extends LayerModel{ + + constructor(){ + super({ + type: 'diagram-links', + isSvg: true, + transformed: true, + }) + } + + getLinks(){ + return this.getModels(); + } +} diff --git a/packages/react-diagrams-core/src/entities/link-layer/LinkLayerWidget.tsx b/packages/react-diagrams-core/src/entities/link-layer/LinkLayerWidget.tsx new file mode 100644 index 0000000..d244f82 --- /dev/null +++ b/packages/react-diagrams-core/src/entities/link-layer/LinkLayerWidget.tsx @@ -0,0 +1,66 @@ +import * as React from "react"; +import styled from "@emotion/styled"; +import * as _ from "lodash"; +import {LinkWidget} from "../link/LinkWidget"; +import {LinkLayerModel} from "./LinkLayerModel"; +import {DiagramEngine} from "../../DiagramEngine"; +import {PointModel} from "../link/PointModel"; + +export interface LinkLayerWidgetProps { + layer: LinkLayerModel; + engine: DiagramEngine; +} + +export interface LinkLayerWidgetState { +} + +namespace S { + export const Container = styled.div` + + `; +} + +export class LinkLayerWidget extends React.Component { + + constructor(props: LinkLayerWidgetProps) { + super(props); + this.state = {} + } + + render() { + return ( + <> + {//only perform these actions when we have a diagram + _.map(this.props.layer.getLinks(), link => { + return ( + { + + // event.stopPropagation(); + // + // // TODO implement this better and more generic + // let action: MoveItemsAction = null; + // let fac: MoveItemsActionFactory = null; + // try { + // fac = this.props.engine.getActionFactories().getFactory(MoveItemsActionFactory.NAME); + // } catch (e) {} + // if (fac) { + // action = fac.generateAction(event); + // action.fireMouseDown({ + // selectedModel: point, + // selectedEntity: event.target as HTMLElement, + // mouseEvent: event + // }); + // this.startFiringAction(action); + // } + }} + key={link.getID()} + link={link} + diagramEngine={this.props.engine} + /> + ); + })} + + ); + } +} diff --git a/lib-core/src/models/LinkModel.ts b/packages/react-diagrams-core/src/entities/link/LinkModel.ts similarity index 93% rename from lib-core/src/models/LinkModel.ts rename to packages/react-diagrams-core/src/entities/link/LinkModel.ts index 97a7ab3..81b4cc3 100644 --- a/lib-core/src/models/LinkModel.ts +++ b/packages/react-diagrams-core/src/entities/link/LinkModel.ts @@ -1,12 +1,11 @@ -import { BaseModel, BaseModelGenerics, BaseModelListener } from '../core-models/BaseModel'; -import { PortModel } from './PortModel'; +import { PortModel } from '../port/PortModel'; import { PointModel } from './PointModel'; import * as _ from 'lodash'; -import { LabelModel } from './LabelModel'; -import { DiagramEngine } from '../DiagramEngine'; -import { BaseEntityEvent } from '../core-models/BaseEntity'; -import { DiagramModel } from './DiagramModel'; -import { Point } from '@projectstorm/react-diagrams-geometry'; +import { LabelModel } from '../label/LabelModel'; +import { DiagramEngine } from '../../DiagramEngine'; +import { DiagramModel } from '../../models/DiagramModel'; +import { Point } from '@projectstorm/geometry'; +import {BaseEntityEvent, BaseModel, BaseModelGenerics, BaseModelListener} from "@projectstorm/react-canvas-core"; export interface LinkModelListener extends BaseModelListener { sourcePortChanged?(event: BaseEntityEvent & { port: null | PortModel }): void; diff --git a/lib-core/src/widgets/LinkWidget.tsx b/packages/react-diagrams-core/src/entities/link/LinkWidget.tsx similarity index 84% rename from lib-core/src/widgets/LinkWidget.tsx rename to packages/react-diagrams-core/src/entities/link/LinkWidget.tsx index 9bf96a6..d9986bb 100644 --- a/lib-core/src/widgets/LinkWidget.tsx +++ b/packages/react-diagrams-core/src/entities/link/LinkWidget.tsx @@ -1,15 +1,12 @@ import * as React from 'react'; -import { DiagramEngine } from '../DiagramEngine'; -import { LinkModel } from '../models/LinkModel'; -import { ListenerHandle } from '../core/BaseObserver'; -import { BaseEntityEvent } from '../core-models/BaseEntity'; -import { BasePositionModel } from '../core-models/BasePositionModel'; -import { PointModel } from '../models/PointModel'; -import { PortModel } from '../models/PortModel'; +import { DiagramEngine } from '../../DiagramEngine'; +import { LinkModel } from './LinkModel'; +import { PointModel } from './PointModel'; +import { PortModel } from '../port/PortModel'; import { MouseEvent } from 'react'; import * as _ from 'lodash'; -import { LabelWidget } from './LabelWidget'; -import { PeformanceWidget } from './PeformanceWidget'; +import { LabelWidget } from '../label/LabelWidget'; +import {BaseEntityEvent, BasePositionModel, ListenerHandle, PeformanceWidget} from "@projectstorm/react-canvas-core"; export interface LinkProps { link: LinkModel; @@ -82,6 +79,10 @@ export class LinkWidget extends React.Component { this.ensureInstalled(installSource, installTarget); } + public static generateLinePath(firstPoint: PointModel, lastPoint: PointModel): string { + return `M${firstPoint.getX()},${firstPoint.getY()} L ${lastPoint.getX()},${lastPoint.getY()}`; + } + componentDidMount(): void { this.ensureInstalled(!!this.props.link.getSourcePort(), !!this.props.link.getTargetPort()); } diff --git a/lib-core/src/models/PointModel.ts b/packages/react-diagrams-core/src/entities/link/PointModel.ts similarity index 91% rename from lib-core/src/models/PointModel.ts rename to packages/react-diagrams-core/src/entities/link/PointModel.ts index b808092..9ee8b05 100644 --- a/lib-core/src/models/PointModel.ts +++ b/packages/react-diagrams-core/src/entities/link/PointModel.ts @@ -1,10 +1,10 @@ -import { BaseModelListener } from '../core-models/BaseModel'; import { LinkModel } from './LinkModel'; import { + BaseModelListener, BasePositionModel, BasePositionModelGenerics, BasePositionModelOptions -} from '../core-models/BasePositionModel'; +} from "@projectstorm/react-canvas-core"; export interface PointModelOptions extends Omit { link: LinkModel; diff --git a/packages/react-diagrams-core/src/entities/node-layer/NodeLayerFactory.tsx b/packages/react-diagrams-core/src/entities/node-layer/NodeLayerFactory.tsx new file mode 100644 index 0000000..eb9f04d --- /dev/null +++ b/packages/react-diagrams-core/src/entities/node-layer/NodeLayerFactory.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import { + AbstractReactFactory, + GenerateModelEvent, + GenerateWidgetEvent, +} from "@projectstorm/react-canvas-core"; +import {DiagramEngine} from "../../DiagramEngine"; +import {NodeLayerModel} from "./NodeLayerModel"; +import {NodeLayerWidget} from "./NodeLayerWidget"; + +export class NodeLayerFactory extends AbstractReactFactory{ + + constructor(){ + super('diagram-nodes'); + } + + generateModel(event: GenerateModelEvent): NodeLayerModel { + return new NodeLayerModel(); + } + + generateReactWidget(event: GenerateWidgetEvent): JSX.Element { + return ( + + ); + } + +} diff --git a/packages/react-diagrams-core/src/entities/node-layer/NodeLayerModel.ts b/packages/react-diagrams-core/src/entities/node-layer/NodeLayerModel.ts new file mode 100644 index 0000000..eb47be4 --- /dev/null +++ b/packages/react-diagrams-core/src/entities/node-layer/NodeLayerModel.ts @@ -0,0 +1,22 @@ +import {LayerModel, LayerModelGenerics} from "@projectstorm/react-canvas-core"; +import {NodeModel} from "../node/NodeModel"; + +export interface NodeLayerModelGenerics extends LayerModelGenerics{ + CHILDREN: NodeModel +} + +export class NodeLayerModel extends LayerModel{ + + constructor(){ + super({ + type: 'diagram-nodes', + isSvg: false, + transformed: true, + }) + } + + getNodes(){ + return this.getModels(); + } + +} diff --git a/packages/react-diagrams-core/src/entities/node-layer/NodeLayerWidget.tsx b/packages/react-diagrams-core/src/entities/node-layer/NodeLayerWidget.tsx new file mode 100644 index 0000000..7fa494f --- /dev/null +++ b/packages/react-diagrams-core/src/entities/node-layer/NodeLayerWidget.tsx @@ -0,0 +1,33 @@ +import * as React from "react"; +import styled from "@emotion/styled"; +import * as _ from "lodash"; +import {NodeModel} from "../node/NodeModel"; +import {NodeWidget} from "../node/NodeWidget"; +import {NodeLayerModel} from "./NodeLayerModel"; +import {DiagramEngine} from "../../DiagramEngine"; + +export interface NodeLayerWidgetProps { + layer: NodeLayerModel; + engine: DiagramEngine; +} + +namespace S { + export const Container = styled.div` + + `; +} + +export class NodeLayerWidget extends React.Component { + + render() { + return ( + <> + { + _.map(this.props.layer.getNodes(), (node: NodeModel) => { + return ; + }) + } + + ); + } +} diff --git a/lib-core/src/models/NodeModel.ts b/packages/react-diagrams-core/src/entities/node/NodeModel.ts similarity index 87% rename from lib-core/src/models/NodeModel.ts rename to packages/react-diagrams-core/src/entities/node/NodeModel.ts index 75860a6..066d3fa 100644 --- a/lib-core/src/models/NodeModel.ts +++ b/packages/react-diagrams-core/src/entities/node/NodeModel.ts @@ -1,12 +1,15 @@ -import { BaseModelListener } from '../core-models/BaseModel'; import * as _ from 'lodash'; -import { DiagramEngine } from '../DiagramEngine'; -import { BaseEntityEvent } from '../core-models/BaseEntity'; -import { BasePositionModel, BasePositionModelGenerics } from '../core-models/BasePositionModel'; -import { DiagramModel } from './DiagramModel'; -import { PortModel } from './PortModel'; -import { LinkModel } from './LinkModel'; -import { Point } from '@projectstorm/react-diagrams-geometry'; +import { DiagramEngine } from '../../DiagramEngine'; +import { DiagramModel } from '../../models/DiagramModel'; +import { PortModel } from '../port/PortModel'; +import { LinkModel } from '../link/LinkModel'; +import { Point } from '@projectstorm/geometry'; +import { + BaseEntityEvent, + BaseModelListener, + BasePositionModel, + BasePositionModelGenerics +} from "@projectstorm/react-canvas-core"; export interface NodeModelListener extends BaseModelListener { positionChanged?(event: BaseEntityEvent): void; diff --git a/lib-core/src/widgets/NodeWidget.tsx b/packages/react-diagrams-core/src/entities/node/NodeWidget.tsx similarity index 70% rename from lib-core/src/widgets/NodeWidget.tsx rename to packages/react-diagrams-core/src/entities/node/NodeWidget.tsx index 36737e8..76e4ce6 100644 --- a/lib-core/src/widgets/NodeWidget.tsx +++ b/packages/react-diagrams-core/src/entities/node/NodeWidget.tsx @@ -1,33 +1,37 @@ import * as React from 'react'; import * as _ from 'lodash'; -import { DiagramEngine } from '../DiagramEngine'; -import { NodeModel } from '../models/NodeModel'; -import { BaseWidget, BaseWidgetProps } from './BaseWidget'; -import { BaseEntityEvent } from '../core-models/BaseEntity'; -import { BaseModel } from '../core-models/BaseModel'; -import { ListenerHandle } from '../core/BaseObserver'; -import { PeformanceWidget } from './PeformanceWidget'; +import { DiagramEngine } from '../../DiagramEngine'; +import { NodeModel } from './NodeModel'; +import {BaseEntityEvent, BaseModel, ListenerHandle, PeformanceWidget} from "@projectstorm/react-canvas-core"; +import styled from "@emotion/styled"; -export interface NodeProps extends BaseWidgetProps { +export interface NodeProps { node: NodeModel; children?: any; diagramEngine: DiagramEngine; } -export class NodeWidget extends BaseWidget { +namespace S{ + export const Node = styled.div` + position: absolute; + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + user-select: none; + cursor: move; + pointer-events: all; + ` +} + +export class NodeWidget extends React.Component { ob: any; ref: React.RefObject; listener: ListenerHandle; constructor(props: NodeProps) { - super('srd-node', props); + super(props); this.ref = React.createRef(); } - getClassName() { - return 'node ' + super.getClassName() + (this.props.node.isSelected() ? this.bem('--selected') : ''); - } - componentWillUnmount(): void { this.ob.disconnect(); this.ob = null; @@ -68,16 +72,16 @@ export class NodeWidget extends BaseWidget { {() => { return ( -
{this.props.diagramEngine.generateWidgetForNode(this.props.node)} -
+ ); }}
diff --git a/lib-core/src/models/PortModel.ts b/packages/react-diagrams-core/src/entities/port/PortModel.ts similarity index 88% rename from lib-core/src/models/PortModel.ts rename to packages/react-diagrams-core/src/entities/port/PortModel.ts index 99d10ba..feecab7 100644 --- a/lib-core/src/models/PortModel.ts +++ b/packages/react-diagrams-core/src/entities/port/PortModel.ts @@ -1,15 +1,14 @@ -import { BaseModelOptions } from '../core-models/BaseModel'; -import { NodeModel } from './NodeModel'; -import { LinkModel } from './LinkModel'; +import { NodeModel } from '../node/NodeModel'; +import { LinkModel } from '../link/LinkModel'; import * as _ from 'lodash'; -import { DiagramEngine } from '../DiagramEngine'; +import { DiagramEngine } from '../../DiagramEngine'; +import { Point } from '@projectstorm/geometry'; import { - BasePositionModel, + BaseEntityEvent, + BaseModelOptions, BasePositionModel, BasePositionModelGenerics, BasePositionModelListener -} from '../core-models/BasePositionModel'; -import { Point } from '@projectstorm/react-diagrams-geometry'; -import { BaseEntityEvent } from '../core-models/BaseEntity'; +} from "@projectstorm/react-canvas-core"; export enum PortModelAlignment { TOP = 'top', diff --git a/lib-core/src/widgets/PortWidget.tsx b/packages/react-diagrams-core/src/entities/port/PortWidget.tsx similarity index 71% rename from lib-core/src/widgets/PortWidget.tsx rename to packages/react-diagrams-core/src/entities/port/PortWidget.tsx index 1a865f7..7ca8209 100644 --- a/lib-core/src/widgets/PortWidget.tsx +++ b/packages/react-diagrams-core/src/entities/port/PortWidget.tsx @@ -1,12 +1,10 @@ import * as React from 'react'; import * as _ from 'lodash'; -import { BaseWidget, BaseWidgetProps } from './BaseWidget'; -import { Toolkit } from '../Toolkit'; -import { PortModel } from '../models/PortModel'; -import { DiagramEngine } from '../DiagramEngine'; -import { ListenerHandle } from '../core/BaseObserver'; +import { PortModel } from './PortModel'; +import { DiagramEngine } from '../../DiagramEngine'; +import {ListenerHandle, Toolkit} from "@projectstorm/react-canvas-core"; -export interface PortProps extends BaseWidgetProps { +export interface PortProps { port: PortModel; engine: DiagramEngine; } @@ -15,12 +13,12 @@ export interface PortState { selected: boolean; } -export class PortWidget extends BaseWidget { +export class PortWidget extends React.Component { ref: React.RefObject; engineListenerHandle: ListenerHandle; constructor(props: PortProps) { - super('srd-port', props); + super(props); this.ref = React.createRef(); this.state = { selected: false @@ -47,15 +45,11 @@ export class PortWidget extends BaseWidget { this.report(); } }); - if (this.props.engine.canvas) { + if (this.props.engine.getCanvas()) { this.report(); } } - getClassName() { - return 'port ' + super.getClassName() + (this.state.selected ? this.bem('--selected') : ''); - } - getExtraProps() { if (Toolkit.TESTING) { const links = _.keys(this.props.port.getNode().getPort(this.props.port.getName()).links).join(','); @@ -70,7 +64,7 @@ export class PortWidget extends BaseWidget { return (
{ this.setState({ selected: true }); }} @@ -80,7 +74,9 @@ export class PortWidget extends BaseWidget { data-name={this.props.port.getName()} data-nodeid={this.props.port.getNode().getID()} {...this.getExtraProps()} - /> + > + {this.props.children} +
); } } diff --git a/packages/react-diagrams-core/src/models/DiagramModel.ts b/packages/react-diagrams-core/src/models/DiagramModel.ts new file mode 100644 index 0000000..6f9523a --- /dev/null +++ b/packages/react-diagrams-core/src/models/DiagramModel.ts @@ -0,0 +1,167 @@ + +import * as _ from 'lodash'; +import { LinkModel } from '../entities/link/LinkModel'; +import { NodeModel } from '../entities/node/NodeModel'; +import { + BaseEntityEvent, + BaseEntityListener, BaseModel, + CanvasModel, + CanvasModelGenerics, LayerModel +} from "@projectstorm/react-canvas-core"; +import {NodeLayerModel} from "../entities/node-layer/NodeLayerModel"; +import {LinkLayerModel} from "../entities/link-layer/LinkLayerModel"; + +export interface DiagramListener extends BaseEntityListener { + nodesUpdated?(event: BaseEntityEvent & { node: NodeModel; isCreated: boolean }): void; + + linksUpdated?(event: BaseEntityEvent & { link: LinkModel; isCreated: boolean }): void; +} + +export interface DiagramModelGenerics extends CanvasModelGenerics { + LISTENER: DiagramListener; +} + +export class DiagramModel extends CanvasModel { + + protected activeNodeLayer: NodeLayerModel; + protected activeLinkLayer: LinkLayerModel; + + constructor(options: G['OPTIONS'] = {}) { + super(options); + this.addLayer(new LinkLayerModel()); + this.addLayer(new NodeLayerModel()); + } + + addLayer(layer: LayerModel): void { + super.addLayer(layer); + if(layer instanceof NodeLayerModel){ + this.activeNodeLayer = layer; + } + if(layer instanceof LinkLayerModel){ + this.activeLinkLayer = layer; + } + } + + getLinkLayers(): LinkLayerModel[]{ + return _.filter(this.layers, (layer) => { + return layer instanceof LinkLayerModel; + }) as LinkLayerModel[]; + } + + getNodeLayers(): NodeLayerModel[]{ + return _.filter(this.layers, (layer) => { + return layer instanceof NodeLayerModel; + }) as NodeLayerModel[]; + } + + getActiveNodeLayer(): NodeLayerModel{ + if(!this.activeNodeLayer){ + const layers = this.getNodeLayers(); + if(layers.length === 0){ + this.addLayer(new NodeLayerModel()) + }else{ + this.activeNodeLayer = layers[0]; + } + } + return this.activeNodeLayer; + } + + getActiveLinkLayer(): LinkLayerModel{ + if(!this.activeLinkLayer){ + const layers = this.getLinkLayers(); + if(layers.length === 0){ + this.addLayer(new NodeLayerModel()) + }else{ + this.activeLinkLayer = layers[0]; + } + } + return this.activeLinkLayer; + } + + getNode(node: string): NodeModel { + for(const layer of this.getNodeLayers()){ + const model = layer.getModel(node); + if(model){ + return model; + } + } + } + + getLink(link: string): LinkModel { + for(const layer of this.getLinkLayers()){ + const model = layer.getModel(link); + if(model){ + return model; + } + } + } + + addAll(...models: BaseModel[]): BaseModel[] { + _.forEach(models, model => { + if (model instanceof LinkModel) { + this.addLink(model); + } else if (model instanceof NodeModel) { + this.addNode(model); + } + }); + return models; + } + + addLink(link: LinkModel): LinkModel { + link.registerListener({ + entityRemoved: () => { + this.removeLink(link); + } + }); + this.getActiveLinkLayer().addModel(link); + this.fireEvent( + { + link, + isCreated: true + }, + 'linksUpdated' + ); + return link; + } + + addNode(node: NodeModel): NodeModel { + node.registerListener({ + entityRemoved: () => { + this.removeNode(node); + } + }); + this.getActiveNodeLayer().addModel(node); + this.fireEvent({ node, isCreated: true }, 'nodesUpdated'); + return node; + } + + removeLink(link: LinkModel) { + const removed = _.some(this.getLinkLayers(), (layer) => { + return layer.removeModel(link); + }); + if(removed){ + this.fireEvent({ link, isCreated: false }, 'linksUpdated'); + } + } + + removeNode(node: NodeModel) { + const removed = _.some(this.getNodeLayers(), (layer) => { + return layer.removeModel(node); + }); + if(removed){ + this.fireEvent({ node, isCreated: false }, 'nodesUpdated'); + } + } + + getLinks(): LinkModel[] { + return _.flatMap(this.getLinkLayers(), (layer) => { + return _.values(layer.getModels()); + }); + } + + getNodes(): NodeModel[] { + return _.flatMap(this.getNodeLayers(), (layer) => { + return _.values(layer.getModels()) + }); + } +} diff --git a/lib-routing/tsconfig.json b/packages/react-diagrams-core/tsconfig.json similarity index 82% rename from lib-routing/tsconfig.json rename to packages/react-diagrams-core/tsconfig.json index c46812c..cf8e294 100644 --- a/lib-routing/tsconfig.json +++ b/packages/react-diagrams-core/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig", + "extends": "../../tsconfig", "compilerOptions": { "declaration": true, "declarationDir": "dist/@types" diff --git a/packages/react-diagrams-core/webpack.config.js b/packages/react-diagrams-core/webpack.config.js new file mode 100644 index 0000000..16fc237 --- /dev/null +++ b/packages/react-diagrams-core/webpack.config.js @@ -0,0 +1,8 @@ +const config = require('../../webpack.shared')(__dirname); +module.exports = { + ...config, + output: { + ...config.output, + library: 'projectstorm/react-canvas-core' + } +}; diff --git a/lib-geometry/.npmignore b/packages/react-diagrams-defaults/.npmignore similarity index 100% rename from lib-geometry/.npmignore rename to packages/react-diagrams-defaults/.npmignore diff --git a/lib-defaults/README.md b/packages/react-diagrams-defaults/README.md similarity index 100% rename from lib-defaults/README.md rename to packages/react-diagrams-defaults/README.md diff --git a/lib-defaults/index.ts b/packages/react-diagrams-defaults/index.ts similarity index 100% rename from lib-defaults/index.ts rename to packages/react-diagrams-defaults/index.ts diff --git a/lib-defaults/package.json b/packages/react-diagrams-defaults/package.json similarity index 86% rename from lib-defaults/package.json rename to packages/react-diagrams-defaults/package.json index 6733306..8089004 100644 --- a/lib-defaults/package.json +++ b/packages/react-diagrams-defaults/package.json @@ -8,8 +8,8 @@ }, "scripts": { "clean": "rm -rf ./dist", - "build": "../node_modules/.bin/webpack", - "build:prod": "NODE_ENV=production ../node_modules/.bin/webpack" + "build": "../../node_modules/.bin/webpack", + "build:prod": "NODE_ENV=production ../../node_modules/.bin/webpack" }, "publishConfig": { "access": "public" diff --git a/lib-defaults/src/label/DefaultLabelFactory.tsx b/packages/react-diagrams-defaults/src/label/DefaultLabelFactory.tsx similarity index 73% rename from lib-defaults/src/label/DefaultLabelFactory.tsx rename to packages/react-diagrams-defaults/src/label/DefaultLabelFactory.tsx index 2b63ea5..e1ccecb 100644 --- a/lib-defaults/src/label/DefaultLabelFactory.tsx +++ b/packages/react-diagrams-defaults/src/label/DefaultLabelFactory.tsx @@ -1,12 +1,13 @@ import * as React from 'react'; -import { AbstractReactFactory } from '@projectstorm/react-diagrams-core'; import { DefaultLabelModel } from './DefaultLabelModel'; import { DefaultLabelWidget } from './DefaultLabelWidget'; +import {AbstractReactFactory} from "@projectstorm/react-canvas-core"; +import {DiagramEngine} from "@projectstorm/react-diagrams-core"; /** * @author Dylan Vorster */ -export class DefaultLabelFactory extends AbstractReactFactory { +export class DefaultLabelFactory extends AbstractReactFactory { constructor() { super('default'); } diff --git a/lib-defaults/src/label/DefaultLabelModel.tsx b/packages/react-diagrams-defaults/src/label/DefaultLabelModel.tsx similarity index 100% rename from lib-defaults/src/label/DefaultLabelModel.tsx rename to packages/react-diagrams-defaults/src/label/DefaultLabelModel.tsx diff --git a/lib-defaults/src/label/DefaultLabelWidget.tsx b/packages/react-diagrams-defaults/src/label/DefaultLabelWidget.tsx similarity index 100% rename from lib-defaults/src/label/DefaultLabelWidget.tsx rename to packages/react-diagrams-defaults/src/label/DefaultLabelWidget.tsx diff --git a/lib-defaults/src/link/DefaultLinkFactory.tsx b/packages/react-diagrams-defaults/src/link/DefaultLinkFactory.tsx similarity index 85% rename from lib-defaults/src/link/DefaultLinkFactory.tsx rename to packages/react-diagrams-defaults/src/link/DefaultLinkFactory.tsx index fe0d660..7bf6f52 100644 --- a/lib-defaults/src/link/DefaultLinkFactory.tsx +++ b/packages/react-diagrams-defaults/src/link/DefaultLinkFactory.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; -import { AbstractReactFactory } from '@projectstorm/react-diagrams-core'; import { DefaultLinkModel } from './DefaultLinkModel'; import { DefaultLinkWidget } from './DefaultLinkWidget'; import styled from '@emotion/styled'; import { css, keyframes } from '@emotion/core'; +import {AbstractReactFactory} from "@projectstorm/react-canvas-core"; +import {DiagramEngine} from "@projectstorm/react-diagrams-core"; namespace S { export const Keyframes = keyframes` @@ -27,7 +28,7 @@ namespace S { `; } -export class DefaultLinkFactory extends AbstractReactFactory { +export class DefaultLinkFactory extends AbstractReactFactory { constructor(type = 'default') { super(type); } diff --git a/lib-defaults/src/link/DefaultLinkModel.ts b/packages/react-diagrams-defaults/src/link/DefaultLinkModel.ts similarity index 95% rename from lib-defaults/src/link/DefaultLinkModel.ts rename to packages/react-diagrams-defaults/src/link/DefaultLinkModel.ts index f71bcdf..20f5068 100644 --- a/lib-defaults/src/link/DefaultLinkModel.ts +++ b/packages/react-diagrams-defaults/src/link/DefaultLinkModel.ts @@ -1,6 +1,4 @@ import { - BaseEntityEvent, - BaseModelOptions, DiagramEngine, LabelModel, LinkModel, @@ -10,7 +8,8 @@ import { PortModelAlignment } from '@projectstorm/react-diagrams-core'; import { DefaultLabelModel } from '../label/DefaultLabelModel'; -import { BezierCurve } from '@projectstorm/react-diagrams-geometry'; +import { BezierCurve } from '@projectstorm/geometry'; +import {BaseEntityEvent, BaseModelOptions} from "@projectstorm/react-canvas-core"; export interface DefaultLinkModelListener extends LinkModelListener { colorChanged?(event: BaseEntityEvent & { color: null | string }): void; diff --git a/lib-defaults/src/link/DefaultLinkPointWidget.tsx b/packages/react-diagrams-defaults/src/link/DefaultLinkPointWidget.tsx similarity index 100% rename from lib-defaults/src/link/DefaultLinkPointWidget.tsx rename to packages/react-diagrams-defaults/src/link/DefaultLinkPointWidget.tsx diff --git a/lib-defaults/src/link/DefaultLinkSegmentWidget.tsx b/packages/react-diagrams-defaults/src/link/DefaultLinkSegmentWidget.tsx similarity index 95% rename from lib-defaults/src/link/DefaultLinkSegmentWidget.tsx rename to packages/react-diagrams-defaults/src/link/DefaultLinkSegmentWidget.tsx index acc3e52..421e7b2 100644 --- a/lib-defaults/src/link/DefaultLinkSegmentWidget.tsx +++ b/packages/react-diagrams-defaults/src/link/DefaultLinkSegmentWidget.tsx @@ -42,7 +42,7 @@ export class DefaultLinkSegmentWidget extends React.Component { - if (!this.props.diagramEngine.isModelLocked(this.props.link)) { + if (!this.props.link.isLocked()) { event.preventDefault(); this.props.link.remove(); } diff --git a/lib-defaults/src/link/DefaultLinkWidget.tsx b/packages/react-diagrams-defaults/src/link/DefaultLinkWidget.tsx similarity index 93% rename from lib-defaults/src/link/DefaultLinkWidget.tsx rename to packages/react-diagrams-defaults/src/link/DefaultLinkWidget.tsx index 315f247..7a3a210 100644 --- a/lib-defaults/src/link/DefaultLinkWidget.tsx +++ b/packages/react-diagrams-defaults/src/link/DefaultLinkWidget.tsx @@ -1,8 +1,9 @@ import * as React from 'react'; -import { DiagramEngine, PointModel, Toolkit } from '@projectstorm/react-diagrams-core'; +import {DiagramEngine, LinkWidget, PointModel} from '@projectstorm/react-diagrams-core'; import { DefaultLinkModel } from './DefaultLinkModel'; import { DefaultLinkPointWidget } from './DefaultLinkPointWidget'; import { DefaultLinkSegmentWidget } from './DefaultLinkSegmentWidget'; +import {Toolkit} from "@projectstorm/react-canvas-core"; export interface DefaultLinkProps { link: DefaultLinkModel; @@ -48,7 +49,7 @@ export class DefaultLinkWidget extends React.Component { if ( !event.shiftKey && - !this.props.diagramEngine.isModelLocked(this.props.link) && + !this.props.link.isLocked() && this.props.link.getPoints().length - 1 <= this.props.diagramEngine.getMaxNumberPointsPerLink() ) { const point = new PointModel({ @@ -120,7 +121,7 @@ export class DefaultLinkWidget extends React.Component { +export class DefaultNodeFactory extends AbstractReactFactory { constructor() { super('default'); } diff --git a/lib-defaults/src/node/DefaultNodeModel.ts b/packages/react-diagrams-defaults/src/node/DefaultNodeModel.ts similarity index 97% rename from lib-defaults/src/node/DefaultNodeModel.ts rename to packages/react-diagrams-defaults/src/node/DefaultNodeModel.ts index 2e1bc84..3f444cf 100644 --- a/lib-defaults/src/node/DefaultNodeModel.ts +++ b/packages/react-diagrams-defaults/src/node/DefaultNodeModel.ts @@ -1,12 +1,12 @@ import * as _ from 'lodash'; import { - BasePositionModelOptions, DiagramEngine, NodeModel, NodeModelGenerics, PortModelAlignment } from '@projectstorm/react-diagrams-core'; import { DefaultPortModel } from '../port/DefaultPortModel'; +import {BasePositionModelOptions} from "@projectstorm/react-canvas-core"; export interface DefaultNodeModelOptions extends BasePositionModelOptions { name?: string; diff --git a/lib-defaults/src/node/DefaultNodeWidget.tsx b/packages/react-diagrams-defaults/src/node/DefaultNodeWidget.tsx similarity index 100% rename from lib-defaults/src/node/DefaultNodeWidget.tsx rename to packages/react-diagrams-defaults/src/node/DefaultNodeWidget.tsx diff --git a/lib-defaults/src/port/DefaultPortFactory.tsx b/packages/react-diagrams-defaults/src/port/DefaultPortFactory.tsx similarity index 60% rename from lib-defaults/src/port/DefaultPortFactory.tsx rename to packages/react-diagrams-defaults/src/port/DefaultPortFactory.tsx index 1fc8e89..e6ead92 100644 --- a/lib-defaults/src/port/DefaultPortFactory.tsx +++ b/packages/react-diagrams-defaults/src/port/DefaultPortFactory.tsx @@ -1,7 +1,8 @@ -import { AbstractModelFactory } from '@projectstorm/react-diagrams-core'; import { DefaultPortModel } from './DefaultPortModel'; +import {AbstractModelFactory} from "@projectstorm/react-canvas-core"; +import {DiagramEngine} from "@projectstorm/react-diagrams-core"; -export class DefaultPortFactory extends AbstractModelFactory { +export class DefaultPortFactory extends AbstractModelFactory { constructor() { super('default'); } diff --git a/lib-defaults/src/port/DefaultPortLabelWidget.tsx b/packages/react-diagrams-defaults/src/port/DefaultPortLabelWidget.tsx similarity index 74% rename from lib-defaults/src/port/DefaultPortLabelWidget.tsx rename to packages/react-diagrams-defaults/src/port/DefaultPortLabelWidget.tsx index 908acaa..d964961 100644 --- a/lib-defaults/src/port/DefaultPortLabelWidget.tsx +++ b/packages/react-diagrams-defaults/src/port/DefaultPortLabelWidget.tsx @@ -18,11 +18,25 @@ namespace S { export const Label = styled.div` padding: 0 5px; `; + + export const Port = styled.div` + width: 15px; + height: 15px; + background: rgba(white, 0.1); + + &:hover{ + background: rgb(192, 255, 0); + } + `; } export class DefaultPortLabel extends React.Component { render() { - const port = ; + const port = ( + + + + ); const label = {this.props.port.getOptions().label}; return ( diff --git a/lib-defaults/src/port/DefaultPortModel.ts b/packages/react-diagrams-defaults/src/port/DefaultPortModel.ts similarity index 96% rename from lib-defaults/src/port/DefaultPortModel.ts rename to packages/react-diagrams-defaults/src/port/DefaultPortModel.ts index fa89825..a9a583b 100644 --- a/lib-defaults/src/port/DefaultPortModel.ts +++ b/packages/react-diagrams-defaults/src/port/DefaultPortModel.ts @@ -1,4 +1,3 @@ -import * as _ from 'lodash'; import { DiagramEngine, LinkModel, @@ -6,9 +5,9 @@ import { PortModelAlignment, PortModelGenerics, PortModelOptions, - AbstractModelFactory } from '@projectstorm/react-diagrams-core'; import { DefaultLinkModel } from '../link/DefaultLinkModel'; +import {AbstractModelFactory} from "@projectstorm/react-canvas-core"; export interface DefaultPortModelOptions extends PortModelOptions { label?: string; diff --git a/lib-geometry/tsconfig.json b/packages/react-diagrams-defaults/tsconfig.json similarity index 82% rename from lib-geometry/tsconfig.json rename to packages/react-diagrams-defaults/tsconfig.json index c46812c..cf8e294 100644 --- a/lib-geometry/tsconfig.json +++ b/packages/react-diagrams-defaults/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig", + "extends": "../../tsconfig", "compilerOptions": { "declaration": true, "declarationDir": "dist/@types" diff --git a/lib-defaults/webpack.config.js b/packages/react-diagrams-defaults/webpack.config.js similarity index 66% rename from lib-defaults/webpack.config.js rename to packages/react-diagrams-defaults/webpack.config.js index 65cdf3f..2687d8e 100644 --- a/lib-defaults/webpack.config.js +++ b/packages/react-diagrams-defaults/webpack.config.js @@ -1,4 +1,4 @@ -const config = require('../webpack.shared')(__dirname); +const config = require('../../webpack.shared')(__dirname); module.exports = { ...config, output: { diff --git a/lib-routing/.npmignore b/packages/react-diagrams-routing/.npmignore similarity index 100% rename from lib-routing/.npmignore rename to packages/react-diagrams-routing/.npmignore diff --git a/lib-routing/README.md b/packages/react-diagrams-routing/README.md similarity index 100% rename from lib-routing/README.md rename to packages/react-diagrams-routing/README.md diff --git a/lib-routing/index.ts b/packages/react-diagrams-routing/index.ts similarity index 100% rename from lib-routing/index.ts rename to packages/react-diagrams-routing/index.ts diff --git a/lib-routing/jest.config.js b/packages/react-diagrams-routing/jest.config.js similarity index 100% rename from lib-routing/jest.config.js rename to packages/react-diagrams-routing/jest.config.js diff --git a/lib-routing/package.json b/packages/react-diagrams-routing/package.json similarity index 78% rename from lib-routing/package.json rename to packages/react-diagrams-routing/package.json index 1d9625f..d253680 100644 --- a/lib-routing/package.json +++ b/packages/react-diagrams-routing/package.json @@ -8,9 +8,9 @@ }, "scripts": { "clean": "rm -rf ./dist", - "build": "../node_modules/.bin/webpack", - "build:prod": "NODE_ENV=production ../node_modules/.bin/webpack", - "test": "../node_modules/.bin/jest --no-cache" + "build": "../../node_modules/.bin/webpack", + "build:prod": "NODE_ENV=production ../../node_modules/.bin/webpack", + "test": "../../node_modules/.bin/jest --no-cache" }, "publishConfig": { "access": "public" @@ -31,7 +31,7 @@ "dependencies": { "@projectstorm/react-diagrams-core": "^6.0.0-alpha.4.2", "@projectstorm/react-diagrams-defaults": "^6.0.0-alpha.4.2", - "@projectstorm/react-diagrams-geometry": "^6.0.0-alpha.4.2" + "@projectstorm/geometry": "^6.0.0-alpha.4.2" }, "peerDependencies": { "dagre": "^0.8.4", diff --git a/lib-routing/src/dagre/DagreEngine.ts b/packages/react-diagrams-routing/src/dagre/DagreEngine.ts similarity index 96% rename from lib-routing/src/dagre/DagreEngine.ts rename to packages/react-diagrams-routing/src/dagre/DagreEngine.ts index cb8e3e3..0895bbf 100644 --- a/lib-routing/src/dagre/DagreEngine.ts +++ b/packages/react-diagrams-routing/src/dagre/DagreEngine.ts @@ -2,7 +2,7 @@ import { DiagramModel, PointModel } from '@projectstorm/react-diagrams-core'; import * as dagre from 'dagre'; import * as _ from 'lodash'; import { GraphLabel } from 'dagre'; -import { Point } from '@projectstorm/react-diagrams-geometry'; +import { Point } from '@projectstorm/geometry'; export interface DagreEngineOptions { graph?: GraphLabel; diff --git a/lib-routing/src/engine/PathFinding.ts b/packages/react-diagrams-routing/src/engine/PathFinding.ts similarity index 100% rename from lib-routing/src/engine/PathFinding.ts rename to packages/react-diagrams-routing/src/engine/PathFinding.ts diff --git a/lib-routing/src/link/PathFindingLinkFactory.tsx b/packages/react-diagrams-routing/src/link/PathFindingLinkFactory.tsx similarity index 94% rename from lib-routing/src/link/PathFindingLinkFactory.tsx rename to packages/react-diagrams-routing/src/link/PathFindingLinkFactory.tsx index b994eea..fc37e9d 100644 --- a/lib-routing/src/link/PathFindingLinkFactory.tsx +++ b/packages/react-diagrams-routing/src/link/PathFindingLinkFactory.tsx @@ -1,16 +1,13 @@ import * as React from 'react'; import { - AbstractReactFactory, DiagramEngine, - FactoryBank, - AbstractFactory, - ListenerHandle } from '@projectstorm/react-diagrams-core'; import { PathFindingLinkModel } from './PathFindingLinkModel'; import { PathFindingLinkWidget } from './PathFindingLinkWidget'; import * as _ from 'lodash'; import * as Path from 'paths-js/path'; import { DefaultLinkFactory } from '@projectstorm/react-diagrams-defaults'; +import {AbstractFactory, FactoryBank, ListenerHandle} from "@projectstorm/react-canvas-core"; export class PathFindingLinkFactory extends DefaultLinkFactory { ROUTING_SCALING_FACTOR: number = 5; @@ -151,14 +148,14 @@ export class PathFindingLinkFactory extends DefaultLinkFactory { - const allNodesCoords = _.values(this.engine.diagramModel.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.diagramModel.getLinks()); + const allLinks = _.values(this.engine.getModel().getLinks()); const allPortsCoords = _.flatMap(allLinks.map(link => [link.getSourcePort(), link.getTargetPort()])) .filter(port => port !== null) .map(item => ({ @@ -175,7 +172,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory item.x).x, 0) / @@ -207,7 +204,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory { - _.values(this.engine.diagramModel.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); @@ -226,7 +223,7 @@ export class PathFindingLinkFactory extends DefaultLinkFactory { const allElements = _.flatMap( - _.values(this.engine.diagramModel.getLinks()).map(link => [].concat(link.getSourcePort(), link.getTargetPort())) + _.values(this.engine.getModel().getLinks()).map(link => [].concat(link.getSourcePort(), link.getTargetPort())) ); allElements .filter(port => port !== null) diff --git a/lib-routing/src/link/PathFindingLinkModel.ts b/packages/react-diagrams-routing/src/link/PathFindingLinkModel.ts similarity index 100% rename from lib-routing/src/link/PathFindingLinkModel.ts rename to packages/react-diagrams-routing/src/link/PathFindingLinkModel.ts diff --git a/lib-routing/src/link/PathFindingLinkWidget.tsx b/packages/react-diagrams-routing/src/link/PathFindingLinkWidget.tsx similarity index 100% rename from lib-routing/src/link/PathFindingLinkWidget.tsx rename to packages/react-diagrams-routing/src/link/PathFindingLinkWidget.tsx diff --git a/lib-routing/tests/PathFinding.test.tsx b/packages/react-diagrams-routing/tests/PathFinding.test.tsx similarity index 100% rename from lib-routing/tests/PathFinding.test.tsx rename to packages/react-diagrams-routing/tests/PathFinding.test.tsx diff --git a/packages/react-diagrams-routing/tsconfig.json b/packages/react-diagrams-routing/tsconfig.json new file mode 100644 index 0000000..cf8e294 --- /dev/null +++ b/packages/react-diagrams-routing/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "declaration": true, + "declarationDir": "dist/@types" + }, + "include": [ + "./src" + ], + "exclude": [ + "./dist" + ] +} diff --git a/lib-routing/webpack.config.js b/packages/react-diagrams-routing/webpack.config.js similarity index 66% rename from lib-routing/webpack.config.js rename to packages/react-diagrams-routing/webpack.config.js index 5ea945b..5a7f0b2 100644 --- a/lib-routing/webpack.config.js +++ b/packages/react-diagrams-routing/webpack.config.js @@ -1,4 +1,4 @@ -const config = require('../webpack.shared')(__dirname); +const config = require('../../webpack.shared')(__dirname); module.exports = { ...config, output: { diff --git a/packages/react-diagrams/.npmignore b/packages/react-diagrams/.npmignore new file mode 100644 index 0000000..011adea --- /dev/null +++ b/packages/react-diagrams/.npmignore @@ -0,0 +1,4 @@ +* +!dist/**/* +!package.json +!README.md diff --git a/packages/react-diagrams/README.md b/packages/react-diagrams/README.md new file mode 100644 index 0000000..e69de29 diff --git a/lib-all/index.ts b/packages/react-diagrams/index.ts similarity index 70% rename from lib-all/index.ts rename to packages/react-diagrams/index.ts index fe99ce3..b33a897 100644 --- a/lib-all/index.ts +++ b/packages/react-diagrams/index.ts @@ -1,8 +1,5 @@ import { - DiagramEngine, - MoveCanvasActionFactory, - MoveItemsActionFactory, - SelectingItemsActionFactory + DiagramEngine, LinkLayerFactory, NodeLayerFactory, } from '@projectstorm/react-diagrams-core'; import { DefaultLabelFactory, @@ -23,6 +20,9 @@ export default (): DiagramEngine => { const engine = new DiagramEngine(); // register model factories + engine.getLayerFactories().registerFactory(new NodeLayerFactory()); + engine.getLayerFactories().registerFactory(new LinkLayerFactory()); + engine.getLabelFactories().registerFactory(new DefaultLabelFactory()); engine.getNodeFactories().registerFactory(new DefaultNodeFactory()); // i cant figure out why engine.getLinkFactories().registerFactory(new DefaultLinkFactory()); @@ -30,8 +30,8 @@ export default (): DiagramEngine => { engine.getPortFactories().registerFactory(new DefaultPortFactory()); // register the default interaction behaviours - engine.getActionFactories().registerFactory(new MoveCanvasActionFactory()); - engine.getActionFactories().registerFactory(new SelectingItemsActionFactory()); - engine.getActionFactories().registerFactory(new MoveItemsActionFactory()); + // engine.getActionFactories().registerFactory(new MoveCanvasActionFactory()); + // engine.getActionFactories().registerFactory(new SelectingItemsActionFactory()); + // engine.getActionFactories().registerFactory(new MoveItemsActionFactory()); return engine; }; diff --git a/lib-all/package.json b/packages/react-diagrams/package.json similarity index 86% rename from lib-all/package.json rename to packages/react-diagrams/package.json index 0491a44..2b4f514 100644 --- a/lib-all/package.json +++ b/packages/react-diagrams/package.json @@ -8,8 +8,8 @@ }, "scripts": { "clean": "rm -rf ./dist", - "build": "../node_modules/.bin/webpack", - "build:prod": "NODE_ENV=production ../node_modules/.bin/webpack" + "build": "../../node_modules/.bin/webpack", + "build:prod": "NODE_ENV=production ../../node_modules/.bin/webpack" }, "publishConfig": { "access": "public" diff --git a/lib-all/tsconfig.json b/packages/react-diagrams/tsconfig.json similarity index 83% rename from lib-all/tsconfig.json rename to packages/react-diagrams/tsconfig.json index b479932..19f5345 100644 --- a/lib-all/tsconfig.json +++ b/packages/react-diagrams/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../tsconfig", + "extends": "../../tsconfig", "compilerOptions": { "declaration": true, "declarationDir": "dist/@types" diff --git a/lib-all/webpack.config.js b/packages/react-diagrams/webpack.config.js similarity index 64% rename from lib-all/webpack.config.js rename to packages/react-diagrams/webpack.config.js index cfac5c5..33f73c0 100644 --- a/lib-all/webpack.config.js +++ b/packages/react-diagrams/webpack.config.js @@ -1,4 +1,4 @@ -const config = require('../webpack.shared')(__dirname); +const config = require('../../webpack.shared')(__dirname); module.exports = { ...config, output: { diff --git a/webpack.shared.js b/webpack.shared.js index acd3ba8..d5084ad 100644 --- a/webpack.shared.js +++ b/webpack.shared.js @@ -13,7 +13,7 @@ module.exports = (directory) => { }, externals: [ nodeExternals({modulesDir: path.join(directory, 'node_modules')}), - nodeExternals({modulesDir: path.join(path.join(directory, '..'), 'node_modules')}) + nodeExternals({modulesDir: path.join(__dirname, 'node_modules')}) ], module: { rules: [