diff --git a/README.md b/README.md index cfc1219..8b9f893 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,15 @@ A super simple, no-nonsense diagramming library written in React that just works [![NPM](https://img.shields.io/npm/v/storm-react-diagrams.svg)](https://npmjs.org/package/storm-react-diagrams) [![NPM](https://img.shields.io/npm/dt/storm-react-diagrams.svg)](https://npmjs.org/package/storm-react-diagrams) -![Demo2](./demo2.png) +![Demo2](./images/example1.png) + +![Demo2](./images/example2.png) + +![Demo2](./images/example3.png) ## Introduction -A no-nonsense diagramming library written entirely in React with the help of Lodash. It aims to be: +A no-nonsense diagramming library written entirely in React with the help of Lodash, and a single polyfill. It aims to be: * Simple, and void of any fuss/complications when implementing it into your own application * Customizable without having to hack the core (adapters/factories etc..) @@ -28,22 +32,17 @@ or yarn add storm-react-diagrams ``` -* Its only dependency is Lodash and obviously React so it will install that too. +## How to build -#### How to build +Simply run ```webpack``` in the root directory (or ```export NODE_ENV=production && webpack``` if you want a production build) and it will spit out the transpiled code and typescript definitions into the dist directory as a single file. __It will also compile the code for the demos__ .We use webpack for this because TSC cannot compile a single UMD file (TSC can currently only output multiple UMD files). -Simply run ```webpack``` in the root directory (or ```webpack -p``` if you want a production build) and it will spit out the transpiled code and typescript definitions into the dist directory as a single file. __It will also compile the code for the demos__ .We use webpack for this because TSC cannot compile a single UMD file (TSC can currently only output multiple UMD files). +_NOTE:_ We turn off name mangeling in production builds because we require class names to be left intact when serializing. -#### How to see the examples - -1. checkout the project -2. run ```webpack``` in the root -3. open up one of the __demos__ folders and load the corresponding index.html file. +## Make your own nodes To see how to create your own nodes like the one below, take a look at __demo3__: -![Demo2](./custom-nodes.png) - +![Demo2](./images/demo3.png) ## How does it work @@ -62,57 +61,29 @@ a link can be connected to it. [Event System](docs/Events.md) -## DiagramWidget props - -- onLinkStateChanged (link, isConnected) -- diagramEngine - - ## Questions -#### Why didn’t I render the nodes as SVG's? +[Questions](docs/Questions.md) -Because its vastly better to render nodes as standard HTML so that we can embed input controls and not have -to deal with the complexities of trying to get SVG to work like we want it to. I also created this primarily to embed into -enterprise applications where the nodes themselves are highly interactive with buttons and other controls that cave when I try to use SVG. +## Usage -#### Why Typescript? +__Delete__ removes any selected items +![__Delete__](./images/rjdDelete.gif) -Because it can transpile into any level of ECMA Script, and the library got really complicated, so I ported it to Typescript -to accommodate the heavy architectural changes I was starting to make. <3 Type Script +__Shift + Mouse Drag__ triggers a multi-selection box +![Shift + Mouse Drag](./images/mouseDrag.gif) -#### Why is there no JSX? +__Shift + Mouse Click__ selects the item (items can be multi-selected) +![Shift + Mouse Click](./images/shiftClick.gif) -Because most of the library is 95% all logic anyway, and I construct very complex DOM elements with many dynamic properties. JSX -Would just get in the way, and I personally hate JSX for a multitude of reasons anyway. +__Mouse Drag__ drags the entire diagram +![Mouse Drag](./images/canvasDrag.gif) -#### How do I make my own elements? +__Mouse Wheel__ zooms the diagram in / out +![Mouse Wheel](./images/mouseWheel.gif) -Take a look at the __defaults__ directory, with specific attention to the __DefaultNodeWidget__ +__Click Link + Drag__ creates a new link point +![Click Link + Drag](./images/createPoint.gif) -#### How do I use the library? - -Take a look at the demo folders, they have simple and complex examples of the complete usage. - -## Usage Demo and Guide - -This is a demo of the interaction taken directly from the test folder. - -![Demo](./demo.gif) - -#### Key commands - -__del key__ will remove anything selected including links - -__shift and drag__ will trigger a multi selection box - -__shift and select nodes/links/points__ will select multiple nodes - -__drag canvas__ will drag the complete diagram - -__mouse wheel__ will zoom in or out the entire diagram - -__click link and drag__ will create a new link anchor/point that you can then drag around - -__click node-port and drag__ will create a new link that is anchored to the port, allowing you -to drag the link to another connecting port +__Click Node Port + Drag__ creates a new link +![Click Node Port + Drag](./images/createLink.gif) diff --git a/custom-nodes.png b/custom-nodes.png deleted file mode 100644 index a04af36..0000000 Binary files a/custom-nodes.png and /dev/null differ diff --git a/demos/demo3/DiamondNodeWidget.ts b/demos/demo3/DiamondNodeWidget.ts index 4f78269..9e3564e 100644 --- a/demos/demo3/DiamondNodeWidget.ts +++ b/demos/demo3/DiamondNodeWidget.ts @@ -16,7 +16,7 @@ export interface DiamonNodeWidgetState { export class DiamonNodeWidget extends React.Component { public static defaultProps: DiamonNodeWidgetProps = { - size:150, + size: 150, node: null }; @@ -34,27 +34,27 @@ export class DiamonNodeWidget extends React.Component - + `}}), - + //left node - React.DOM.div({style: {position: 'absolute', zIndex:10,top:this.props.size/2 - 5}}, + React.DOM.div({style: {position: 'absolute', zIndex:10,top:this.props.size/2 - 8, left: -8}}, React.createElement(SRD.PortWidget,{name: 'left', node: this.props.node}) ), - + //top node - React.DOM.div({style: {position: 'absolute', zIndex:10,left:this.props.size/2-8}}, + React.DOM.div({style: {position: 'absolute', zIndex:10,left:this.props.size/2-8,top:-8}}, React.createElement(SRD.PortWidget,{name: 'top', node: this.props.node}) ), - + //right - React.DOM.div({style: {position: 'absolute', zIndex:10,left:this.props.size-10,top:this.props.size/2}}, + React.DOM.div({style: {position: 'absolute', zIndex:10,left:this.props.size-8,top:this.props.size/2 - 8}}, React.createElement(SRD.PortWidget,{name: 'right', node: this.props.node}) ), - + //bottom - React.DOM.div({style: {position: 'absolute', zIndex:10,left :this.props.size/2 - 8,top:this.props.size-10}}, + React.DOM.div({style: {position: 'absolute', zIndex:10,left :this.props.size/2 - 8,top:this.props.size-8}}, React.createElement(SRD.PortWidget,{name: 'bottom', node: this.props.node}) ), ) @@ -63,4 +63,3 @@ export class DiamonNodeWidget extends React.Component ./dist/style.css" }, "dependencies": { + "closest": "^0.0.1", "lodash": "^4.13.1", "react": "^15.1.0" }, @@ -29,14 +30,14 @@ "@types/lodash": "^4.14.52", "@types/react": "^15.0.9", "@types/react-dom": "^0.14.23", - "source-map-loader": "^0.1.6", - "ts-loader": "^2.0.0", - "typescript": "^2.1.6", "css-loader": "^0.26.1", "node-sass": "^4.5.0", "react-dom": "^15.1.0", "sass-loader": "^6.0.0", + "source-map-loader": "^0.1.6", "style-loader": "^0.13.1", + "ts-loader": "^2.0.0", + "typescript": "^2.1.6", "webpack": "^2.2.1" } } diff --git a/src/Common.ts b/src/Common.ts index c70dbaa..5f7e837 100644 --- a/src/Common.ts +++ b/src/Common.ts @@ -2,9 +2,9 @@ import {BaseEntity, BaseListener} from "./BaseEntity"; import * as _ from "lodash"; export interface BaseModelListener extends BaseListener{ - + selectionChanged?(item: BaseModel, isSelected:boolean): void; - + entityRemoved?(item:any): void; } @@ -12,34 +12,34 @@ export interface BaseModelListener extends BaseListener{ * @author Dylan Vorster */ export class BaseModel extends BaseEntity{ - + selected: boolean; - + constructor(id?:string){ super(id); this.selected = false; } - + deSerialize(ob){ super.deSerialize(ob); this.selected = ob.selected; } - + serialize(){ return _.merge(super.serialize(),{ _class: this.constructor.name, selected: this.selected }); } - + public getID(): string{ return this.id } - + public isSelected(): boolean{ return this.selected; } - + public setSelected(selected: boolean = true){ this.selected = selected; this.iterateListeners((listener) => { @@ -48,7 +48,7 @@ export class BaseModel extends BaseEntity { if(listener.entityRemoved){ @@ -59,73 +59,73 @@ export class BaseModel extends BaseEntity{ - + x:number; y:number; link: LinkModel; - + constructor(link: LinkModel,points: {x:number,y: number}){ super(); this.x = points.x; this.y = points.y; this.link = link; } - + deSerialize(ob){ super.deSerialize(ob); this.x = ob.x; this.y = ob.y; } - + serialize(){ return _.merge(super.serialize(),{ x: this.x, y: this.y }); } - + remove(){ super.remove(); - + //clear references if (this.link){ this.link.removePoint(this); } } - + updateLocation(points: {x:number,y: number}){ this.x = points.x; this.y = points.y; } - + getX():number{ return this.x; } - + getY():number{ return this.y; } - + getLink(): LinkModel{ return this.link; } } export interface LinkModelListener extends BaseModelListener{ - + sourcePortChanged?(item:LinkModel,target: null|PortModel): void; - + targetPortChanged?(item:LinkModel,target: null|PortModel): void; } export class LinkModel extends BaseModel{ - + linkType: string; sourcePort: PortModel|null; targetPort: PortModel|null; points: PointModel[]; extras: {}; - + constructor(){ super(); this.linkType = 'default'; @@ -137,7 +137,7 @@ export class LinkModel extends BaseModel{ this.sourcePort = null; this.targetPort = null; } - + deSerialize(ob){ super.deSerialize(ob); this.linkType = ob.type; @@ -147,7 +147,7 @@ export class LinkModel extends BaseModel{ return p; }) } - + serialize(){ return _.merge(super.serialize(),{ type: this.linkType, @@ -161,7 +161,7 @@ export class LinkModel extends BaseModel{ extras: this.extras }); } - + remove(){ super.remove(); if (this.sourcePort){ @@ -171,16 +171,16 @@ export class LinkModel extends BaseModel{ this.targetPort.removeLink(this); } } - + isLastPoint(point: PointModel){ var index = this.getPointIndex(point); return index === this.points.length-1; } - + getPointIndex(point: PointModel){ return this.points.indexOf(point); } - + getPointModel(id: string): PointModel|null{ for (var i = 0; i < this.points.length;i++){ if (this.points[i].id === id){ @@ -189,15 +189,15 @@ export class LinkModel extends BaseModel{ } return null; } - + getFirstPoint(): PointModel{ return this.points[0]; } - + getLastPoint(): PointModel{ return this.points[this.points.length-1]; } - + setSourcePort(port: PortModel){ port.addLink(this); this.sourcePort = port; @@ -205,15 +205,15 @@ export class LinkModel extends BaseModel{ listener.sourcePortChanged && listener.sourcePortChanged(this, port); }); } - + getSourcePort(): PortModel{ return this.sourcePort; } - + getTargetPort(): PortModel{ return this.targetPort; } - + setTargetPort(port: PortModel){ port.addLink(this); this.targetPort = port; @@ -221,23 +221,23 @@ export class LinkModel extends BaseModel{ listener.targetPortChanged && listener.targetPortChanged(this, port); }); } - + getPoints(): PointModel[]{ return this.points; } - + setPoints(points: PointModel[]){ this.points = points; } - + removePoint(pointModel: PointModel){ this.points.splice(this.getPointIndex(pointModel),1); } - + addPoint(pointModel:PointModel,index = 1){ this.points.splice(index,0,pointModel); } - + getType(): string{ return this.linkType; } @@ -247,12 +247,12 @@ export class PortModel extends BaseModel{ name: string; parentNode: NodeModel; links: {[id: string]: LinkModel}; - + deSerialize(ob){ super.deSerialize(ob); this.name = ob.name; } - + serialize(){ return _.merge(super.serialize(),{ name: this.name, @@ -262,47 +262,47 @@ export class PortModel extends BaseModel{ }) }); } - + constructor(name: string, id?:string){ super(id); this.name = name; this.links = {}; this.parentNode = null; } - + getName(): string{ return this.name; } - + getParent(): NodeModel{ return this.parentNode; } - + setParentNode(node: NodeModel){ this.parentNode = node; } - + removeLink(link: LinkModel){ delete this.links[link.getID()]; } - + addLink(link: LinkModel){ this.links[link.getID()] = link; } - + getLinks(): {[id: string]: LinkModel}{ return this.links; } } export class NodeModel extends BaseModel{ - + nodeType: string; x: number; y: number; extras: {}; ports: {[s: string]:PortModel}; - + constructor(nodeType: string = 'default', id?:string){ super(id); this.nodeType = nodeType; @@ -311,7 +311,7 @@ export class NodeModel extends BaseModel{ this.extras = {}; this.ports = {}; } - + deSerialize(ob){ super.deSerialize(ob); this.nodeType = ob.type; @@ -319,7 +319,7 @@ export class NodeModel extends BaseModel{ this.y = ob.y; this.extras = ob.extras; } - + serialize(){ return _.merge(super.serialize(),{ type: this.nodeType, @@ -331,7 +331,7 @@ export class NodeModel extends BaseModel{ }) }); } - + remove(){ super.remove(); for (var i in this.ports){ @@ -340,7 +340,7 @@ export class NodeModel extends BaseModel{ }); } } - + getPortFromID(id): PortModel | null{ for (var i in this.ports){ if (this.ports[i].id === id){ @@ -349,15 +349,15 @@ export class NodeModel extends BaseModel{ } return null; } - + getPort(name: string): PortModel | null{ return this.ports[name]; } - + getPorts(): {[s: string]:PortModel}{ return this.ports; } - + removePort(port: PortModel){ //clear the parent node reference if(this.ports[port.name]){ @@ -365,14 +365,14 @@ export class NodeModel extends BaseModel{ delete this.ports[port.name]; } } - + addPort(port: PortModel): PortModel{ port.setParentNode(this); this.ports[port.name] = port; return port; } - + getType(): string{ return this.nodeType; } -} \ No newline at end of file +} diff --git a/src/Toolkit.ts b/src/Toolkit.ts index 509f9b8..b6eedf1 100644 --- a/src/Toolkit.ts +++ b/src/Toolkit.ts @@ -1,3 +1,4 @@ +import closest = require("closest"); /** * @author Dylan Vorster */ @@ -12,4 +13,17 @@ export class Toolkit { return v.toString(16); }); } -} \ No newline at end of file + + /** + * 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){ + return element.closest(selector); + } + return closest(element,selector); + } +} diff --git a/src/widgets/DiagramWidget.ts b/src/widgets/DiagramWidget.ts index f5d6623..9330983 100644 --- a/src/widgets/DiagramWidget.ts +++ b/src/widgets/DiagramWidget.ts @@ -5,6 +5,7 @@ import * as _ from "lodash"; import {PointModel, NodeModel, BaseModel, BaseModelListener, LinkModel,PortModel} from "../Common"; import {LinkLayerWidget} from "./LinkLayerWidget"; import {NodeLayerWidget} from "./NodeLayerWidget"; +import {Toolkit} from "../Toolkit"; export interface SelectionModel{ model: BaseModel; @@ -16,7 +17,7 @@ export class BaseAction{ mouseX: number; mouseY: number; ms: number; - + constructor(mouseX: number,mouseY: number){ this.mouseX = mouseX; this.mouseY = mouseY; @@ -27,19 +28,19 @@ export class BaseAction{ export class SelectingAction extends BaseAction{ mouseX2: number; mouseY2: number; - + constructor(mouseX: number,mouseY: number){ super(mouseX,mouseY); this.mouseX2 = mouseX; this.mouseY2 = mouseY; } - + containsElement(x: number, y: number, diagramModel: DiagramModel): boolean{ var z = diagramModel.getZoomLevel()/100.0; return ( - (x + diagramModel.getOffsetX())*z > this.mouseX && - (x + diagramModel.getOffsetX())*z < this.mouseX2&& - (y + diagramModel.getOffsetY())*z > this.mouseY && + (x + diagramModel.getOffsetX())*z > this.mouseX && + (x + diagramModel.getOffsetX())*z < this.mouseX2&& + (y + diagramModel.getOffsetY())*z > this.mouseY && (y + diagramModel.getOffsetY())*z < this.mouseY2 ) } @@ -48,7 +49,7 @@ export class SelectingAction extends BaseAction{ export class MoveCanvasAction extends BaseAction{ initialOffsetX: number; initialOffsetY: number; - + constructor(mouseX: number, mouseY: number, diagramModel: DiagramModel){ super(mouseX,mouseY); this.initialOffsetX = diagramModel.getOffsetX(); @@ -64,12 +65,12 @@ export class MoveItemsAction extends BaseAction{ this.moved = false; diagramEngine.enableRepaintEntities(diagramEngine.getDiagramModel().getSelectedItems()); var selectedItems = diagramEngine.getDiagramModel().getSelectedItems(); - + //dont allow items which are locked to move selectedItems = selectedItems.filter((item) => { return !diagramEngine.isModelLocked(item); }) - + this.selectionModels = selectedItems.map((item: PointModel | NodeModel) => { return { model: item, @@ -82,11 +83,11 @@ export class MoveItemsAction extends BaseAction{ export interface DiagramProps { diagramEngine:DiagramEngine; - + allowLooseLinks?: boolean; allowCanvasTranslation?: boolean; allowCanvasZoom?: boolean; - + actionStartedFiring?: (action: BaseAction) => boolean; actionStillFiring?: (action: BaseAction) => void; actionStoppedFiring?: (action: BaseAction) => void; @@ -105,7 +106,7 @@ export interface DiagramState { * @author Dylan Vorster */ export class DiagramWidget extends React.Component { - + public static defaultProps: DiagramProps = { diagramEngine:null, allowLooseLinks: true, @@ -126,7 +127,7 @@ export class DiagramWidget extends React.Component { document:null } } - + componentWillMount(){ this.setState({ diagramEngineListener: this.props.diagramEngine.addListener({ @@ -144,7 +145,7 @@ export class DiagramWidget extends React.Component { window.removeEventListener('mouseUp',this.onMouseUp); window.removeEventListener('mouseMove',this.onMouseMove); } - + componentWillUpdate(nextProps: DiagramProps){ if (this.props.diagramEngine.diagramModel.id !== nextProps.diagramEngine.diagramModel.id){ this.setState({renderedNodes: false}); @@ -155,7 +156,7 @@ export class DiagramWidget extends React.Component { nextProps.diagramEngine.diagramModel.rendered = true; } } - + componentDidUpdate(){ if (!this.state.renderedNodes){ this.setState({ @@ -163,10 +164,10 @@ export class DiagramWidget extends React.Component { }); } } - + componentDidMount(){ this.props.diagramEngine.setCanvas(this.refs['canvas'] as Element); - + //add a keyboard listener this.setState({ document: document, @@ -187,67 +188,67 @@ export class DiagramWidget extends React.Component { }); window.focus(); } - + /** * Gets a model and element under the mouse cursor */ getMouseElement(event): {model: BaseModel, element: Element}{ var target = event.target as Element; var diagramModel = this.props.diagramEngine.diagramModel; - + //is it a port - var element = target.closest('.port[data-name]'); + var element = Toolkit.closest(target,'.port[data-name]'); if(element){ - var nodeElement = target.closest('.node[data-nodeid]') as HTMLElement; + var nodeElement = Toolkit.closest(target,'.node[data-nodeid]') as HTMLElement; return { model: diagramModel.getNode(nodeElement.getAttribute('data-nodeid')).getPort(element.getAttribute('data-name')), element: element }; } - + //look for a point - element = target.closest('.point[data-id]'); + element = Toolkit.closest(target,'.point[data-id]'); if(element){ return { model: diagramModel.getLink(element.getAttribute('data-linkid')).getPointModel(element.getAttribute('data-id')), element: element }; } - + //look for a link - element = target.closest('[data-linkid]'); + element = Toolkit.closest(target,'[data-linkid]'); if(element){ return { model: diagramModel.getLink(element.getAttribute('data-linkid')), element: element }; } - + //look for a node - element = target.closest('.node[data-nodeid]'); + element = Toolkit.closest(target,'.node[data-nodeid]'); if(element){ return { model: diagramModel.getNode(element.getAttribute('data-nodeid')), element: element } } - + return null; } - + 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: BaseAction){ var setState = true; if(this.props.actionStartedFiring){ @@ -373,7 +374,7 @@ export class DiagramWidget extends React.Component { render() { var diagramEngine = this.props.diagramEngine; var diagramModel = diagramEngine.getDiagramModel(); - + return ( React.DOM.div({ ref:'canvas', @@ -404,27 +405,27 @@ export class DiagramWidget extends React.Component { var relative = diagramEngine.getRelativePoint(event.pageX, event.pageY); this.startFiringAction(new SelectingAction(relative.x, relative.y)); } - + //its a drag the canvas event else{ diagramModel.clearSelection(); this.startFiringAction(new MoveCanvasAction(event.pageX, event.pageY, diagramModel)); } } - + //its a port element, we want to drag a link else if (model.model instanceof PortModel){ var relative = diagramEngine.getRelativeMousePoint(event); var link = new LinkModel(); link.setSourcePort(model.model); - + link.getFirstPoint().updateLocation(relative) link.getLastPoint().updateLocation(relative); - + diagramModel.clearSelection(); link.getLastPoint().setSelected(true); diagramModel.addLink(link); - + this.startFiringAction(new MoveItemsAction(event.pageX, event.pageY, diagramEngine)); } //its some or other element, probably want to move it @@ -433,7 +434,7 @@ export class DiagramWidget extends React.Component { diagramModel.clearSelection(); } model.model.setSelected(true); - + this.startFiringAction(new MoveItemsAction(event.pageX, event.pageY,diagramEngine)); } this.state.document.addEventListener('mousemove', this.onMouseMove); @@ -465,4 +466,4 @@ export class DiagramWidget extends React.Component { ) ); } -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index c9110c6..54d60dc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,9 +9,9 @@ "skipLibCheck": true }, "exclude": [ - "node_modules", - "**/*.spec.ts", + "node_modules", + "**/*.spec.ts", "webpack.config.js", "./dist" - ] + ] } diff --git a/webpack.config.js b/webpack.config.js index 3f05b1b..73117e6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,4 +1,22 @@ var webpack = require("webpack"); +var plugins = []; + +//do we minify it all +if(process.env.NODE_ENV === 'production'){ + plugins.push(new webpack.optimize.UglifyJsPlugin({ + mangle: { + keep_fnames: true + }, + compress: { + keep_fnames: true, + warnings: false, + } + })); + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify('production') + }) +} + /** * @author Dylan Vorster */ @@ -32,20 +50,7 @@ module.exports = [ root: '_' } }, - plugins:[ - new webpack.optimize.UglifyJsPlugin({ - mangle: { - keep_fnames: true - }, - compress: { - keep_fnames: true, - warnings: false, - } - }), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('production') - }) - ], + plugins:plugins, module: { rules: [ { @@ -64,7 +69,7 @@ module.exports = [ resolve: { extensions: [".tsx", ".ts", ".js"] }, -// devtool: 'source-map' + devtool: 'eval-cheap-module-source-map' }, //for building the demos and tests { @@ -101,20 +106,7 @@ module.exports = [ root: '_' } }, - plugins:[ - new webpack.optimize.UglifyJsPlugin({ - mangle: { - keep_fnames: true - }, - compress: { - keep_fnames: true, - warnings: false, - } - }), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('production') - }) - ], + plugins:plugins, module: { rules: [ { @@ -146,6 +138,6 @@ module.exports = [ resolve: { extensions: [".tsx", ".ts", ".js"] }, -// devtool: 'source-map' + devtool: 'eval-cheap-module-source-map' } ]; diff --git a/yarn.lock b/yarn.lock index 608067e..bcd60b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -433,6 +433,12 @@ clone@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" +closest@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/closest/-/closest-0.0.1.tgz#26da6f80b3e0e17e71f80f12782819e9f653495c" + dependencies: + matches-selector "0.0.1" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1427,6 +1433,10 @@ map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" +matches-selector@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/matches-selector/-/matches-selector-0.0.1.tgz#1df5262243ae341c1a0804dd302048267ac713bb" + math-expression-evaluator@^1.2.14: version "1.2.16" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.16.tgz#b357fa1ca9faefb8e48d10c14ef2bcb2d9f0a7c9"