diff --git a/.changeset/funny-chairs-worry.md b/.changeset/funny-chairs-worry.md new file mode 100644 index 00000000..9568b0df --- /dev/null +++ b/.changeset/funny-chairs-worry.md @@ -0,0 +1,5 @@ +--- +'@projectstorm/react-canvas-core': major +--- + +Fixed issue when content changing in canvas cause drag not working. diff --git a/.gitignore b/.gitignore index 5960d76a..a6bbf733 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ dist .env node_modules tsconfig.tsbuildinfo -.vscode \ No newline at end of file +.vscode +.npmrc +yarn.lock +package-lock.json diff --git a/README.md b/README.md index 2886a393..f7f8cefe 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,5 @@ Simply run `pnpm` then `pnpm build` or `pnpm build:prod` in the root directory a ## Built with react-diagrams > Do you have an interesting project built with *react-diagrams*? PR it into this section for others to see. + +Diagrams for GraphQL schema and query plan: [GraphQL Diagrams](https://github.com/xiaogezhang/graphql-diagrams) diff --git a/package.json b/package.json index 14c895c5..0368d6b1 100644 --- a/package.json +++ b/package.json @@ -18,23 +18,23 @@ "nodes" ], "scripts": { - "ncu": "ncu -u && pnpm recursive exec -- ncu -u", - "format": "prettier --write \"**/*.{ts,tsx,js,jsx}\"", - "clean": "rm -rf packages/*/dist", - "test": "pnpm run -r test", - "build": "tsc --build && pnpm run -r build", - "build:prod": "NODE_ENV=production pnpm build", - "release": "pnpm build:prod && pnpm changeset publish", - "release:storybook": "tsc --build && cd diagrams-demo-gallery && pnpm storybook:build && ./node_modules/.bin/storybook-to-ghpages --existing-output-dir .out" + "ncu": "ncu -u && pnpm recursive exec -- ncu -u", + "format": "prettier --write \"**/*.{ts,tsx,js,jsx}\"", + "clean": "rm -rf packages/*/dist", + "test": "pnpm run -r test", + "build": "tsc --build && pnpm run -r build", + "build:prod": "NODE_ENV=production pnpm build", + "release": "pnpm build:prod && pnpm changeset publish", + "release:storybook": "tsc --build && cd diagrams-demo-gallery && pnpm storybook:build && ./node_modules/.bin/storybook-to-ghpages --existing-output-dir .out" }, "devDependencies": { - "@changesets/cli": "^2.26.2", + "@changesets/cli": "^2.26.2", "@types/jest": "^29.5.5", "@types/node": "^20.6.3", "jest": "^29.7.0", "jest-cli": "^29.7.0", "prettier": "^3.0.3", - "rimraf": "^5.0.1", + "rimraf": "^5.0.1", "source-map-loader": "^4.0.1", "terser-webpack-plugin": "^5.3.9", "ts-jest": "^29.1.1", @@ -44,5 +44,9 @@ "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1", "webpack-node-externals": "^3.0.0" + }, + "dependencies": { + "npm": "^10.8.1", + "pnpm": "^9.4.0" } } diff --git a/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx b/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx index 61faa11c..27ad6803 100644 --- a/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx +++ b/packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx @@ -5,110 +5,95 @@ import styled from '@emotion/styled'; import { SmartLayerWidget } from '../layer/SmartLayerWidget'; export interface DiagramProps { - engine: CanvasEngine; - className?: string; + engine: CanvasEngine; + className?: string; } namespace S { - export const Canvas = styled.div` - position: relative; - cursor: move; - overflow: hidden; - `; + 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; +export function CanvasWidget(props: DiagramProps) { + const ref = React.useRef(null); + const [, forceUpdate] = React.useReducer(x => x + 1, 0); + const {engine, className} = props; + const model = engine.getModel(); + // @ts-ignore + const keyDown = React.useCallback((event) => { + engine.getActionEventBus().fireAction({event}); + }, [engine]); + // @ts-ignore + const keyUp = React.useCallback((event) => { + engine.getActionEventBus().fireAction({event}); + }, [engine]); - constructor(props: DiagramProps) { - super(props); + React.useEffect(() => { + const canvasListener = engine.registerListener({ + repaintCanvas: () => { + if (ref.current) { + forceUpdate(); + } + }, + }); + if (ref.current) { + engine.setCanvas(ref.current); + } - this.ref = React.createRef(); - this.state = { - action: null, - diagramEngineListener: null - }; - } + document.addEventListener('keyup', keyUp); + document.addEventListener('keydown', keyDown); + engine.iterateListeners((list) => { + list.rendered && list.rendered(); + }); - componentWillUnmount() { - this.props.engine.deregisterListener(this.canvasListener); - this.props.engine.setCanvas(null); + return () => { + engine.deregisterListener(canvasListener); + engine.setCanvas(undefined); - document.removeEventListener('keyup', this.keyUp); - document.removeEventListener('keydown', this.keyDown); - } + document.removeEventListener('keyup', keyUp); + document.removeEventListener('keydown', keyDown); + }; + }, [engine, keyDown, keyUp]); - 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 }); - }} - onTouchStart={(event) => { - this.props.engine.getActionEventBus().fireAction({ event }); - }} - onTouchEnd={(event) => { - this.props.engine.getActionEventBus().fireAction({ event }); - }} - onTouchMove={(event) => { - this.props.engine.getActionEventBus().fireAction({ event }); - }} - > - {model.getLayers().map((layer) => { - return ( - - - - ); - })} - - ); - } + return ( + { + engine.getActionEventBus().fireAction({event}); + }} + onMouseDown={(event) => { + engine.getActionEventBus().fireAction({event}); + }} + onMouseUp={(event) => { + engine.getActionEventBus().fireAction({event}); + }} + onMouseMove={(event) => { + engine.getActionEventBus().fireAction({event}); + }} + onTouchStart={(event) => { + engine.getActionEventBus().fireAction({event}); + }} + onTouchEnd={(event) => { + engine.getActionEventBus().fireAction({event}); + }} + onTouchMove={(event) => { + engine.getActionEventBus().fireAction({event}); + }}> + {model.getLayers().map((layer) => { + return ( + + + + ); + })} + + ); } diff --git a/packages/react-canvas-core/src/states/DragCanvasState.ts b/packages/react-canvas-core/src/states/DragCanvasState.ts index 1a2fe073..7bbc5514 100644 --- a/packages/react-canvas-core/src/states/DragCanvasState.ts +++ b/packages/react-canvas-core/src/states/DragCanvasState.ts @@ -23,12 +23,13 @@ export class DragCanvasState extends Abst allowDrag: true, ...options }; + this.initialCanvasX = 0; + this.initialCanvasY = 0; } async activated(prev) { super.activated(prev); this.engine.getModel().clearSelection(); - await this.engine.repaintCanvas(true); // we can block layer rendering because we are only targeting the transforms for (let layer of this.engine.getModel().getLayers()) { @@ -37,6 +38,7 @@ export class DragCanvasState extends Abst this.initialCanvasX = this.engine.getModel().getOffsetX(); this.initialCanvasY = this.engine.getModel().getOffsetY(); + await this.engine.repaintCanvas(true); } deactivated(next: State) {