[
  {
    "path": ".changeset/README.md",
    "content": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works\nwith multi-package repos, or single-package repos to help you version and publish your code. You can\nfind the full documentation for it [in our repository](https://github.com/changesets/changesets)\n\nWe have a quick list of common questions to get you started engaging with this project in\n[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)\n"
  },
  {
    "path": ".changeset/cold-drinks-unite.md",
    "content": "---\n'@projectstorm/react-diagrams-defaults': patch\n'@projectstorm/react-diagrams-routing': patch\n'@projectstorm/react-diagrams-core': patch\n'@projectstorm/react-canvas-core': patch\n'@projectstorm/react-diagrams-gallery': patch\n'@projectstorm/react-diagrams-demo': patch\n'@projectstorm/geometry': patch\n---\n\nUpdated packages to support React v19\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n\t\"$schema\": \"https://unpkg.com/@changesets/config@2.2.0/schema.json\",\n\t\"changelog\": \"@changesets/cli/changelog\",\n\t\"commit\": false,\n\t\"fixed\": [],\n\t\"linked\": [],\n\t\"access\": \"restricted\",\n\t\"baseBranch\": \"master\",\n\t\"updateInternalDependencies\": \"patch\",\n\t\"ignore\": []\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "[*]\nindent_style = tab\nindent_size = 2\ntrim_trailing_whitespace = true\n\n# Some exceptions\n[{package.json,*.yml}]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".envrc",
    "content": "PATH_add ./node_modules/.bin\n"
  },
  {
    "path": ".gitbook.yaml",
    "content": "root: ./docs/\n\nstructure:\n  summary: README.md"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "# Checklist\n\n- [ ] The tests pass\n- [ ] I have referenced the issue(s) or other PR(s) this fixes/relates-to\n- [ ] I have run ```pnpm changeset``` and followed the instructions\n- [ ] I have explained in this PR, what I did and why\n- [ ] I replaced the image below\n- [ ] Had a beer/coffee/tea because I did something cool today\n\n## What, why and how?\n\n\n## Feel good image:\n\n\n![LOL](https://i.pinimg.com/originals/7f/1b/c3/7f1bc3fb2e123dd3255a85c04db22f19.jpg)"
  },
  {
    "path": ".github/workflows/prettier.yml",
    "content": "name: Prettier check\n\n# This action works with pull requests and pushes\non:\n  pull_request:\n\njobs:\n  prettier:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n        with:\n          # Make sure the actual branch is checked out when running on pull requests\n          ref: ${{ github.head_ref }}\n\n\n      - uses: actions/checkout@v2 # Check out the repository first.\n      - uses: actionsx/prettier@v2\n        with:\n          # prettier CLI arguments.\n          args: --check --ignore-path .prettierignore --config .prettierrc '**/*.{ts,tsx,js,jsx}'"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    branches:\n      - master\n\nconcurrency: ${{ github.workflow }}-${{ github.ref }}\n\njobs:\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Repo\n        uses: actions/checkout@v2\n\n      - name: Read .nvmrc\n        run: echo \"##[set-output name=NVMRC;]$(cat .nvmrc)\"\n        id: nvm\n\n      - name: Use Node.js (.nvmrc)\n        uses: actions/setup-node@v2\n        with:\n          node-version: \"${{ steps.nvm.outputs.NVMRC }}\"\n\n      - name: Install PNPM\n        uses: pnpm/action-setup@v2\n        with:\n          version: latest\n\n      - name: Install Dependencies\n        run: pnpm install\n\n      - name: Create Release Pull Request\n        uses: changesets/action@v1\n        id: changesets\n        with:\n          # This expects you to have a script called release which does a build for your packages and calls changeset publish\n          publish: pnpm release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n      - name: publish storybook\n        if: steps.changesets.outputs.published == 'true'\n        run: pnpm release:storybook"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Build and Test\non:\n  pull_request:\njobs:\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Repo\n        uses: actions/checkout@v2\n\n      - name: Read .nvmrc\n        run: echo \"##[set-output name=NVMRC;]$(cat .nvmrc)\"\n        id: nvm\n\n      - name: Use Node.js (.nvmrc)\n        uses: actions/setup-node@v2\n        with:\n          node-version: \"${{ steps.nvm.outputs.NVMRC }}\"\n\n      - name: Install PNPM\n        uses: pnpm/action-setup@v2\n        with:\n          version: latest\n\n      - name: Install Dependencies\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build"
  },
  {
    "path": ".gitignore",
    "content": "dist\n.DS_Store\n.idea\n.out\n*.zip\n.env\nnode_modules\ntsconfig.tsbuildinfo\n.vscode"
  },
  {
    "path": ".prettierignore",
    "content": "node_modules\ndist\n.out\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n\t\"semi\": true,\n\t\"singleQuote\": true,\n\t\"useTabs\": true,\n\t\"printWidth\": 120,\n\t\"trailingComma\": \"none\"\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "__V7!__\n\nwe are now using changesets! you can see the changes for individual packages in their corresponding folders.\nHere is the main changeset for the core package which depends on everything:\n\n[Changelog for @projectstorm/react-diagrams](./packages/react-diagrams/CHANGELOG.md)\n\n---\n\n__6.7.4__\n\n.0 -> .4 because I messed up the version / publishing\n\n* (upgrade all dependencies, including a move to React 18)\n  * https://github.com/projectstorm/react-diagrams/pull/947\n\n__6.7.0__\n\nbug fixes:\n* https://github.com/projectstorm/react-diagrams/pull/882\n* https://github.com/projectstorm/react-diagrams/pull/914\n* https://github.com/projectstorm/react-diagrams/pull/875\n\ntypes\n* https://github.com/projectstorm/react-diagrams/pull/906\n\nfeatures:\n* https://github.com/projectstorm/react-diagrams/pull/915\n* https://github.com/projectstorm/react-diagrams/pull/877\n\n__6.6.1__\n\nbug fixes:\n* https://github.com/projectstorm/react-diagrams/pull/861\n* https://github.com/projectstorm/react-diagrams/pull/871\n* https://github.com/projectstorm/react-diagrams/pull/870\n\nSome maintenance:\n* https://github.com/projectstorm/react-diagrams/pull/861\n\n__6.6.0__\n\n* (docs-broken) https://github.com/projectstorm/react-diagrams/pull/834\n* (bug) https://github.com/projectstorm/react-diagrams/pull/838\n* (docs-broken) https://github.com/projectstorm/react-diagrams/pull/847\n* (bug) https://github.com/projectstorm/react-diagrams/pull/852\n* (docs-broken) https://github.com/projectstorm/react-diagrams/pull/856\n* (improvement) https://github.com/projectstorm/react-diagrams/pull/857\n* (bug) https://github.com/projectstorm/react-diagrams/pull/860\n\nAlso includes a bump on all packages using `ncu` recursively.\n\n__6.5.2__\n\nhttps://github.com/projectstorm/react-diagrams/pull/830\n\n* (fix) issue with zoom to fit selected\n* (improvement) properly export PathFinding\n* (maintenance) bump all dependencies\n\n__6.5.1__\n\nhttps://github.com/projectstorm/react-diagrams/pull/829\n\n* (improved) zoom to fit now centers correctly\n* (fix) remove wrong peer dependency (@emotion/core)\n\n__6.5.0__\n\nhttps://github.com/projectstorm/react-diagrams/pull/814\n\n* Some rendering fixes\n* small api change around `zoomToFit`\n* more api options with the `DefaultLink`\n\n__6.4.0__\n\nhttps://github.com/projectstorm/react-diagrams/pull/813\n\n* Bump all packages and move to Emotion 11 and React 17\n* Move to the latest Storybook\n\n__6.2.0__\n\n* (improvement) Move away fromn math-js (https://github.com/projectstorm/react-diagrams/pull/651)\n* (fix) https://github.com/projectstorm/react-diagrams/pull/639\n* (fix) Fixing link spawning at (0,0) when clicking port once (inspired by https://github.com/projectstorm/react-diagrams/pull/637)\n\n__6.1.1__\n\n* (feature) https://github.com/projectstorm/react-diagrams/pull/576 [Add zoom to fit nodes feature, fixes #568]\n* (improvement) https://github.com/projectstorm/react-diagrams/pull/621 [Support deriving from DefaultLabelModel]\n* (fix) https://github.com/projectstorm/react-diagrams/pull/603\n   [Fixes selectionChanged listener not being deregistered on NodeWidget, Fixes unchecked access to this.props.link.getSourcePort() on LinkWidget]\n* (maintenance) bump everything\n* fix serialize/deserialize issue with example project raw JS node\n\n__6.0.0__\n\nNote: This is a complete rewrite of the library, a good place to start to see how the new system works\nis with the new demo project which illustrates the new capability.\n\nI would also recommend taking a look at the new updated DiamondPort widget which shows more capability.\n\n* Break up library into monorepo\n* Introduce react-canvas-core as a new framework\n* Use geometry classes instead of raw X and Y primitives so we can do matrix stuff in the future\n* move testing framework to a name based system instead of ID's\n* Introduce multiple layers (can now have multiple node and link layers)\n* Rewrote the deserialization system to be promise based\n* Completely overhauled the observer framework on the models\n* Moved all the logic in the DiagramWidget into a a new hierarchical state machine\n* Introduces new states for editing\n* Introduced faster layout rendering when transforming the canvas directly\n* Moved all canvas smart routing into its own link-type under routing package\n* Broke up link rendering into a much more modular system that is much easier to extend\n* Introduced port alignment allowing the developer to specify how enter it\n* Improved generics throughout the entire model system with Mapped Types\n* Rewrote all the styles using emotion instead of sass\n* Fixed up all the demos to use the new API\n* Introduced a demo project that illustrates how to use the library with ES6 as well as with Typescript\n* Improved the grid rendering system to allow graphical elements to specify how they get transformed\n* Introduced a performance widget for improving performance in a more deterministic way by comparing the serialization of the model (with a way of opting out)\n* Renamed a bunch of methods to be more consistent and more understandable\n* Completely removed the double render state system that required nodes to render before links, this is done when ports report their new positions\n* Ports can now dynamically be added and removed without having to tell the system it happeend\n* Port widgets are now containers dumb containers for you own ports\n* Port widgets report new sizing information to their target links when they change position, you no longer need to invalidate them\n\n__5.3.2__\n\n* (maintenance) Upgrade :allthethings: (all the build tooling was upgrade)\n* (api) move to ES6 (JS now contains native classes)\n* (api) changed package name to @projectstorm/react-diagrams\n* (bug) (PR259)(https://github.com/projectstorm/react-diagrams/pull/259) Fixes #258\n* (refactor) (PR 306)(https://github.com/projectstorm/react-diagrams/pull/306) `:any` fix\n* (feature) (PR 178)(https://github.com/projectstorm/react-diagrams/pull/178) Trigger a positionChanged event when moving a Node that has the listener assigned.\n* (fix) (PR 356)(https://github.com/projectstorm/react-diagrams/pull/356) Fixed Type issue with 'PointModel()'\n* (demo) dark mode and upgrade storybook\n\n__5.2.1__\n\n* (fix) Always remove link from old source/target port on port change\n* (maintenance) upgrade node modules\n* (refactor) https://github.com/projectstorm/react-diagrams/commit/55f62587bd3b12513c7d37eff59edfc8bdb8d6c9\n* (bug) https://github.com/projectstorm/react-diagrams/commit/75ef02dd4d131a0e7c08b2680c69efc390e50b84\n-> and other improvements, also checkout the foundation work happening over at https://github.com/projectstorm/react-canvas\n\n__5.1.0__\n\n* (api) Rename XXXFactory into AbstractXXXFactory\n* (refactor) tslint and prettier are now the same\n* (refactor) Each class now explicitely has its own class file (consistency)\n* (feature) Smooth vertical links (no longer limited to horizontal)\n* (feature) Dedicated documentation via gitbook\n* (bug) forgot to export some\n* (refactor) consistently use lodash where possible\n* (maintenance) upgrade node modules\n\n__5.0.0__ [http://dylanv.blog/2018/03/03/storm-react-diagrams-5-0-0/](https://dylanvorster.com/storm-react-diagrams-v5-0/)\n\nPR: https://github.com/projectstorm/react-diagrams/pull/145\n\n* (refactor) Links completely overhauled\n* (feature) Smart Routing\n* (feature) Flow support\n* (demo) Smart Routing\n* (demo) Animated links\n* (api) Bootstrapping Improvements\n* (feature) add custom properties to all widgets\n* (refactor) use BEM for all css\n* (feature) Default Link factory hooks\n* (tests) e2e tests + helper framework\n* (tests) automatically load JEST Snapshots\n* (feature) Link labels!\n\n__4.0.0__ [http://dylanv.blog/2018/01/18/storm-react-diagrams-v4-0-0/](https://dylanvorster.com/storm-react-diagrams-v4-0/)\n\n* (refactor) Events system was completely overhauled\n* (demo) Custom Link Sizes\n* (refactor) Demos are now much more verbose and better managed\n* (update) node packages\n* (bug) Fix #129\n* (feature) Control link creation through ports\n* (refactor) Models are now in seperate files\n* (refactor) Merged the concept of instance factories and widget factories into one\n* (feature) Models can now be cloned at various parts of the model graph\n* (demo) Cloning\n* (feature) models control isLocked\n\n__3.2.0__ [http://dylanv.blog/2017/11/22/storm-react-diagrams-3-2-0/](https://dylanvorster.com/storm-react-diagrams-3-2-0/)\n* (feature) zoom to fit\n* added Circle CI tests\n* (demo) dagre automatic layouts\n* (demo) zoom to fit\n* (demo) selection events\n* (demo) limit number of points\n* (demo) programmatic node updating\n* updated dependencies\n* (bugs) swapping diagram models in engines\n* (bugs) issues with the rendering pipeline #107\n* added ci badge to Readme\n\n__3.1.3__\n* Refactor links slightly\n* use min extension for css\n* bump package versions\n* export more classes\n\n__3.1.2__\n* Hotfix: fix zooming when canvas not in the top left corner\n(https://github.com/projectstorm/react-diagrams/pull/88)\n\n__3.1.0__ [http://dylanv.blog/2017/09/15/storm-react-diagrams-3-1-0/](https://dylanvorster.com/storm-react-diagrams-3-1-0/)\n* Zoom relative to mouse location\n* Fixed links not connecting when grid is larger than port size\n* Prevented points from dragging when connected to a port and the node itself is not selected\n* API fixes\n* Code cleanup\n\n__3.0.0__ [http://dylanv.blog/2017/09/13/storm-react-diagrams-v3/](https://dylanvorster.com/storm-react-diagrams-3-0/)\n* Massive performance updates\n* Complete rewrite\n* Started a changelog and design documents for each revision\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nSee below for guidelines on house keeping:\n\n### Always add a PR\n\nSince the project runs on GitHub, the best way to contribute is to fork and then submit a PR.\nYou will find a template that you will need to fill out\n\n### Adding new demos\n\nAdd a new folder in the ./demos directory and make sure that it is named correctly like the other demos. \nA new demo should conform to the standard of either `demo-simple` in which it contains a markdown file that\nclearly explains 'whats going on', or the code sample should have very clear comments that almost always should ready\nlike an instruction manual such as the simple demo.\n\nFinally, you should link up your demo to the __index.tsx__ file in the __demos__ directory. It should be quite\nself explanatory on how it works, but ultimately I have a helper method that makes it easy to link source code\nto the demo itself, hence the 'require' statements. The third parameter is if you want to place your demo\ninside a markdown guide (again: see simple demo for how that is done).\n\n### Make the demo testable\n\nSimilar procedure, except link your demo in the __index.tsx__ file sitting in the __tests__ directory.\nRunning `yarn run test` will fire up jest (hopefully) and then it will render your demo to a snapshot directory\nwhich when run again (for a second time), should compare the output to the newely generated snapshot. Make sure\nto commit the updated snapshot file with your PR!\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Storm\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Introduction\n\n[![Join the chat at https://gitter.im/projectstorm/react-diagrams](https://badges.gitter.im/projectstorm/react-diagrams.svg)](https://gitter.im/projectstorm/react-diagrams?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![NPM](https://img.shields.io/npm/v/@projectstorm/react-diagrams.svg)](https://npmjs.org/package/@projectstorm/react-diagrams) [![Package Quality](https://npm.packagequality.com/shield/storm-react-diagrams.svg)](https://packagequality.com/#?package=storm-react-diagrams)\n\n![](.gitbook/assets/logo.jpg)\n\n**DEMO**: [http://projectstorm.cloud/react-diagrams](http://projectstorm.cloud/react-diagrams)\n\n**DOCS \\(wip\\)** [https://projectstorm.gitbook.io/react-diagrams](https://projectstorm.gitbook.io/react-diagrams)\n\nDocs are currently being worked on, along with a migration path.\n\n## What\n\nA flow & process orientated diagramming library inspired by **Blender**, **Labview** and **Unreal engine**.\n\n* **Modern Codebase** written entirely in Typescript and React, the library makes use of powerful generics, advanced software engineering principles and is broken up into multiple modules.\n* **Hackable and extensible** the entire library including its core can be extended, rewired and re-assembled into fundamentally different software to suit your own software needs.\n* **HTML nodes as a first class citizen** the library was originally written to represent advanced dynamic nodes, that are difficult to represent as SVG's due to complex input requirements ux requirements.\n* **Designed for process** the library is aimed for software engineers that want to rewire their programs at runtime, and that want to make their software more dynamic.\n* **Fast diagram editing** the defaults provided give the highest priority to editing diagrams as fast as possible.\n\n## Gallery\n\nExample implementation using custom models: \\(Dylan's personal code\\)\n\n![Personal Project](.gitbook/assets/example1.jpg)\n![](.gitbook/assets/example2.jpg)\n\nGet started with the default models right out of the box:\n\n![](.gitbook/assets/example3.jpg)\n\n## Installing\n\nFor all the bells and whistles:\n\n```text\nyarn add @projectstorm/react-diagrams\n```\n\nThis includes all the packages listed below \\(and works \\(mostly and conceptually\\) like it used to in version 5.0\\)\n\n### A more modular approach\n\nThis library now has a more modular design and you can import just the core \\(contains no default factories or routing\\)\n\n```text\nyarn add @projectstorm/react-diagrams-core\n```\n\nthis is built ontop of the evolving **react-canvas-core** library\n\n```text\nyarn add @projectstorm/react-canvas-core\n```\n\nwhich makes use of\n\n```text\nyarn add @projectstorm/geometry\n```\n\nand of course, you can add some extras:\n\n```text\nyarn add @projectstorm/react-diagrams-defaults\nyarn add @projectstorm/react-diagrams-routing\n```\n\n## How to use\n\nBefore running any of the examples, please run `pnpm build` in the root. This project is a monorepo, and the packages (including the demos) require the packages to first be built.\n\n\nTake a look at the [diagram demos](https://github.com/projectstorm/react-diagrams/tree/master/diagrams-demo-gallery/demos)\n\n**or**\n\nTake a look at the [demo project](https://github.com/projectstorm/react-diagrams/tree/master/diagrams-demo-project) which contains an example for ES6 as well as Typescript\n\n**or**\n\n[Checkout the docs](https://projectstorm.gitbook.io/react-diagrams/)\n\n## Run the demos\n\nAfter running `pnpm install` and `pnpm build`, you must then run: `cd diagrams-demo-gallery && pnpm run start`\n\n## Building from source\n\nSimply run `pnpm` then `pnpm build` or `pnpm build:prod` in the root directory and it will spit out the transpiled code and typescript definitions into the dist directory as a single file.\n\n## Built with react-diagrams\n\n> Do you have an interesting project built with *react-diagrams*? PR it into this section for others to see.\n"
  },
  {
    "path": "diagrams-demo-gallery/.babelrc.json",
    "content": "{\n  \"sourceType\": \"unambiguous\",\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"targets\": {\n          \"chrome\": 100,\n          \"safari\": 15,\n          \"firefox\": 91\n        }\n      }\n    ],\n    \"@babel/preset-react\",\n\t\t\"@babel/preset-typescript\"\n  ],\n  \"plugins\": []\n}"
  },
  {
    "path": "diagrams-demo-gallery/.storybook/main.js",
    "content": "module.exports = {\n\tstories: ['../demos/*.stories.tsx'],\n\taddons: ['@storybook/addon-actions', '@storybook/addon-webpack5-compiler-babel'],\n\tframework: '@storybook/react-webpack5'\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/.storybook/manager.js",
    "content": "import { addons } from '@storybook/manager-api';\n\nimport diagramsTheme from './theme';\n\naddons.setConfig({\n\ttheme: diagramsTheme\n});\n"
  },
  {
    "path": "diagrams-demo-gallery/.storybook/preview-head.html",
    "content": "<style>\n\thtml, body, #storybook-root {\n\t\theight: 100%;\n\t}\n</style>"
  },
  {
    "path": "diagrams-demo-gallery/.storybook/preview.js",
    "content": "export const parameters = {\n\tlayout: 'fullscreen'\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/.storybook/theme.js",
    "content": "import { create } from '@storybook/theming';\n\nexport default create({\n\tbase: 'dark',\n\tbrandTitle: 'STORM React Diagrams',\n\tbrandUrl: 'https://github.com/projectstorm/react-diagrams'\n});\n"
  },
  {
    "path": "diagrams-demo-gallery/CHANGELOG.md",
    "content": "# @projectstorm/react-diagrams-gallery\n\n## 7.2.1\n\n### Patch Changes\n\n- adb4415: Fixed the demos\n\n## 7.2.0\n\n### Minor Changes\n\n- 1be4073: Remove setTimeout from demo-dagre to avoid layout breaks\n\n### Patch Changes\n\n- 80285fe: refactor: update lodash imports to use individual functions\n- Updated dependencies [09ed60f]\n- Updated dependencies [20766f5]\n- Updated dependencies [80285fe]\n  - @projectstorm/react-canvas-core@7.0.3\n  - @projectstorm/react-diagrams-core@7.0.3\n  - @projectstorm/react-diagrams-defaults@7.1.3\n  - @projectstorm/react-diagrams@7.0.4\n\n## 7.1.2\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n- Updated dependencies [66c687a]\n  - @projectstorm/react-diagrams-defaults@7.1.2\n  - @projectstorm/react-diagrams-core@7.0.2\n  - @projectstorm/react-canvas-core@7.0.2\n  - @projectstorm/react-diagrams@7.0.3\n\n## 7.1.1\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/react-canvas-core@7.0.1\n  - @projectstorm/react-diagrams@7.0.2\n  - @projectstorm/react-diagrams-core@7.0.1\n  - @projectstorm/react-diagrams-defaults@7.1.1\n\n## 7.1.0\n\n### Minor Changes\n\n- e0d21f1: - [feature] new ability to refresh links in auto distribute system [PR 756](https://github.com/projectstorm/react-diagrams/pull/756)\n\n  - [fix] Default link now uses the correct method for creating a point allowing this to be overridden [PR 939](https://github.com/projectstorm/react-diagrams/pull/939)\n\n  Big thanks to @ToTheHit and @h0111in for your help on these, even though its very delayed on my part :)\n\n### Patch Changes\n\n- Updated dependencies [e0d21f1]\n  - @projectstorm/react-diagrams-defaults@7.1.0\n  - @projectstorm/react-diagrams@7.0.1\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/react-diagrams-defaults@7.0.0\n  - @projectstorm/react-diagrams-core@7.0.0\n  - @projectstorm/react-canvas-core@7.0.0\n  - @projectstorm/react-diagrams@7.0.0\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/1_SimpleUsage.stories.tsx",
    "content": "import { Toolkit } from '@projectstorm/react-canvas-core';\nToolkit.TESTING = true;\n\nexport default {\n\ttitle: 'Simple Usage'\n};\n\nimport demo_simple from './demo-simple';\nimport demo_flow from './demo-simple-flow';\nimport demo_performance from './demo-performance';\nimport demo_locks from './demo-locks';\nimport demo_grid from './demo-grid';\nimport demo_listeners from './demo-listeners';\nimport demo_zoom from './demo-zoom-to-fit';\nimport demo_zoom_nodes from './demo-zoom-to-fit-nodes';\nimport demo_canvas_drag from './demo-canvas-drag';\nimport demo_pan_and_zoom from './demo-pan-and-zoom';\nimport demo_dynamic_ports from './demo-dynamic-ports';\nimport demo_labels from './demo-labelled-links';\n\nexport const DemoSimple = demo_simple;\nexport const SimpleFlowExample = demo_flow;\nexport const PerformanceDemo = demo_performance;\nexport const LockedWidget = demo_locks;\nexport const CanvasGridSize = demo_grid;\nexport const EventsAndListeners = demo_listeners;\nexport const ZoomToFit = demo_zoom;\nexport const ZoomToFitSelectNodes = demo_zoom_nodes;\nexport const CanvasDrag = demo_canvas_drag;\nexport const CanvasPanAndZoom = demo_pan_and_zoom;\nexport const DynamicPorts = demo_dynamic_ports;\nexport const LinksWithLabels = demo_labels;\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/2_AdvancedUsage.stories.tsx",
    "content": "import { Toolkit } from '@projectstorm/react-canvas-core';\nToolkit.TESTING = true;\n\nexport default {\n\ttitle: 'Advanced Usage'\n};\n\nimport demo_adv_clone_selected from './demo-cloning';\nimport demo_adv_ser_des from './demo-serializing';\nimport demo_adv_prog from './demo-mutate-graph';\nimport demo_adv_dnd from './demo-drag-and-drop';\nimport demo_smart_routing from './demo-smart-routing';\nimport demo_right_angles_routing from './demo-right-angles-routing';\nimport demo_alternative_linking from './demo-alternative-linking';\nimport demo_custom_delete_keys from './demo-custom_delete_keys';\n\nexport const CloneSelected = demo_adv_clone_selected;\nexport const SerializingAndDeSerializing = demo_adv_ser_des;\nexport const ProgramaticallyModifyingGraph = demo_adv_prog;\nexport const DragAndDrop = demo_adv_dnd;\nexport const SmartRouting = demo_smart_routing;\nexport const RightAnglesRouting = demo_right_angles_routing;\nexport const LinkingByClickingInsteadOfDragging = demo_alternative_linking;\nexport const SettingCustomDeleteKeys = demo_custom_delete_keys;\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/3_Customization.stories.tsx",
    "content": "import { Toolkit } from '@projectstorm/react-canvas-core';\nToolkit.TESTING = true;\n\nexport default {\n\ttitle: 'Customization'\n};\n\nimport demo_custom_link_label from './demo-custom-link-label';\nimport demo_custom_action from './demo-custom-action';\nimport demo_cust_nodes from './demo-custom-node1';\nimport demo_cust_links from './demo-custom-link1';\nimport demo_cust_links2 from './demo-custom-link2';\n\nexport const CustomDiamondNode = demo_cust_nodes;\nexport const CustomAnimatedLinks = demo_cust_links;\nexport const CustomLinkEndsWithArrows = demo_cust_links2;\nexport const CustomLinkLabel = demo_custom_link_label;\nexport const CustomEvent = demo_custom_action;\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/4_Libraries.stories.tsx",
    "content": "import { Toolkit } from '@projectstorm/react-canvas-core';\nToolkit.TESTING = true;\n\nexport default {\n\ttitle: 'External Libs'\n};\n\nimport demo_3rd_dagre from './demo-dagre';\nimport demo_gsap from './demo-animation';\n\nexport const DagreDistribute = demo_3rd_dagre;\nexport const GsapAnimation = demo_gsap;\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-alternative-linking/CreateLinkState.ts",
    "content": "import { Action, ActionEvent, InputType, State } from '@projectstorm/react-canvas-core';\nimport { PortModel, LinkModel, DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { MouseEvent, KeyboardEvent } from 'react';\n\n/**\n * This state is controlling the creation of a link.\n */\nexport class CreateLinkState extends State<DiagramEngine> {\n\tsourcePort: PortModel;\n\tlink: LinkModel;\n\n\tconstructor() {\n\t\tsuper({ name: 'create-new-link' });\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_UP,\n\t\t\t\tfire: (actionEvent: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(actionEvent);\n\t\t\t\t\tconst {\n\t\t\t\t\t\tevent: { clientX, clientY }\n\t\t\t\t\t} = actionEvent;\n\t\t\t\t\tconst ox = this.engine.getModel().getOffsetX();\n\t\t\t\t\tconst oy = this.engine.getModel().getOffsetY();\n\n\t\t\t\t\tif (element instanceof PortModel && !this.sourcePort) {\n\t\t\t\t\t\tthis.sourcePort = element;\n\n\t\t\t\t\t\t/* would be cool if link creating could be done somewhat like\n                        const link = createLink({\n                            sourcePort: this.sourcePort,\n                            points: [{ x: clientX, y: clientY }, { x: clientX, y: clientY }]\n                        })\n                        */\n\t\t\t\t\t\tconst link = this.sourcePort.createLinkModel();\n\t\t\t\t\t\tlink.setSourcePort(this.sourcePort);\n\t\t\t\t\t\tlink.getFirstPoint().setPosition(clientX - ox, clientY - oy);\n\t\t\t\t\t\tlink.getLastPoint().setPosition(clientX - ox + 20, clientY - oy + 20);\n\n\t\t\t\t\t\tthis.link = this.engine.getModel().addLink(link);\n\t\t\t\t\t} else if (element instanceof PortModel && this.sourcePort && element != this.sourcePort) {\n\t\t\t\t\t\tif (this.sourcePort.canLinkToPort(element)) {\n\t\t\t\t\t\t\tthis.link.setTargetPort(element);\n\t\t\t\t\t\t\telement.reportPosition();\n\t\t\t\t\t\t\tthis.clearState();\n\t\t\t\t\t\t\tthis.eject();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (element === this.link.getLastPoint()) {\n\t\t\t\t\t\tthis.link.point(clientX - ox, clientY - oy, -1);\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_MOVE,\n\t\t\t\tfire: (actionEvent: ActionEvent<React.MouseEvent>) => {\n\t\t\t\t\tif (!this.link) return;\n\t\t\t\t\tconst { event } = actionEvent;\n\t\t\t\t\tthis.link.getLastPoint().setPosition(event.clientX, event.clientY);\n\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.KEY_UP,\n\t\t\t\tfire: (actionEvent: ActionEvent<KeyboardEvent>) => {\n\t\t\t\t\t// on esc press remove any started link and pop back to default state\n\t\t\t\t\tif (actionEvent.event.keyCode === 27) {\n\t\t\t\t\t\tthis.link.remove();\n\t\t\t\t\t\tthis.clearState();\n\t\t\t\t\t\tthis.eject();\n\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\tclearState() {\n\t\tthis.link = undefined;\n\t\tthis.sourcePort = undefined;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-alternative-linking/DefaultState.ts",
    "content": "import { MouseEvent, TouchEvent } from 'react';\nimport {\n\tSelectingState,\n\tState,\n\tAction,\n\tInputType,\n\tActionEvent,\n\tDragCanvasState\n} from '@projectstorm/react-canvas-core';\nimport { PortModel, DiagramEngine, DragDiagramItemsState } from '@projectstorm/react-diagrams-core';\nimport { CreateLinkState } from './CreateLinkState';\n\nexport class DefaultState extends State<DiagramEngine> {\n\tdragCanvas: DragCanvasState;\n\tcreateLink: CreateLinkState;\n\tdragItems: DragDiagramItemsState;\n\n\tconstructor() {\n\t\tsuper({ name: 'starting-state' });\n\t\tthis.childStates = [new SelectingState()];\n\t\tthis.dragCanvas = new DragCanvasState();\n\t\tthis.createLink = new CreateLinkState();\n\t\tthis.dragItems = new DragDiagramItemsState();\n\n\t\t// determine what was clicked on\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(event);\n\n\t\t\t\t\t// the canvas was clicked on, transition to the dragging canvas state\n\t\t\t\t\tif (!element) {\n\t\t\t\t\t\tthis.transitionWithEvent(this.dragCanvas, event);\n\t\t\t\t\t}\n\t\t\t\t\t// initiate dragging a new link\n\t\t\t\t\telse if (element instanceof PortModel) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// move the items (and potentially link points)\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.transitionWithEvent(this.dragItems, event);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\t// touch drags the canvas\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.TOUCH_START,\n\t\t\t\tfire: (event: ActionEvent<TouchEvent>) => {\n\t\t\t\t\tthis.transitionWithEvent(new DragCanvasState(), event);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_UP,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(event);\n\n\t\t\t\t\tif (element instanceof PortModel) this.transitionWithEvent(this.createLink, event);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-alternative-linking/index.tsx",
    "content": "import * as React from 'react';\nimport createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\nimport { DefaultState } from './DefaultState';\n\nexport default () => {\n\tconst engine = createEngine();\n\tconst model = new DiagramModel();\n\n\tconst node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tnode1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\tconst node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tnode2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\tmodel.addAll(node1, node2);\n\n\tengine.setModel(model);\n\n\t// Use this custom \"DefaultState\" instead of the actual default state we get with the engine\n\tengine.getStateMachine().pushState(new DefaultState());\n\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-animation/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport gsap from 'gsap';\nimport { DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Tests the grid size\n */\nclass NodeDelayedPosition extends React.Component<any, any> {\n\tconstructor(props) {\n\t\tsuper(props);\n\t}\n\n\trender() {\n\t\tconst { engine } = this.props;\n\t\treturn (\n\t\t\t<DemoWorkspaceWidget>\n\t\t\t\t<DemoCanvasWidget>\n\t\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t\t</DemoCanvasWidget>\n\t\t\t</DemoWorkspaceWidget>\n\t\t);\n\t}\n}\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine({ repaintDebounceMs: 12 });\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t//3-C) create another default node\n\tvar node3 = new DefaultNodeModel('Node 3', 'rgb(192,255,0)');\n\tnode2.setPosition(200, 300);\n\n\t//3-D) create another default node\n\tvar node4 = new DefaultNodeModel('Node 4', 'rgb(192,255,0)');\n\tnode2.setPosition(400, 400);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1, node3, node4);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\tvar interval = setInterval(() => {\n\t\t[node1, node2, node3, node4].map((node) => {\n\t\t\tvar obj = { x: 0, y: 0 };\n\t\t\tgsap.fromTo(\n\t\t\t\tobj,\n\t\t\t\t{\n\t\t\t\t\tx: node.getPosition().x,\n\t\t\t\t\ty: node.getPosition().y\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tx: Math.floor(Math.random() * 500),\n\t\t\t\t\ty: Math.floor(Math.random() * 500),\n\t\t\t\t\tduration: 0.8,\n\t\t\t\t\tonUpdate: () => {\n\t\t\t\t\t\tnode.setPosition(obj.x, obj.y);\n\t\t\t\t\t\tengine.repaintCanvas();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t});\n\t}, 2000);\n\n\t//6) render the diagram!\n\treturn <NodeDelayedPosition engine={engine} model={model} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-canvas-drag/index.tsx",
    "content": "import * as React from 'react';\nimport createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Tests the drag on/off\n */\nclass CanvasDragToggle extends React.Component<any, any> {\n\tenableDrag = () => {\n\t\tconst { engine } = this.props;\n\t\tconst state = engine.getStateMachine().getCurrentState();\n\t\tstate.dragCanvas.config.allowDrag = true;\n\t};\n\n\tdisableDrag = () => {\n\t\tconst { engine } = this.props;\n\t\tconst state = engine.getStateMachine().getCurrentState();\n\t\tstate.dragCanvas.config.allowDrag = false;\n\t};\n\n\trender() {\n\t\tconst { engine } = this.props;\n\t\treturn (\n\t\t\t<DemoWorkspaceWidget\n\t\t\t\tbuttons={[\n\t\t\t\t\t<DemoButton key={1} onClick={this.enableDrag}>\n\t\t\t\t\t\tEnable canvas drag\n\t\t\t\t\t</DemoButton>,\n\t\t\t\t\t<DemoButton key={2} onClick={this.disableDrag}>\n\t\t\t\t\t\tDisable canvas drag\n\t\t\t\t\t</DemoButton>\n\t\t\t\t]}\n\t\t\t>\n\t\t\t\t<DemoCanvasWidget>\n\t\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t\t</DemoCanvasWidget>\n\t\t\t</DemoWorkspaceWidget>\n\t\t);\n\t}\n}\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn <CanvasDragToggle engine={engine} model={model} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-cloning/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, LinkModel, NodeModel } from '@projectstorm/react-diagrams';\nimport _forEach from 'lodash/forEach';\nimport * as React from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { BaseModel, CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Tests cloning\n */\nclass CloneSelected extends React.Component<any, any> {\n\tconstructor(props: any) {\n\t\tsuper(props);\n\t\tthis.cloneSelected = this.cloneSelected.bind(this);\n\t}\n\n\tcloneSelected() {\n\t\tlet { engine } = this.props;\n\t\tlet offset = { x: 100, y: 100 };\n\t\tlet model = engine.getModel();\n\n\t\tlet itemMap = {};\n\t\t_forEach(model.getSelectedEntities(), (item: BaseModel<any>) => {\n\t\t\tlet newItem = item.clone(itemMap);\n\n\t\t\t// offset the nodes slightly\n\t\t\tif (newItem instanceof NodeModel) {\n\t\t\t\tnewItem.setPosition(newItem.getX() + offset.x, newItem.getY() + offset.y);\n\t\t\t\tmodel.addNode(newItem);\n\t\t\t} else if (newItem instanceof LinkModel) {\n\t\t\t\t// offset the link points\n\t\t\t\tnewItem.getPoints().forEach((p) => {\n\t\t\t\t\tp.setPosition(p.getX() + offset.x, p.getY() + offset.y);\n\t\t\t\t});\n\t\t\t\tmodel.addLink(newItem);\n\t\t\t}\n\t\t\t(newItem as BaseModel).setSelected(false);\n\t\t});\n\n\t\tthis.forceUpdate();\n\t}\n\n\trender() {\n\t\tconst { engine } = this.props;\n\t\treturn (\n\t\t\t<DemoWorkspaceWidget buttons={<DemoButton onClick={this.cloneSelected}>Clone Selected</DemoButton>}>\n\t\t\t\t<DemoCanvasWidget>\n\t\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t\t</DemoCanvasWidget>\n\t\t\t</DemoWorkspaceWidget>\n\t\t);\n\t}\n}\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tlet port = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tlet port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t// link the ports\n\tlet link1 = port.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn <CloneSelected engine={engine} model={model} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-action/index.tsx",
    "content": "import * as React from 'react';\nimport _forEach from 'lodash/forEach';\nimport createEngine, { DiagramModel, DefaultNodeModel, DefaultLinkModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget, Action, ActionEvent, InputType } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\ninterface CustomDeleteItemsActionOptions {\n\tkeyCodes?: number[];\n}\n\n/**\n * Deletes all selected items, but asks for confirmation first\n */\nclass CustomDeleteItemsAction extends Action {\n\tconstructor(options: CustomDeleteItemsActionOptions = {}) {\n\t\toptions = {\n\t\t\tkeyCodes: [46, 8],\n\t\t\t...options\n\t\t};\n\t\tsuper({\n\t\t\ttype: InputType.KEY_DOWN,\n\t\t\tfire: (event: ActionEvent<React.KeyboardEvent>) => {\n\t\t\t\tif (options.keyCodes.indexOf(event.event.keyCode) !== -1) {\n\t\t\t\t\tconst selectedEntities = this.engine.getModel().getSelectedEntities();\n\t\t\t\t\tif (selectedEntities.length > 0) {\n\t\t\t\t\t\tconst confirm = window.confirm('Are you sure you want to delete?');\n\n\t\t\t\t\t\tif (confirm) {\n\t\t\t\t\t\t\t_forEach(selectedEntities, (model) => {\n\t\t\t\t\t\t\t\t// only delete items which are not locked\n\t\t\t\t\t\t\t\tif (!model.isLocked()) {\n\t\t\t\t\t\t\t\t\tmodel.remove();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\nexport default () => {\n\t// create an engine without registering DeleteItemsAction\n\tconst engine = createEngine({ registerDefaultDeleteItemsAction: false });\n\tconst model = new DiagramModel();\n\n\tconst node1 = new DefaultNodeModel({ name: 'Node 1', color: 'rgb(0,192,255)' });\n\tnode1.setPosition(100, 100);\n\tconst port1 = node1.addOutPort('Out');\n\n\tconst node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tconst port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\tconst link1 = port1.link<DefaultLinkModel>(port2);\n\tlink1.getOptions().testName = 'Test';\n\tlink1.addLabel('Hello World!');\n\n\tmodel.addAll(node1, node2, link1);\n\n\tengine.setModel(model);\n\n\t// register an DeleteItemsAction with custom keyCodes (in this case, only Delete key)\n\tengine.getActionEventBus().registerAction(new CustomDeleteItemsAction());\n\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-link-label/EditableLabelFactory.tsx",
    "content": "import * as React from 'react';\nimport { AbstractReactFactory, GenerateWidgetEvent } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams';\n\nimport { EditableLabelModel } from './EditableLabelModel';\nimport { EditableLabelWidget } from './EditableLabelWidget';\nimport { JSX } from 'react';\n\nexport class EditableLabelFactory extends AbstractReactFactory<EditableLabelModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('editable-label');\n\t}\n\n\tgenerateModel(): EditableLabelModel {\n\t\treturn new EditableLabelModel();\n\t}\n\n\tgenerateReactWidget(event: GenerateWidgetEvent<EditableLabelModel>): JSX.Element {\n\t\treturn <EditableLabelWidget model={event.model} />;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-link-label/EditableLabelModel.ts",
    "content": "import { LabelModel } from '@projectstorm/react-diagrams';\nimport { BaseModelOptions, DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport interface EditableLabelOptions extends BaseModelOptions {\n\tvalue?: string;\n}\n\nexport class EditableLabelModel extends LabelModel {\n\tvalue: string;\n\n\tconstructor(options: EditableLabelOptions = {}) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\ttype: 'editable-label'\n\t\t});\n\t\tthis.value = options.value || '';\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tvalue: this.value\n\t\t};\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>): void {\n\t\tsuper.deserialize(event);\n\t\tthis.value = event.data.value;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-link-label/EditableLabelWidget.tsx",
    "content": "import * as React from 'react';\n\nimport { EditableLabelModel } from './EditableLabelModel';\nimport styled from '@emotion/styled';\nimport { action } from '@storybook/addon-actions';\n\nexport interface FlowAliasLabelWidgetProps {\n\tmodel: EditableLabelModel;\n}\n\nnamespace S {\n\t// NOTE: this CSS rules allows to interact with elements in label\n\texport const Label = styled.div`\n\t\tuser-select: none;\n\t\tpointer-events: auto;\n\t`;\n}\n\n// now we can render all what we want in the label\nexport const EditableLabelWidget: React.FunctionComponent<FlowAliasLabelWidgetProps> = (props) => {\n\tconst [str, setStr] = React.useState(props.model.value);\n\n\treturn (\n\t\t<S.Label>\n\t\t\t<input\n\t\t\t\tvalue={str}\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\tconst newVal = event.target.value;\n\n\t\t\t\t\t// update value both in internal component state\n\t\t\t\t\tsetStr(newVal);\n\t\t\t\t\t// and in model object\n\t\t\t\t\tprops.model.value = newVal;\n\t\t\t\t}}\n\t\t\t/>\n\n\t\t\t<button onClick={() => action('model eventDidFire')('You clicked the button')}>Click me!</button>\n\t\t</S.Label>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-link-label/index.tsx",
    "content": "import * as React from 'react';\nimport createEngine, { DefaultNodeModel, DiagramModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nimport { EditableLabelFactory } from './EditableLabelFactory';\nimport { EditableLabelModel } from './EditableLabelModel';\n\n/**\n * @Author Shumaf Lovpache (aka Soarex16)\n */\n\nexport default () => {\n\t// engine setup\n\tconst engine = createEngine();\n\n\t// register our label factory\n\tengine.getLabelFactories().registerFactory(new EditableLabelFactory());\n\n\t// setup diagram model\n\tconst model = new DiagramModel();\n\n\t// create some nodes\n\tconst node1 = new DefaultNodeModel('Node1', 'red');\n\tconst port1 = node1.addOutPort('out');\n\tnode1.setPosition(250, 100);\n\n\tconst node2 = new DefaultNodeModel('Node2', 'green');\n\tconst port2 = node2.addInPort('in');\n\tnode2.setPosition(800, 300);\n\n\t// link nodes together\n\tconst link1 = port1.link(port2);\n\n\t// !!!\n\t// add our custom label to link\n\tlink1.addLabel(\n\t\tnew EditableLabelModel({\n\t\t\tvalue: 'Hello, I am label!'\n\t\t})\n\t);\n\n\t// add models to the root graph\n\tmodel.addAll(node1, port1, node2, port2, link1);\n\n\t// load model into engine\n\tengine.setModel(model);\n\n\t// render diagram\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-link1/index.tsx",
    "content": "import createEngine, {\n\tDiagramModel,\n\tDefaultNodeModel,\n\tDefaultPortModel,\n\tDefaultLinkFactory,\n\tDefaultLinkModel\n} from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport class AdvancedLinkModel extends DefaultLinkModel {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'advanced',\n\t\t\twidth: 10\n\t\t});\n\t}\n}\n\nexport class AdvancedPortModel extends DefaultPortModel {\n\tcreateLinkModel(): AdvancedLinkModel | null {\n\t\treturn new AdvancedLinkModel();\n\t}\n}\n\nexport class AdvancedLinkSegment extends React.Component<{ model: AdvancedLinkModel; path: string }> {\n\tpath: SVGPathElement;\n\tcircle: SVGCircleElement;\n\tcallback: () => any;\n\tpercent: number;\n\thandle: any;\n\tmounted: boolean;\n\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.percent = 0;\n\t}\n\n\tcomponentDidMount() {\n\t\tthis.mounted = true;\n\t\tthis.callback = () => {\n\t\t\tif (!this.circle || !this.path) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.percent += 2;\n\t\t\tif (this.percent > 100) {\n\t\t\t\tthis.percent = 0;\n\t\t\t}\n\n\t\t\tlet point = this.path.getPointAtLength(this.path.getTotalLength() * (this.percent / 100.0));\n\n\t\t\tthis.circle.setAttribute('cx', '' + point.x);\n\t\t\tthis.circle.setAttribute('cy', '' + point.y);\n\n\t\t\tif (this.mounted) {\n\t\t\t\trequestAnimationFrame(this.callback);\n\t\t\t}\n\t\t};\n\t\trequestAnimationFrame(this.callback);\n\t}\n\n\tcomponentWillUnmount() {\n\t\tthis.mounted = false;\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<path\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tref={(ref) => {\n\t\t\t\t\t\tthis.path = ref;\n\t\t\t\t\t}}\n\t\t\t\t\tstrokeWidth={this.props.model.getOptions().width}\n\t\t\t\t\tstroke=\"rgba(255,0,0,0.5)\"\n\t\t\t\t\td={this.props.path}\n\t\t\t\t/>\n\t\t\t\t<circle\n\t\t\t\t\tref={(ref) => {\n\t\t\t\t\t\tthis.circle = ref;\n\t\t\t\t\t}}\n\t\t\t\t\tr={10}\n\t\t\t\t\tfill=\"orange\"\n\t\t\t\t/>\n\t\t\t</>\n\t\t);\n\t}\n}\n\nexport class AdvancedLinkFactory extends DefaultLinkFactory {\n\tconstructor() {\n\t\tsuper('advanced');\n\t}\n\n\tgenerateModel(): AdvancedLinkModel {\n\t\treturn new AdvancedLinkModel();\n\t}\n\n\tgenerateLinkSegment(model: AdvancedLinkModel, selected: boolean, path: string) {\n\t\treturn (\n\t\t\t<g>\n\t\t\t\t<AdvancedLinkSegment model={model} path={path} />\n\t\t\t</g>\n\t\t);\n\t}\n}\n/**\n *\n * Simple link styling demo\n *\n * @Author kfrajtak\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\tengine.getLinkFactories().registerFactory(new AdvancedLinkFactory());\n\n\t// create some nodes\n\tvar node1 = new DefaultNodeModel('Source', 'rgb(0,192,255)');\n\tlet port1 = node1.addPort(new AdvancedPortModel(false, 'out-1', 'Out thick'));\n\tlet port2 = node1.addPort(new DefaultPortModel(false, 'out-2', 'Out default'));\n\tnode1.setPosition(100, 100);\n\n\tvar node2 = new DefaultNodeModel('Target', 'rgb(192,255,0)');\n\tvar port3 = node2.addPort(new AdvancedPortModel(true, 'in-1', 'In thick'));\n\tvar port4 = node2.addPort(new DefaultPortModel(true, 'in-2', 'In default'));\n\tnode2.setPosition(300, 100);\n\n\tvar node3 = new DefaultNodeModel('Source', 'rgb(0,192,255)');\n\tnode3.addPort(new AdvancedPortModel(false, 'out-1', 'Out thick'));\n\tnode3.addPort(new DefaultPortModel(false, 'out-2', 'Out default'));\n\tnode3.setPosition(100, 200);\n\n\tvar node4 = new DefaultNodeModel('Target', 'rgb(192,255,0)');\n\tnode4.addPort(new AdvancedPortModel(true, 'in-1', 'In thick'));\n\tnode4.addPort(new DefaultPortModel(true, 'in-2', 'In default'));\n\tnode4.setPosition(300, 200);\n\n\tvar model = new DiagramModel();\n\n\tmodel.addAll(port1.link(port3), port2.link(port4));\n\n\t// add everything else\n\tmodel.addAll(node1, node2, node3, node4);\n\n\t// load model into engine\n\tengine.setModel(model);\n\n\t// render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-link2/index.tsx",
    "content": "import createEngine, {\n\tDiagramModel,\n\tDefaultNodeModel,\n\tDefaultPortModel,\n\tDefaultLinkFactory,\n\tDefaultLinkModel,\n\tDefaultLinkWidget\n} from '@projectstorm/react-diagrams';\nimport { LinkWidget, PointModel } from '@projectstorm/react-diagrams-core';\nimport * as React from 'react';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\nimport { JSX, MouseEvent } from 'react';\nimport { DefaultLinkPointWidget, DefaultLinkSegmentWidget } from '@projectstorm/react-diagrams-defaults/dist';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core/dist';\n\nexport class AdvancedLinkModel extends DefaultLinkModel {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'advanced',\n\t\t\twidth: 4\n\t\t});\n\t}\n}\n\nexport class AdvancedPortModel extends DefaultPortModel {\n\tcreateLinkModel(): AdvancedLinkModel | null {\n\t\treturn new AdvancedLinkModel();\n\t}\n}\n\nconst CustomLinkArrowWidget = (props) => {\n\tconst { point, previousPoint } = props;\n\n\tconst angle =\n\t\t90 +\n\t\t(Math.atan2(\n\t\t\tpoint.getPosition().y - previousPoint.getPosition().y,\n\t\t\tpoint.getPosition().x - previousPoint.getPosition().x\n\t\t) *\n\t\t\t180) /\n\t\t\tMath.PI;\n\n\t//translate(50, -10),\n\treturn (\n\t\t<g className=\"arrow\" transform={'translate(' + point.getPosition().x + ', ' + point.getPosition().y + ')'}>\n\t\t\t<g style={{ transform: 'rotate(' + angle + 'deg)' }}>\n\t\t\t\t<g transform={'translate(0, -3)'}>\n\t\t\t\t\t<polygon\n\t\t\t\t\t\tpoints=\"0,10 8,30 -8,30\"\n\t\t\t\t\t\tfill={props.color}\n\t\t\t\t\t\tdata-id={point.getID()}\n\t\t\t\t\t\tdata-linkid={point.getLink().getID()}\n\t\t\t\t\t/>\n\t\t\t\t</g>\n\t\t\t</g>\n\t\t</g>\n\t);\n};\n\nexport interface AdvancedLinkWWidgetProps {\n\tlink: DefaultLinkModel;\n\tdiagramEngine: DiagramEngine;\n\tpointAdded?: (point: PointModel, event: MouseEvent) => any;\n\trenderPoints?: boolean;\n\tselected?: (event: MouseEvent) => any;\n}\n\nexport class AdvancedLinkWidget extends React.Component<AdvancedLinkWWidgetProps> {\n\tgeneratePoint = (point: PointModel): JSX.Element => {\n\t\treturn (\n\t\t\t<DefaultLinkPointWidget\n\t\t\t\tkey={point.getID()}\n\t\t\t\tpoint={point as any}\n\t\t\t\tcolorSelected={this.props.link.getOptions().selectedColor ?? ''}\n\t\t\t\tcolor={this.props.link.getOptions().color}\n\t\t\t/>\n\t\t);\n\t};\n\n\tgenerateLink = (path: string, extraProps: any, id: string | number): JSX.Element => {\n\t\treturn (\n\t\t\t<DefaultLinkSegmentWidget\n\t\t\t\tkey={`link-${id}`}\n\t\t\t\tpath={path}\n\t\t\t\tdiagramEngine={this.props.diagramEngine}\n\t\t\t\tfactory={this.props.diagramEngine.getFactoryForLink(this.props.link)}\n\t\t\t\tlink={this.props.link}\n\t\t\t\textras={extraProps}\n\t\t\t/>\n\t\t);\n\t};\n\n\taddPointToLink = (event: MouseEvent, index: number) => {\n\t\tif (\n\t\t\t!event.shiftKey &&\n\t\t\t!this.props.link.isLocked() &&\n\t\t\tthis.props.link.getPoints().length - 1 <= this.props.diagramEngine.getMaxNumberPointsPerLink()\n\t\t) {\n\t\t\tconst position = this.props.diagramEngine.getRelativeMousePoint(event);\n\t\t\tconst point = this.props.link.point(position.x, position.y, index);\n\t\t\tevent.persist();\n\t\t\tevent.stopPropagation();\n\t\t\tthis.props.diagramEngine.getActionEventBus().fireAction({\n\t\t\t\tevent,\n\t\t\t\tmodel: point\n\t\t\t});\n\t\t}\n\t};\n\n\tgenerateArrow(point: PointModel, previousPoint: PointModel): JSX.Element {\n\t\treturn (\n\t\t\t<CustomLinkArrowWidget\n\t\t\t\tkey={point.getID()}\n\t\t\t\tpoint={point as any}\n\t\t\t\tpreviousPoint={previousPoint as any}\n\t\t\t\tcolorSelected={this.props.link.getOptions().selectedColor}\n\t\t\t\tcolor={this.props.link.getOptions().color}\n\t\t\t/>\n\t\t);\n\t}\n\n\trender() {\n\t\t//ensure id is present for all points on the path\n\t\tvar points = this.props.link.getPoints();\n\t\tvar paths = [];\n\n\t\t//draw the multiple anchors and complex line instead\n\t\tfor (let j = 0; j < points.length - 1; j++) {\n\t\t\tpaths.push(\n\t\t\t\tthis.generateLink(\n\t\t\t\t\tLinkWidget.generateLinePath(points[j], points[j + 1]),\n\t\t\t\t\t{\n\t\t\t\t\t\t'data-linkid': this.props.link.getID(),\n\t\t\t\t\t\t'data-point': j,\n\t\t\t\t\t\tonMouseDown: (event: MouseEvent) => {\n\t\t\t\t\t\t\tthis.addPointToLink(event, j + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tj\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\t//render the circles\n\t\tfor (let i = 1; i < points.length - 1; i++) {\n\t\t\tpaths.push(this.generatePoint(points[i]));\n\t\t}\n\n\t\tif (this.props.link.getTargetPort() !== null) {\n\t\t\tpaths.push(this.generateArrow(points[points.length - 1], points[points.length - 2]));\n\t\t} else {\n\t\t\tpaths.push(this.generatePoint(points[points.length - 1]));\n\t\t}\n\n\t\treturn <g data-default-link-test={this.props.link.getOptions().testName}>{paths}</g>;\n\t}\n}\n\nexport class AdvancedLinkFactory extends DefaultLinkFactory {\n\tconstructor() {\n\t\tsuper('advanced');\n\t}\n\n\tgenerateModel(): AdvancedLinkModel {\n\t\treturn new AdvancedLinkModel();\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <AdvancedLinkWidget link={event.model} diagramEngine={this.engine} />;\n\t}\n}\n\n/**\n *\n * Simple link styling demo\n *\n * @Author kfrajtak\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\tengine.getLinkFactories().registerFactory(new AdvancedLinkFactory());\n\n\t// create some nodes\n\tvar node1 = new DefaultNodeModel('Source', 'rgb(0,192,255)');\n\tlet port1 = node1.addPort(new AdvancedPortModel(false, 'out'));\n\tnode1.setPosition(100, 100);\n\n\tvar node2 = new DefaultNodeModel('Target', 'rgb(192,255,0)');\n\tvar port2 = node2.addPort(new AdvancedPortModel(true, 'in'));\n\tnode2.setPosition(500, 350);\n\n\tvar node3 = new DefaultNodeModel('Source', 'rgb(0,192,255)');\n\tlet port3 = node3.addPort(new AdvancedPortModel(false, 'out'));\n\tnode3.setPosition(100, 500);\n\n\tvar node4 = new DefaultNodeModel('Target', 'rgb(192,255,0)');\n\tvar port4 = node4.addPort(new AdvancedPortModel(true, 'in'));\n\tnode4.setPosition(500, 450);\n\n\tvar model = new DiagramModel();\n\n\tmodel.addAll(port1.link(port2), port3.link(port4));\n\n\t// add everything else\n\tmodel.addAll(node1, node2, node3, node4);\n\n\t// load model into engine\n\tengine.setModel(model);\n\n\t// render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeFactory.tsx",
    "content": "import { DiamondNodeWidget } from './DiamondNodeWidget';\nimport { DiamondNodeModel } from './DiamondNodeModel';\nimport * as React from 'react';\nimport { AbstractReactFactory } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { JSX } from 'react';\n\nexport class DiamondNodeFactory extends AbstractReactFactory<DiamondNodeModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('diamond');\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <DiamondNodeWidget engine={this.engine} size={50} node={event.model} />;\n\t}\n\n\tgenerateModel(event) {\n\t\treturn new DiamondNodeModel();\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeModel.ts",
    "content": "import { NodeModel, NodeModelGenerics, PortModelAlignment } from '@projectstorm/react-diagrams';\nimport { DiamondPortModel } from './DiamondPortModel';\n\nexport interface DiamondNodeModelGenerics {\n\tPORT: DiamondPortModel;\n}\n\nexport class DiamondNodeModel extends NodeModel<NodeModelGenerics & DiamondNodeModelGenerics> {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'diamond'\n\t\t});\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.TOP));\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.LEFT));\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.BOTTOM));\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.RIGHT));\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-node1/DiamondNodeWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiamondNodeModel } from './DiamondNodeModel';\nimport { DiagramEngine, PortModelAlignment, PortWidget } from '@projectstorm/react-diagrams';\nimport styled from '@emotion/styled';\n\nexport interface DiamondNodeWidgetProps {\n\tnode: DiamondNodeModel;\n\tengine: DiagramEngine;\n\tsize?: number;\n}\n\nnamespace S {\n\texport const Port = styled.div`\n\t\twidth: 16px;\n\t\theight: 16px;\n\t\tz-index: 10;\n\t\tbackground: rgba(0, 0, 0, 0.5);\n\t\tborder-radius: 8px;\n\t\tcursor: pointer;\n\n\t\t&:hover {\n\t\t\tbackground: rgba(0, 0, 0, 1);\n\t\t}\n\t`;\n}\n\n/**\n * @author Dylan Vorster\n */\nexport class DiamondNodeWidget extends React.Component<DiamondNodeWidgetProps> {\n\trender() {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={'diamond-node'}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'relative',\n\t\t\t\t\twidth: this.props.size,\n\t\t\t\t\theight: this.props.size\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\twidth={this.props.size}\n\t\t\t\t\theight={this.props.size}\n\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t__html:\n\t\t\t\t\t\t\t`\n          <g id=\"Layer_1\">\n          </g>\n          <g id=\"Layer_2\">\n            <polygon fill=\"mediumpurple\" stroke=\"${\n\t\t\t\t\t\t\tthis.props.node.isSelected() ? 'white' : '#000000'\n\t\t\t\t\t\t}\" stroke-width=\"3\" stroke-miterlimit=\"10\" points=\"10,` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t` ` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t`,10 ` +\n\t\t\t\t\t\t\t(this.props.size - 10) +\n\t\t\t\t\t\t\t`,` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t` ` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t`,` +\n\t\t\t\t\t\t\t(this.props.size - 10) +\n\t\t\t\t\t\t\t` \"/>\n          </g>\n        `\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\ttop: this.props.size / 2 - 8,\n\t\t\t\t\t\tleft: -8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.LEFT)}\n\t\t\t\t\tengine={this.props.engine}\n\t\t\t\t>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tleft: this.props.size / 2 - 8,\n\t\t\t\t\t\ttop: -8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.TOP)}\n\t\t\t\t\tengine={this.props.engine}\n\t\t\t\t>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tleft: this.props.size - 8,\n\t\t\t\t\t\ttop: this.props.size / 2 - 8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.RIGHT)}\n\t\t\t\t\tengine={this.props.engine}\n\t\t\t\t>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tleft: this.props.size / 2 - 8,\n\t\t\t\t\t\ttop: this.props.size - 8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.BOTTOM)}\n\t\t\t\t\tengine={this.props.engine}\n\t\t\t\t>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-node1/DiamondPortModel.ts",
    "content": "import { LinkModel, PortModel, DefaultLinkModel, PortModelAlignment } from '@projectstorm/react-diagrams';\n\nexport class DiamondPortModel extends PortModel {\n\tconstructor(alignment: PortModelAlignment) {\n\t\tsuper({\n\t\t\ttype: 'diamond',\n\t\t\tname: alignment,\n\t\t\talignment: alignment\n\t\t});\n\t}\n\n\tcreateLinkModel(): LinkModel {\n\t\treturn new DefaultLinkModel();\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-node1/SimplePortFactory.ts",
    "content": "import { DiagramEngine, PortModel } from '@projectstorm/react-diagrams';\nimport { AbstractModelFactory } from '@projectstorm/react-canvas-core';\n\nexport class SimplePortFactory extends AbstractModelFactory<PortModel, DiagramEngine> {\n\tcb: (initialConfig?: any) => PortModel;\n\n\tconstructor(type: string, cb: (initialConfig?: any) => PortModel) {\n\t\tsuper(type);\n\t\tthis.cb = cb;\n\t}\n\n\tgenerateModel(event): PortModel {\n\t\treturn this.cb(event.initialConfig);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom-node1/index.tsx",
    "content": "import createEngine, { DefaultNodeModel, DiagramModel, PortModelAlignment } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\n// import the custom models\nimport { DiamondNodeModel } from './DiamondNodeModel';\nimport { DiamondNodeFactory } from './DiamondNodeFactory';\nimport { SimplePortFactory } from './SimplePortFactory';\nimport { DiamondPortModel } from './DiamondPortModel';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * @Author Dylan Vorster\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t// register some other factories as well\n\tengine\n\t\t.getPortFactories()\n\t\t.registerFactory(new SimplePortFactory('diamond', (config) => new DiamondPortModel(PortModelAlignment.LEFT)));\n\tengine.getNodeFactories().registerFactory(new DiamondNodeFactory());\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 200);\n\n\t//3-B) create our new custom node\n\tvar node2 = new DiamondNodeModel();\n\tnode2.setPosition(250, 108);\n\n\tvar node3 = new DefaultNodeModel('Node 3', 'red');\n\tvar port3 = node3.addInPort('In');\n\tnode3.setPosition(500, 100);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(node2.getPort(PortModelAlignment.LEFT));\n\tvar link2 = port3.link(node2.getPort(PortModelAlignment.RIGHT));\n\n\tvar node4 = new DefaultNodeModel('Node 4', 'rgb(0,192,255)');\n\tvar port4 = node4.addOutPort('Out');\n\tnode4.setPosition(200, 10);\n\n\tvar link3 = port4.link(node2.getPort(PortModelAlignment.TOP));\n\n\tvar node5 = new DefaultNodeModel('Node 5', 'mediumpurple');\n\tvar port5 = node5.addInPort('In');\n\tnode5.setPosition(400, 300);\n\n\tvar link4 = port5.link(node2.getPort(PortModelAlignment.BOTTOM));\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, node3, link1, link2, node4, link3, link4, node5);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-custom_delete_keys/index.tsx",
    "content": "import * as React from 'react';\nimport createEngine, { DiagramModel, DefaultNodeModel, DefaultLinkModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget, DeleteItemsAction } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport default () => {\n\t// create an engine without registering DeleteItemsAction\n\tconst engine = createEngine({ registerDefaultDeleteItemsAction: false });\n\tconst model = new DiagramModel();\n\n\tconst node1 = new DefaultNodeModel({ name: 'Node 1', color: 'rgb(0,192,255)' });\n\tnode1.setPosition(100, 100);\n\tconst port1 = node1.addOutPort('Out');\n\n\tconst node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tconst port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\tconst link1 = port1.link<DefaultLinkModel>(port2);\n\tlink1.getOptions().testName = 'Test';\n\tlink1.addLabel('Hello World!');\n\n\tmodel.addAll(node1, node2, link1);\n\n\tengine.setModel(model);\n\n\t// register an DeleteItemsAction with custom keyCodes (in this case, only Delete key)\n\tengine.getActionEventBus().registerAction(new DeleteItemsAction({ keyCodes: [46] }));\n\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-dagre/index.tsx",
    "content": "import createEngine, {\n\tDiagramModel,\n\tDefaultNodeModel,\n\tDefaultPortModel,\n\tNodeModel,\n\tDagreEngine,\n\tDiagramEngine,\n\tPathFindingLinkFactory\n} from '@projectstorm/react-diagrams';\nimport { useLayoutEffect, useRef } from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nfunction createNode(name): any {\n\treturn new DefaultNodeModel(name, 'rgb(0,192,255)');\n}\n\nlet count = 0;\n\nfunction connectNodes(nodeFrom, nodeTo, engine: DiagramEngine) {\n\t//just to get id-like structure\n\tcount++;\n\tconst portOut = nodeFrom.addPort(new DefaultPortModel(true, `${nodeFrom.name}-out-${count}`, 'Out'));\n\tconst portTo = nodeTo.addPort(new DefaultPortModel(false, `${nodeFrom.name}-to-${count}`, 'IN'));\n\treturn portOut.link(portTo);\n\n\t// ################# UNCOMMENT THIS LINE FOR PATH FINDING #############################\n\t// return portOut.link(portTo, engine.getLinkFactories().getFactory(PathFindingLinkFactory.NAME));\n\t// #####################################################################################\n}\n\n/**\n * Tests auto distribution\n */\nfunction genDagreEngine() {\n\treturn new DagreEngine({\n\t\tgraph: {\n\t\t\trankdir: 'RL',\n\t\t\tranker: 'longest-path',\n\t\t\tmarginx: 25,\n\t\t\tmarginy: 25\n\t\t},\n\t\tincludeLinks: true,\n\t\tnodeMargin: 25\n\t});\n}\n\nfunction autoDistribute(engine: DiagramEngine) {\n\tconst model = engine.getModel();\n\n\tconst dagreEngine = genDagreEngine();\n\tdagreEngine.redistribute(model);\n\n\treroute(engine);\n\tengine.repaintCanvas();\n}\n\nfunction autoRefreshLinks(engine: DiagramEngine) {\n\tconst model = engine.getModel();\n\n\tconst dagreEngine = genDagreEngine();\n\tdagreEngine.refreshLinks(model);\n\n\t// only happens if pathfing is enabled (check line 29)\n\treroute(engine);\n\tengine.repaintCanvas();\n}\n\nfunction reroute(engine: DiagramEngine) {\n\tengine.getLinkFactories().getFactory<PathFindingLinkFactory>(PathFindingLinkFactory.NAME).calculateRoutingMatrix();\n}\n\nfunction DemoWidget(props) {\n\tconst engine = props.engine;\n\n\tuseLayoutEffect(() => {\n\t\tautoDistribute(engine);\n\t}, []);\n\n\tconst redistribute = () => {\n\t\tautoDistribute(engine);\n\t};\n\n\tconst refreshLinks = () => {\n\t\tautoRefreshLinks(engine);\n\t};\n\n\treturn (\n\t\t<DemoWorkspaceWidget\n\t\t\tbuttons={\n\t\t\t\t<div>\n\t\t\t\t\t<DemoButton onClick={redistribute}>Re-distribute</DemoButton>\n\t\t\t\t\t<DemoButton onClick={refreshLinks}>Refresh Links</DemoButton>\n\t\t\t\t</div>\n\t\t\t}\n\t\t>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n}\n\nexport default () => {\n\t//1) setup the diagram engine\n\tconst engineRef = useRef(createEngine());\n\tlet engine = engineRef.current;\n\n\t//2) setup the diagram model\n\tlet model = new DiagramModel();\n\n\t//3) create a default nodes\n\tlet nodesFrom: NodeModel[] = [];\n\tlet nodesTo: NodeModel[] = [];\n\n\tnodesFrom.push(createNode('from-1'));\n\tnodesFrom.push(createNode('from-2'));\n\tnodesFrom.push(createNode('from-3'));\n\n\tnodesTo.push(createNode('to-1'));\n\tnodesTo.push(createNode('to-2'));\n\tnodesTo.push(createNode('to-3'));\n\n\t//4) link nodes together\n\tlet links = nodesFrom.map((node, index) => {\n\t\treturn connectNodes(node, nodesTo[index], engine);\n\t});\n\n\t// more links for more complicated diagram\n\tlinks.push(connectNodes(nodesTo[0], nodesTo[1], engine));\n\tlinks.push(connectNodes(nodesTo[1], nodesTo[2], engine));\n\tlinks.push(connectNodes(nodesTo[0], nodesTo[2], engine));\n\tlinks.push(connectNodes(nodesFrom[0], nodesFrom[2], engine));\n\tlinks.push(connectNodes(nodesFrom[0], nodesTo[2], engine));\n\n\t// initial random position\n\tnodesFrom.forEach((node, index) => {\n\t\tnode.setPosition(index * 70, index * 70);\n\t\tmodel.addNode(node);\n\t});\n\n\tnodesTo.forEach((node, index) => {\n\t\tnode.setPosition(index * 70, 100);\n\t\tmodel.addNode(node);\n\t});\n\n\tlinks.forEach((link) => {\n\t\tmodel.addLink(link);\n\t});\n\n\tengine.setModel(model);\n\n\treturn <DemoWidget model={model} engine={engine} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-drag-and-drop/Application.ts",
    "content": "import * as SRD from '@projectstorm/react-diagrams';\n\n/**\n * @author Dylan Vorster\n */\nexport class Application {\n\tprotected activeModel: SRD.DiagramModel;\n\tprotected diagramEngine: SRD.DiagramEngine;\n\n\tconstructor() {\n\t\tthis.diagramEngine = SRD.default();\n\t\tthis.newModel();\n\t}\n\n\tpublic newModel() {\n\t\tthis.activeModel = new SRD.DiagramModel();\n\t\tthis.diagramEngine.setModel(this.activeModel);\n\n\t\t//3-A) create a default node\n\t\tvar node1 = new SRD.DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\t\tlet port = node1.addOutPort('Out');\n\t\tnode1.setPosition(100, 100);\n\n\t\t//3-B) create another default node\n\t\tvar node2 = new SRD.DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\t\tlet port2 = node2.addInPort('In');\n\t\tnode2.setPosition(400, 100);\n\n\t\t// link the ports\n\t\tlet link1 = port.link(port2);\n\n\t\tthis.activeModel.addAll(node1, node2, link1);\n\t}\n\n\tpublic getActiveDiagram(): SRD.DiagramModel {\n\t\treturn this.activeModel;\n\t}\n\n\tpublic getDiagramEngine(): SRD.DiagramEngine {\n\t\treturn this.diagramEngine;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-drag-and-drop/components/BodyWidget.tsx",
    "content": "import * as React from 'react';\nimport _keys from 'lodash/keys';\nimport { TrayWidget } from './TrayWidget';\nimport { Application } from '../Application';\nimport { TrayItemWidget } from './TrayItemWidget';\nimport { DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../../helpers/DemoCanvasWidget';\nimport styled from '@emotion/styled';\n\nexport interface BodyWidgetProps {\n\tapp: Application;\n}\n\nnamespace S {\n\texport const Body = styled.div`\n\t\tflex-grow: 1;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tmin-height: 100%;\n\t`;\n\n\texport const Header = styled.div`\n\t\tdisplay: flex;\n\t\tbackground: rgb(30, 30, 30);\n\t\tflex-grow: 0;\n\t\tflex-shrink: 0;\n\t\tcolor: white;\n\t\tfont-family: Helvetica, Arial, sans-serif;\n\t\tpadding: 10px;\n\t\talign-items: center;\n\t`;\n\n\texport const Content = styled.div`\n\t\tdisplay: flex;\n\t\tflex-grow: 1;\n\t`;\n\n\texport const Layer = styled.div`\n\t\tposition: relative;\n\t\tflex-grow: 1;\n\t`;\n}\n\nexport class BodyWidget extends React.Component<BodyWidgetProps> {\n\trender() {\n\t\treturn (\n\t\t\t<S.Body>\n\t\t\t\t<S.Header>\n\t\t\t\t\t<div className=\"title\">Storm React Diagrams - DnD demo</div>\n\t\t\t\t</S.Header>\n\t\t\t\t<S.Content>\n\t\t\t\t\t<TrayWidget>\n\t\t\t\t\t\t<TrayItemWidget model={{ type: 'in' }} name=\"In Node\" color=\"rgb(192,255,0)\" />\n\t\t\t\t\t\t<TrayItemWidget model={{ type: 'out' }} name=\"Out Node\" color=\"rgb(0,192,255)\" />\n\t\t\t\t\t</TrayWidget>\n\t\t\t\t\t<S.Layer\n\t\t\t\t\t\tonDrop={(event) => {\n\t\t\t\t\t\t\tvar data = JSON.parse(event.dataTransfer.getData('storm-diagram-node'));\n\t\t\t\t\t\t\tvar nodesCount = _keys(this.props.app.getDiagramEngine().getModel().getNodes()).length;\n\n\t\t\t\t\t\t\tvar node: DefaultNodeModel = null;\n\t\t\t\t\t\t\tif (data.type === 'in') {\n\t\t\t\t\t\t\t\tnode = new DefaultNodeModel('Node ' + (nodesCount + 1), 'rgb(192,255,0)');\n\t\t\t\t\t\t\t\tnode.addInPort('In');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnode = new DefaultNodeModel('Node ' + (nodesCount + 1), 'rgb(0,192,255)');\n\t\t\t\t\t\t\t\tnode.addOutPort('Out');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvar point = this.props.app.getDiagramEngine().getRelativeMousePoint(event);\n\t\t\t\t\t\t\tnode.setPosition(point);\n\t\t\t\t\t\t\tthis.props.app.getDiagramEngine().getModel().addNode(node);\n\t\t\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DemoCanvasWidget>\n\t\t\t\t\t\t\t<CanvasWidget engine={this.props.app.getDiagramEngine()} />\n\t\t\t\t\t\t</DemoCanvasWidget>\n\t\t\t\t\t</S.Layer>\n\t\t\t\t</S.Content>\n\t\t\t</S.Body>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-drag-and-drop/components/TrayItemWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\n\nexport interface TrayItemWidgetProps {\n\tmodel: any;\n\tcolor?: string;\n\tname: string;\n}\n\nnamespace S {\n\texport const Tray = styled.div<{ color: string }>`\n\t\tcolor: white;\n\t\tfont-family: Helvetica, Arial;\n\t\tpadding: 5px;\n\t\tmargin: 0px 10px;\n\t\tborder: solid 1px ${(p) => p.color};\n\t\tborder-radius: 5px;\n\t\tmargin-bottom: 2px;\n\t\tcursor: pointer;\n\t`;\n}\n\nexport class TrayItemWidget extends React.Component<TrayItemWidgetProps> {\n\trender() {\n\t\treturn (\n\t\t\t<S.Tray\n\t\t\t\tcolor={this.props.color}\n\t\t\t\tdraggable={true}\n\t\t\t\tonDragStart={(event) => {\n\t\t\t\t\tevent.dataTransfer.setData('storm-diagram-node', JSON.stringify(this.props.model));\n\t\t\t\t}}\n\t\t\t\tclassName=\"tray-item\"\n\t\t\t>\n\t\t\t\t{this.props.name}\n\t\t\t</S.Tray>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-drag-and-drop/components/TrayWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\n\nnamespace S {\n\texport const Tray = styled.div`\n\t\tmin-width: 200px;\n\t\tbackground: rgb(20, 20, 20);\n\t\tflex-grow: 0;\n\t\tflex-shrink: 0;\n\t`;\n}\n\nexport class TrayWidget extends React.Component {\n\trender() {\n\t\treturn <S.Tray>{this.props.children}</S.Tray>;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-drag-and-drop/index.tsx",
    "content": "import * as React from 'react';\n\nimport { BodyWidget } from './components/BodyWidget';\nimport { Application } from './Application';\n\nexport default () => {\n\tvar app = new Application();\n\treturn <BodyWidget app={app} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-dynamic-ports/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, DiagramEngine } from '@projectstorm/react-diagrams';\nimport _values from 'lodash/values';\nimport * as React from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nclass CloneSelected extends React.Component<{ model: DiagramModel; engine: DiagramEngine }, any> {\n\taddPorts = () => {\n\t\tconst nodes: DefaultNodeModel[] = _values(this.props.model.getNodes()) as DefaultNodeModel[];\n\t\tfor (let node of nodes) {\n\t\t\tif (node.getOptions().name === 'Node 2') {\n\t\t\t\tnode.addInPort(`in-${node.getInPorts().length + 1}`, false);\n\t\t\t} else {\n\t\t\t\tnode.addOutPort(`out-${node.getOutPorts().length + 1}`, false);\n\t\t\t}\n\t\t}\n\t\tthis.props.engine.repaintCanvas();\n\t};\n\n\trender() {\n\t\tconst { engine } = this.props;\n\t\treturn (\n\t\t\t<DemoWorkspaceWidget buttons={<DemoButton onClick={this.addPorts}>Add more ports</DemoButton>}>\n\t\t\t\t<DemoCanvasWidget>\n\t\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t\t</DemoCanvasWidget>\n\t\t\t</DemoWorkspaceWidget>\n\t\t);\n\t}\n}\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tnode2.setPosition(400, 100);\n\n\t// link the ports\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn <CloneSelected engine={engine} model={model} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-grid/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Tests the grid size\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\tmodel.setGridSize(50);\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tlet port = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tlet port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t// link the ports\n\tlet link1 = port.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-labelled-links/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, DefaultLinkModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { action } from '@storybook/addon-actions';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport default () => {\n\t// setup the diagram engine\n\tconst engine = createEngine();\n\n\t// setup the diagram model\n\tconst model = new DiagramModel();\n\n\t// create four nodes\n\tconst node1 = new DefaultNodeModel('Node A', 'rgb(0,192,255)');\n\tconst port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\tconst node2 = new DefaultNodeModel('Node B', 'rgb(255,255,0)');\n\tconst port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 50);\n\n\tconst node3 = new DefaultNodeModel('Node C (no label)', 'rgb(192,255,255)');\n\tconst port3 = node3.addInPort('In');\n\tnode3.setPosition(450, 180);\n\n\tconst node4 = new DefaultNodeModel('Node D', 'rgb(192,0,255)');\n\tconst port4 = node4.addInPort('In');\n\tnode4.setPosition(300, 250);\n\n\t// link node A and B together and give it a label\n\tconst link1 = port1.link(port2);\n\t(link1 as DefaultLinkModel).addLabel('Custom label 1');\n\t(link1 as DefaultLinkModel).addLabel('Custom label 2');\n\n\t// no label for A and C, just a link\n\tconst link2 = port1.link(port3);\n\n\t// also a label for A and D\n\tconst link3 = port1.link(port4);\n\t(link3 as DefaultLinkModel).addLabel('Emoji label: 🎉');\n\n\t// add all to the main model\n\tmodel.addAll(node1, node2, node3, node4, link1, link2, link3);\n\n\t// load model into engine and render\n\tengine.setModel(model);\n\n\treturn (\n\t\t<DemoWorkspaceWidget\n\t\t\tbuttons={\n\t\t\t\t<DemoButton\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\taction('Serialized Graph')(JSON.stringify(model.serializeDiagram(), null, 2));\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tSerialize Graph\n\t\t\t\t</DemoButton>\n\t\t\t}\n\t\t>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-listeners/index.tsx",
    "content": "import * as React from 'react';\nimport { action } from '@storybook/addon-actions';\nimport createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Shows some of the events triggered when elements are selected\n */\nexport default () => {\n\t// setup the diagram engine\n\tvar engine = createEngine();\n\n\tvar model = new DiagramModel();\n\n\t// sample for link with simple line\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(255,99,66)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 40);\n\n\tvar node3 = new DefaultNodeModel('Node 3', 'rgb(128,99,255)');\n\tvar port3 = node3.addInPort('In');\n\tnode3.setPosition(300, 160);\n\n\t//link the nodes\n\tlet link1 = port1.link(port2);\n\tlet link2 = port1.link(port3);\n\n\t// add all the models\n\tlet models = model.addAll(node1, node2, node3, link1, link2);\n\n\t// add a selection listener to each\n\tmodels.forEach((item) => {\n\t\titem.registerListener({\n\t\t\teventDidFire: action('element eventDidFire')\n\t\t});\n\t});\n\n\tmodel.registerListener({\n\t\teventDidFire: action('model eventDidFire')\n\t});\n\n\tengine.setModel(model);\n\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-locks/index.tsx",
    "content": "import * as React from 'react';\nimport createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n *\n * Shows how you can lock down the system so that the entire scene cant be interacted with.\n *\n * @Author Dylan Vorster\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\tvar model = new DiagramModel();\n\n\t// sample for link with simple line (no additional points)\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\tlet link1 = port1.link(port2);\n\n\tmodel.addAll(node1, node2, link1);\n\n\t// sample for link with complex line (additional points)\n\tvar node3 = new DefaultNodeModel('Node 3', 'rgb(0,192,255)');\n\tvar port3 = node3.addOutPort('Out');\n\tnode3.setPosition(100, 250);\n\n\tvar node4 = new DefaultNodeModel('Node 4', 'rgb(192,255,0)');\n\tvar port4 = node4.addInPort('In');\n\tnode4.setPosition(400, 250);\n\n\tvar link2 = port3.link(port4);\n\n\tlink2.point(350, 225);\n\tlink2.point(200, 225);\n\n\tmodel.addAll(node3, node4, link2);\n\n\tengine.setModel(model);\n\n\t//!========================================= <<<<<<<\n\n\tmodel.setLocked(true);\n\n\t//!=========================================  <<<<<<<\n\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-mutate-graph/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, NodeModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport _values from 'lodash/values';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Tests the grid size\n */\nclass NodeDelayedPosition extends React.Component<any, any> {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.updatePosition = this.updatePosition.bind(this);\n\t\tthis.updatePositionViaSerialize = this.updatePositionViaSerialize.bind(this);\n\t}\n\n\tupdatePosition() {\n\t\tconst { engine } = this.props;\n\t\tlet model = engine.getModel();\n\t\tconst nodes = model.getNodes();\n\t\tlet node = nodes[Object.keys(nodes)[0]];\n\t\tnode.setPosition(node.getX() + 30, node.getY() + 30);\n\t\tengine.repaintCanvas();\n\t}\n\n\tupdatePositionViaSerialize() {\n\t\tlet { engine } = this.props;\n\t\tlet model = engine.getModel();\n\t\tlet str = JSON.stringify(model.serialize());\n\t\tlet model2 = new DiagramModel();\n\t\tlet obj: ReturnType<DiagramModel['serialize']> = JSON.parse(str);\n\t\tlet node: ReturnType<NodeModel['serialize']> = _values(obj.layers[1].models)[0] as any;\n\t\tnode.x += 30;\n\t\tnode.y += 30;\n\n\t\tmodel2.deserializeModel(obj, engine);\n\t\tengine.setModel(model2);\n\t}\n\n\trender() {\n\t\tconst { engine } = this.props;\n\t\treturn (\n\t\t\t<DemoWorkspaceWidget\n\t\t\t\tbuttons={[\n\t\t\t\t\t<DemoButton key={1} onClick={this.updatePosition}>\n\t\t\t\t\t\tUpdate position\n\t\t\t\t\t</DemoButton>,\n\t\t\t\t\t<DemoButton key={2} onClick={this.updatePositionViaSerialize}>\n\t\t\t\t\t\tUpdate position via serialize\n\t\t\t\t\t</DemoButton>\n\t\t\t\t]}\n\t\t\t>\n\t\t\t\t<DemoCanvasWidget>\n\t\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t\t</DemoCanvasWidget>\n\t\t\t</DemoWorkspaceWidget>\n\t\t);\n\t}\n}\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn <NodeDelayedPosition engine={engine} model={model} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-pan-and-zoom/index.tsx",
    "content": "import * as React from 'react';\nimport createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n * Tests the pan and zoom action, which is intended as a trackpad/mobile\n * alternative to the standard ZoomCanvasAction\n */\nclass CanvasPanAndZoomToggle extends React.Component<any, any> {\n\trender() {\n\t\tconst { engine } = this.props;\n\t\treturn (\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t);\n\t}\n}\n\nexport default () => {\n\t/**\n\t * 1) setup the diagram engine\n\t * PandAndZoomCanvasAction and ZoomCanvasAction are mutually exclusive\n\t * If both are enabled, ZoomCanvasAction will override.\n\t */\n\tvar engine = createEngine({\n\t\tregisterDefaultPanAndZoomCanvasAction: true,\n\t\tregisterDefaultZoomCanvasAction: false\n\t});\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn <CanvasPanAndZoomToggle engine={engine} model={model} />;\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-performance/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n *\n * Simple stress test of the system, shows that it can handle many nodes, and\n * retain good performance\n *\n * @Author Dylan Vorster\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\tfor (var i = 0; i < 8; i++) {\n\t\tfor (var j = 0; j < 8; j++) {\n\t\t\tgenerateNodes(model, i * 200, j * 100);\n\t\t}\n\t}\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n\nfunction generateNodes(model: DiagramModel, offsetX: number, offsetY: number) {\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100 + offsetX, 100 + offsetY);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(200 + offsetX, 100 + offsetY);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-right-angles-routing/index.tsx",
    "content": "import createEngine, {\n\tDiagramModel,\n\tDefaultNodeModel,\n\tDefaultPortModel,\n\tRightAngleLinkFactory,\n\tLinkModel,\n\tRightAngleLinkModel\n} from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { action } from '@storybook/addon-actions';\nimport { AbstractModelFactory, CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n// When new link is created by clicking on port the RightAngleLinkModel needs to be returned.\nexport class RightAnglePortModel extends DefaultPortModel {\n\tcreateLinkModel(factory?: AbstractModelFactory<LinkModel>) {\n\t\treturn new RightAngleLinkModel();\n\t}\n}\n\nexport default () => {\n\t// setup the diagram engine\n\tconst engine = createEngine();\n\tengine.getLinkFactories().registerFactory(new RightAngleLinkFactory());\n\n\t// setup the diagram model\n\tconst model = new DiagramModel();\n\n\t// create four nodes in a way that straight links wouldn't work\n\tconst node1 = new DefaultNodeModel('Node A', 'rgb(0,192,255)');\n\tconst port1 = node1.addPort(new RightAnglePortModel(false, 'out-1', 'Out'));\n\tnode1.setPosition(340, 350);\n\n\tconst node2 = new DefaultNodeModel('Node B', 'rgb(255,255,0)');\n\tconst port2 = node2.addPort(new RightAnglePortModel(false, 'out-1', 'Out'));\n\tnode2.setPosition(240, 80);\n\tconst node3 = new DefaultNodeModel('Node C', 'rgb(192,255,255)');\n\tconst port3 = node3.addPort(new RightAnglePortModel(true, 'in-1', 'In'));\n\tnode3.setPosition(540, 180);\n\tconst node4 = new DefaultNodeModel('Node D', 'rgb(192,0,255)');\n\tconst port4 = node4.addPort(new RightAnglePortModel(true, 'in-1', 'In'));\n\tnode4.setPosition(95, 185);\n\n\t// linking things together\n\tconst link1 = port1.link(port4);\n\tconst link2 = port2.link(port3);\n\n\t// add all to the main model\n\tmodel.addAll(node1, node2, node3, node4, link1, link2);\n\n\t// load model into engine and render\n\tengine.setModel(model);\n\n\treturn (\n\t\t<DemoWorkspaceWidget\n\t\t\tbuttons={\n\t\t\t\t<DemoButton\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\taction('Serialized Graph')(JSON.stringify(model.serialize(), null, 2));\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tSerialize Graph\n\t\t\t\t</DemoButton>\n\t\t\t}\n\t\t>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-serializing/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, DefaultLabelModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { action } from '@storybook/addon-actions';\nimport * as beautify from 'json-beautify';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\tlink1.addLabel(new DefaultLabelModel({ label: 'Label' }));\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//!------------- SERIALIZING ------------------\n\n\tvar str = JSON.stringify(model.serialize());\n\n\t//!------------- DESERIALIZING ----------------\n\n\tvar model2 = new DiagramModel();\n\tmodel2.deserializeModel(JSON.parse(str), engine);\n\tengine.setModel(model2);\n\n\treturn (\n\t\t<DemoWorkspaceWidget\n\t\t\tbuttons={\n\t\t\t\t<DemoButton\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\taction('Serialized Graph')(beautify(model2.serialize(), null, 2, 80));\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tSerialize Graph\n\t\t\t\t</DemoButton>\n\t\t\t}\n\t\t>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-simple/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, DefaultLinkModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel({\n\t\tname: 'Node 1',\n\t\tcolor: 'rgb(0,192,255)'\n\t});\n\tnode1.setPosition(100, 100);\n\tlet port1 = node1.addOutPort('Out');\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tlet port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t// link the ports\n\tlet link1 = port1.link<DefaultLinkModel>(port2);\n\tlink1.getOptions().testName = 'Test';\n\tlink1.addLabel('Hello World!');\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-simple-flow/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel, DefaultDiagramState } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t// ############################################ MAGIC HAPPENS HERE\n\tconst state = engine.getStateMachine().getCurrentState();\n\tif (state instanceof DefaultDiagramState) {\n\t\tstate.dragNewLink.config.allowLooseLinks = false;\n\t}\n\t// ############################################ MAGIC HAPPENS HERE\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100, 100);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(400, 100);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//3-D) create an orphaned node\n\tvar node3 = new DefaultNodeModel('Node 3', 'rgb(0,192,255)');\n\tnode3.addOutPort('Out');\n\tnode3.setPosition(100, 200);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, node3, link1);\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoCanvasWidget>\n\t\t\t<CanvasWidget engine={engine} />\n\t\t</DemoCanvasWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-smart-routing/index.tsx",
    "content": "import createEngine, {\n\tDiagramModel,\n\tDefaultNodeModel,\n\tDefaultPortModel,\n\tPathFindingLinkFactory,\n\tDefaultLabelModel\n} from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { DemoButton, DemoWorkspaceWidget } from '../helpers/DemoWorkspaceWidget';\nimport { action } from '@storybook/addon-actions';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\nexport default () => {\n\t// setup the diagram engine\n\tconst engine = createEngine();\n\n\t// setup the diagram model\n\tconst model = new DiagramModel();\n\n\t// create four nodes in a way that straight links wouldn't work\n\tconst node1 = new DefaultNodeModel('Node A', 'rgb(0,192,255)');\n\tconst port1 = node1.addPort(new DefaultPortModel(false, 'out-1', 'Out'));\n\tnode1.setPosition(340, 350);\n\n\tconst node2 = new DefaultNodeModel('Node B', 'rgb(255,255,0)');\n\tconst port2 = node2.addPort(new DefaultPortModel(false, 'out-1', 'Out'));\n\tnode2.setPosition(240, 80);\n\tconst node3 = new DefaultNodeModel('Node C', 'rgb(192,255,255)');\n\tconst port3 = node3.addPort(new DefaultPortModel(true, 'in-1', 'In'));\n\tnode3.setPosition(540, 180);\n\tconst node4 = new DefaultNodeModel('Node D', 'rgb(192,0,255)');\n\tconst port4 = node4.addPort(new DefaultPortModel(true, 'in-1', 'In'));\n\tnode4.setPosition(95, 185);\n\tconst node5 = new DefaultNodeModel('Node E', 'rgb(192,255,0)');\n\tnode5.setPosition(250, 180);\n\n\tconst pathfinding = engine.getLinkFactories().getFactory<PathFindingLinkFactory>(PathFindingLinkFactory.NAME);\n\n\t// linking things together (specifically using the pathfinding link)\n\tconst link1 = port1.link(port4, pathfinding);\n\tconst link2 = port2.link(port3, pathfinding);\n\n\tlink1.addLabel(\n\t\tnew DefaultLabelModel({\n\t\t\tlabel: 'I am a label!',\n\t\t\toffsetY: 20\n\t\t})\n\t);\n\n\t// add all to the main model\n\tmodel.addAll(node1, node2, node3, node4, node5, link1, link2);\n\n\t// load model into engine and render\n\tengine.setModel(model);\n\n\treturn (\n\t\t<DemoWorkspaceWidget\n\t\t\tbuttons={\n\t\t\t\t<DemoButton\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\taction('Serialized Graph')(JSON.stringify(model.serialize(), null, 2));\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tSerialize Graph\n\t\t\t\t</DemoButton>\n\t\t\t}\n\t\t>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n};\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-zoom-to-fit/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { DemoWorkspaceWidget, DemoButton } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n *\n * Simple stress test of the system plus zoom to fit function\n *\n * @Author Dylan Vorster\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\tfor (var i = 0; i < 8; i++) {\n\t\tfor (var j = 0; j < 8; j++) {\n\t\t\tgenerateNodes(model, i * 200, j * 100);\n\t\t}\n\t}\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoWorkspaceWidget buttons={<DemoButton onClick={() => engine.zoomToFit()}>Zoom to fit</DemoButton>}>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n};\n\nfunction generateNodes(model: DiagramModel, offsetX: number, offsetY: number) {\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100 + offsetX, 100 + offsetY);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(200 + offsetX, 100 + offsetY);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/demo-zoom-to-fit-nodes/index.tsx",
    "content": "import createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';\nimport * as React from 'react';\nimport { DemoWorkspaceWidget, DemoButton } from '../helpers/DemoWorkspaceWidget';\nimport { CanvasWidget } from '@projectstorm/react-canvas-core';\nimport { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';\n\n/**\n *\n * Simple stress test of the system plus zoom to fit function\n *\n * @Author Dylan Vorster\n */\nexport default () => {\n\t//1) setup the diagram engine\n\tvar engine = createEngine();\n\n\t//2) setup the diagram model\n\tvar model = new DiagramModel();\n\n\tfor (var i = 0; i < 8; i++) {\n\t\tfor (var j = 0; j < 8; j++) {\n\t\t\tgenerateNodes(model, i * 200, j * 100);\n\t\t}\n\t}\n\n\t//5) load model into engine\n\tengine.setModel(model);\n\n\t//6) render the diagram!\n\treturn (\n\t\t<DemoWorkspaceWidget\n\t\t\tbuttons={<DemoButton onClick={() => engine.zoomToFitSelectedNodes(50)}>Zoom to fit</DemoButton>}\n\t\t>\n\t\t\t<DemoCanvasWidget>\n\t\t\t\t<CanvasWidget engine={engine} />\n\t\t\t</DemoCanvasWidget>\n\t\t</DemoWorkspaceWidget>\n\t);\n};\n\nfunction generateNodes(model: DiagramModel, offsetX: number, offsetY: number) {\n\t//3-A) create a default node\n\tvar node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');\n\tvar port1 = node1.addOutPort('Out');\n\tnode1.setPosition(100 + offsetX, 100 + offsetY);\n\n\t//3-B) create another default node\n\tvar node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');\n\tvar port2 = node2.addInPort('In');\n\tnode2.setPosition(200 + offsetX, 100 + offsetY);\n\n\t//3-C) link the 2 nodes together\n\tvar link1 = port1.link(port2);\n\n\t//4) add the models to the root graph\n\tmodel.addAll(node1, node2, link1);\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/helpers/DemoCanvasWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\nimport { css, Global } from '@emotion/react';\n\nexport interface DemoCanvasWidgetProps {\n\tcolor?: string;\n\tbackground?: string;\n}\n\nnamespace S {\n\texport const Container = styled.div<{ color: string; background: string }>`\n\t\theight: 100%;\n\t\tbackground-color: ${(p) => p.background};\n\t\tbackground-size: 50px 50px;\n\t\tdisplay: flex;\n\n\t\t> * {\n\t\t\theight: 100%;\n\t\t\tmin-height: 100%;\n\t\t\twidth: 100%;\n\t\t}\n\n\t\tbackground-image: linear-gradient(\n\t\t\t\t0deg,\n\t\t\t\ttransparent 24%,\n\t\t\t\t${(p) => p.color} 25%,\n\t\t\t\t${(p) => p.color} 26%,\n\t\t\t\ttransparent 27%,\n\t\t\t\ttransparent 74%,\n\t\t\t\t${(p) => p.color} 75%,\n\t\t\t\t${(p) => p.color} 76%,\n\t\t\t\ttransparent 77%,\n\t\t\t\ttransparent\n\t\t\t),\n\t\t\tlinear-gradient(\n\t\t\t\t90deg,\n\t\t\t\ttransparent 24%,\n\t\t\t\t${(p) => p.color} 25%,\n\t\t\t\t${(p) => p.color} 26%,\n\t\t\t\ttransparent 27%,\n\t\t\t\ttransparent 74%,\n\t\t\t\t${(p) => p.color} 75%,\n\t\t\t\t${(p) => p.color} 76%,\n\t\t\t\ttransparent 77%,\n\t\t\t\ttransparent\n\t\t\t);\n\t`;\n\n\texport const Expand = css`\n\t\thtml,\n\t\tbody,\n\t\t#root {\n\t\t\theight: 100%;\n\t\t}\n\t`;\n}\n\nexport class DemoCanvasWidget extends React.Component<React.PropsWithChildren<DemoCanvasWidgetProps>> {\n\trender() {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<Global styles={S.Expand} />\n\t\t\t\t<S.Container\n\t\t\t\t\tbackground={this.props.background || 'rgb(60, 60, 60)'}\n\t\t\t\t\tcolor={this.props.color || 'rgba(255,255,255, 0.05)'}\n\t\t\t\t>\n\t\t\t\t\t{this.props.children}\n\t\t\t\t</S.Container>\n\t\t\t</>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/helpers/DemoWorkspaceWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\n\nexport interface DemoWorkspaceWidgetProps {\n\tbuttons?: any;\n}\n\nnamespace S {\n\texport const Toolbar = styled.div`\n\t\tpadding: 5px;\n\t\tdisplay: flex;\n\t\tflex-shrink: 0;\n\t`;\n\n\texport const Content = styled.div`\n\t\tflex-grow: 1;\n\t\theight: 100%;\n\t`;\n\n\texport const Container = styled.div`\n\t\tbackground: black;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\theight: 100%;\n\t\tborder-radius: 5px;\n\t\toverflow: hidden;\n\t`;\n}\n\nexport const DemoButton = styled.button`\n\tbackground: rgb(60, 60, 60);\n\tfont-size: 14px;\n\tpadding: 5px 10px;\n\tborder: none;\n\tcolor: white;\n\toutline: none;\n\tcursor: pointer;\n\tmargin: 2px;\n\tborder-radius: 3px;\n\n\t&:hover {\n\t\tbackground: rgb(0, 192, 255);\n\t}\n`;\n\nexport class DemoWorkspaceWidget extends React.Component<React.PropsWithChildren<DemoWorkspaceWidgetProps>> {\n\trender() {\n\t\treturn (\n\t\t\t<S.Container>\n\t\t\t\t<S.Toolbar>{this.props.buttons}</S.Toolbar>\n\t\t\t\t<S.Content>{this.props.children}</S.Content>\n\t\t\t</S.Container>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/helpers/Helper.tsx",
    "content": "import * as React from 'react';\n\nexport class Helper {\n\t/**\n\t * Logs the mouse position in the console, but overlays a div that consumes all events\n\t * since the actual story book stories are rendered as an iFrame.\n\t */\n\tstatic logMousePosition() {\n\t\tlet element = window.parent.document.createElement('mouse-position');\n\t\telement.style.position = 'absolute';\n\t\telement.style.top = '0px';\n\t\telement.style.left = '0px';\n\t\telement.style.bottom = '0px';\n\t\telement.style.right = '0px';\n\t\telement.style.zIndex = '10';\n\t\twindow.parent.document.body.appendChild(element);\n\n\t\twindow.parent.window.addEventListener('mousemove', (event) => {\n\t\t\tconsole.clear();\n\t\t\tconsole.log(event.clientX, event.clientY);\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/demos/helpers/index.css",
    "content": "html,\nbody,\n#storybook-root {\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/package.json",
    "content": "{\n  \"name\": \"@projectstorm/react-diagrams-gallery\",\n  \"version\": \"7.2.1\",\n  \"author\": \"dylanvorster\",\n  \"license\": \"MIT\",\n  \"private\": true,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n  },\n  \"scripts\": {\n    \"start\": \"pnpm storybook dev\",\n    \"storybook:build\": \"pnpm storybook build -c .storybook -o .out\"\n  },\n  \"keywords\": [\n    \"web\",\n    \"diagram\",\n    \"diagrams\",\n    \"react\",\n    \"typescript\",\n    \"flowchart\",\n    \"simple\",\n    \"links\",\n    \"nodes\"\n  ],\n  \"dependencies\": {\n    \"@projectstorm/react-canvas-core\": \"workspace:*\",\n    \"@projectstorm/react-diagrams\": \"workspace:*\",\n    \"@projectstorm/react-diagrams-core\": \"workspace:*\",\n    \"@projectstorm/react-diagrams-defaults\": \"workspace:*\",\n    \"gsap\": \"^3.12.2\",\n    \"json-beautify\": \"^1.1.1\",\n    \"lodash\": \"^4.17.21\",\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/preset-env\": \"^7.26.9\",\n    \"@babel/preset-react\": \"^7.26.3\",\n    \"@babel/preset-typescript\": \"^7.27.0\",\n    \"@storybook/addon-actions\": \"^8.6.9\",\n    \"@storybook/addon-webpack5-compiler-babel\": \"^3.0.5\",\n    \"@storybook/manager-api\": \"^8.6.10\",\n    \"@storybook/preview-api\": \"^8.6.10\",\n    \"@storybook/react\": \"^8.6.9\",\n    \"@storybook/react-webpack5\": \"^8.6.9\",\n    \"@storybook/storybook-deployer\": \"^2.8.16\",\n    \"@storybook/theming\": \"^8.6.9\",\n    \"@types/lodash\": \"^4.14.200\",\n    \"@types/react\": \"^19.0.12\",\n    \"@types/react-dom\": \"^19.0.4\",\n    \"storybook\": \"^8.6.9\"\n  }\n}\n"
  },
  {
    "path": "diagrams-demo-gallery/tsconfig.json",
    "content": "{\n\t\"compileOnSave\": false,\n\t\"compilerOptions\": {\n\t\t\"esModuleInterop\": true,\n\t\t\"declaration\": true,\n\t\t\"composite\": true,\n\t\t\"incremental\": true,\n\t\t\"strictNullChecks\": false,\n\t\t\"sourceMap\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"jsx\": \"react\",\n\t\t\"target\": \"ES6\",\n\t\t\"module\": \"commonjs\",\n\t\t\"strict\": false,\n\t\t\"lib\": [\n\t\t\t\"DOM\",\n\t\t\t\"ES6\"\n\t\t]\n\t},\n\t\"include\": [\n\t\t\"demos\"\n\t]\n}\n"
  },
  {
    "path": "diagrams-demo-project/.babelrc",
    "content": "{\n\t\"presets\": [\n\t\t[\"@babel/preset-env\",{\n\t\t\t\"targets\": {\n\t\t\t\t\"node\": true\n\t\t\t}\n\t\t}],\n\t\t\"@babel/preset-react\"\n\t]\n}\n"
  },
  {
    "path": "diagrams-demo-project/CHANGELOG.md",
    "content": "# @projectstorm/react-diagrams-demo\n\n## 7.0.4\n\n### Patch Changes\n\n- @projectstorm/react-diagrams@7.0.4\n\n## 7.0.3\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n  - @projectstorm/react-diagrams@7.0.3\n\n## 7.0.2\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/react-diagrams@7.0.2\n\n## 7.0.1\n\n### Patch Changes\n\n- @projectstorm/react-diagrams@7.0.1\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/react-diagrams@7.0.0\n"
  },
  {
    "path": "diagrams-demo-project/README.md",
    "content": "# Project STORM > React diagrams > Demo Project\n\n![](./screenshot.png)\n\nIn this repo you will find a simple webpack-dev-server project\nthat shows how to get started with the library.\n\nIt contains an example of how to implement a custom node in both Vanilla ES6 as-well\nas typescript (the recommended way).\n\nSimply run `yarn start` which will also open your browser.\n\n"
  },
  {
    "path": "diagrams-demo-project/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"UTF-8\"/>\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n\t<title>Project STORM | React Diagrams demo</title>\n\t<script src=\"bundle.js\"></script>\n</head>\n<body>\n<div id=\"application\"/>\n</body>\n</html>\n"
  },
  {
    "path": "diagrams-demo-project/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-diagrams-demo\",\n\t\"version\": \"7.0.4\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"private\": true,\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"start\": \"./node_modules/.bin/webpack serve --open\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"@projectstorm/react-diagrams\": \"workspace:*\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@babel/core\": \"^7.26.10\",\n\t\t\"@babel/preset-react\": \"^7.26.3\",\n\t\t\"@types/react\": \"^19.0.12\",\n\t\t\"@types/react-dom\": \"^19.0.4\",\n\t\t\"babel-loader\": \"^9.1.3\",\n\t\t\"css-loader\": \"^6.8.1\",\n\t\t\"html-webpack-plugin\": \"^5.5.3\",\n\t\t\"source-map-loader\": \"^4.0.1\",\n\t\t\"style-loader\": \"^3.3.3\",\n\t\t\"webpack\": \"^5.88.2\",\n\t\t\"webpack-cli\": \"^5.1.4\",\n\t\t\"webpack-dev-server\": \"^4.15.1\"\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/BodyWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine, CanvasWidget } from '@projectstorm/react-diagrams';\n\nexport interface BodyWidgetProps {\n\tengine: DiagramEngine;\n}\n\nexport class BodyWidget extends React.Component<BodyWidgetProps> {\n\trender() {\n\t\treturn <CanvasWidget className=\"diagram-container\" engine={this.props.engine} />;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/custom-node-js/JSCustomNodeFactory.jsx",
    "content": "import * as React from 'react';\nimport { JSCustomNodeModel } from './JSCustomNodeModel';\nimport { JSCustomNodeWidget } from './JSCustomNodeWidget';\nimport { AbstractReactFactory } from '@projectstorm/react-diagrams';\n\nexport class JSCustomNodeFactory extends AbstractReactFactory {\n\tconstructor() {\n\t\tsuper('js-custom-node');\n\t}\n\n\tgenerateModel(event) {\n\t\treturn new JSCustomNodeModel();\n\t}\n\n\tgenerateReactWidget(event) {\n\t\treturn <JSCustomNodeWidget engine={this.engine} node={event.model} />;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/custom-node-js/JSCustomNodeModel.js",
    "content": "import { DefaultPortModel, NodeModel } from '@projectstorm/react-diagrams';\n\n/**\n * Example of a custom model using pure javascript\n */\nexport class JSCustomNodeModel extends NodeModel {\n\tconstructor(options = {}) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\ttype: 'js-custom-node'\n\t\t});\n\t\tthis.color = options.color || { options: 'red' };\n\n\t\t// setup an in and out port\n\t\tthis.addPort(\n\t\t\tnew DefaultPortModel({\n\t\t\t\tin: true,\n\t\t\t\tname: 'in'\n\t\t\t})\n\t\t);\n\t\tthis.addPort(\n\t\t\tnew DefaultPortModel({\n\t\t\t\tin: false,\n\t\t\t\tname: 'out'\n\t\t\t})\n\t\t);\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tcolor: this.color\n\t\t};\n\t}\n\n\tdeserialize(ob, engine) {\n\t\tsuper.deserialize(ob, engine);\n\t\tthis.color = ob.color;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/custom-node-js/JSCustomNodeWidget.jsx",
    "content": "import * as React from 'react';\nimport { PortWidget } from '@projectstorm/react-diagrams';\n\nexport class JSCustomNodeWidget extends React.Component {\n\trender() {\n\t\treturn (\n\t\t\t<div className=\"custom-node\">\n\t\t\t\t<PortWidget engine={this.props.engine} port={this.props.node.getPort('in')}>\n\t\t\t\t\t<div className=\"circle-port\" />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget engine={this.props.engine} port={this.props.node.getPort('out')}>\n\t\t\t\t\t<div className=\"circle-port\" />\n\t\t\t\t</PortWidget>\n\t\t\t\t<div className=\"custom-node-color\" style={{ backgroundColor: this.props.node.color }} />\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/custom-node-ts/TSCustomNodeFactory.tsx",
    "content": "import * as React from 'react';\nimport { TSCustomNodeModel } from './TSCustomNodeModel';\nimport { TSCustomNodeWidget } from './TSCustomNodeWidget';\nimport { AbstractReactFactory } from '@projectstorm/react-diagrams';\nimport { DiagramEngine } from '@projectstorm/react-diagrams';\nimport { JSX } from 'react';\n\nexport class TSCustomNodeFactory extends AbstractReactFactory<TSCustomNodeModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('ts-custom-node');\n\t}\n\n\tgenerateModel(initialConfig) {\n\t\treturn new TSCustomNodeModel();\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <TSCustomNodeWidget engine={this.engine as DiagramEngine} node={event.model} />;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/custom-node-ts/TSCustomNodeModel.ts",
    "content": "import { BaseModelOptions, DefaultPortModel, NodeModel } from '@projectstorm/react-diagrams';\n\nexport interface TSCustomNodeModelOptions extends BaseModelOptions {\n\tcolor?: string;\n}\n\nexport class TSCustomNodeModel extends NodeModel {\n\tcolor: string;\n\n\tconstructor(options: TSCustomNodeModelOptions = {}) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\ttype: 'ts-custom-node'\n\t\t});\n\t\tthis.color = options.color || 'red';\n\n\t\t// setup an in and out port\n\t\tthis.addPort(\n\t\t\tnew DefaultPortModel({\n\t\t\t\tin: true,\n\t\t\t\tname: 'in'\n\t\t\t})\n\t\t);\n\t\tthis.addPort(\n\t\t\tnew DefaultPortModel({\n\t\t\t\tin: false,\n\t\t\t\tname: 'out'\n\t\t\t})\n\t\t);\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tcolor: this.color\n\t\t};\n\t}\n\n\tdeserialize(event): void {\n\t\tsuper.deserialize(event);\n\t\tthis.color = event.data.color;\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/custom-node-ts/TSCustomNodeWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine, PortWidget } from '@projectstorm/react-diagrams';\nimport { TSCustomNodeModel } from './TSCustomNodeModel';\n\nexport interface TSCustomNodeWidgetProps {\n\tnode: TSCustomNodeModel;\n\tengine: DiagramEngine;\n}\n\nexport interface TSCustomNodeWidgetState {}\n\nexport class TSCustomNodeWidget extends React.Component<TSCustomNodeWidgetProps, TSCustomNodeWidgetState> {\n\tconstructor(props: TSCustomNodeWidgetProps) {\n\t\tsuper(props);\n\t\tthis.state = {};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div className=\"custom-node\">\n\t\t\t\t<PortWidget engine={this.props.engine} port={this.props.node.getPort('in')}>\n\t\t\t\t\t<div className=\"circle-port\" />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget engine={this.props.engine} port={this.props.node.getPort('out')}>\n\t\t\t\t\t<div className=\"circle-port\" />\n\t\t\t\t</PortWidget>\n\t\t\t\t<div className=\"custom-node-color\" style={{ backgroundColor: this.props.node.color }} />\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/main.css",
    "content": "*{\n\tmargin: 0;\n\tpadding: 0;\n}\n\nhtml, body, #application{\n\theight: 100%;\n\toverflow: hidden;\n}\n\n.diagram-container{\n\tbackground: #333333;\n\twidth: 100%;\n\theight: 100%;\n}\n\n.custom-node{\n\tborder: solid 2px gray;\n\tborder-radius: 5px;\n\twidth: 50px;\n\theight: 50px;\n\tdisplay: flex;\n\talign-items: flex-start;\n\tjustify-content: space-between;\n\tposition: relative;\n}\n\n.custom-node-color{\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\twidth: 20px;\n\theight: 20px;\n\ttransform: translate(-50%, -50%);\n\tborder-radius: 10px;\n}\n\n.circle-port{\n\twidth: 12px;\n\theight: 12px;\n\tmargin: 2px;\n\tborder-radius: 4px;\n\tbackground: darkgray;\n\tcursor: pointer;\n}\n\n.circle-port:hover{\n\tbackground: mediumpurple;\n}\n"
  },
  {
    "path": "diagrams-demo-project/src/main.tsx",
    "content": "import * as React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport './main.css';\nimport createEngine, { DefaultLinkModel, DiagramModel } from '@projectstorm/react-diagrams';\nimport { JSCustomNodeFactory } from './custom-node-js/JSCustomNodeFactory';\nimport { TSCustomNodeFactory } from './custom-node-ts/TSCustomNodeFactory';\nimport { JSCustomNodeModel } from './custom-node-js/JSCustomNodeModel';\nimport { TSCustomNodeModel } from './custom-node-ts/TSCustomNodeModel';\nimport { BodyWidget } from './BodyWidget';\n\n// create an instance of the engine\nconst engine = createEngine();\n\n// register the two engines\nengine.getNodeFactories().registerFactory(new JSCustomNodeFactory() as any);\nengine.getNodeFactories().registerFactory(new TSCustomNodeFactory());\n\n// create a diagram model\nconst model = new DiagramModel();\n\n//####################################################\n// now create two nodes of each type, and connect them\n\nconst node1 = new JSCustomNodeModel({ color: 'rgb(192,255,0)' });\nnode1.setPosition(50, 50);\n\nconst node2 = new TSCustomNodeModel({ color: 'rgb(0,192,255)' });\nnode2.setPosition(200, 50);\n\nconst link1 = new DefaultLinkModel();\nlink1.setSourcePort(node1.getPort('out'));\nlink1.setTargetPort(node2.getPort('in'));\n\nmodel.addAll(node1, node2, link1);\n\n//####################################################\n\n// install the model into the engine\nengine.setModel(model);\n\ndocument.addEventListener('DOMContentLoaded', () => {\n\tconst root = createRoot(document.querySelector('#application'));\n\troot.render(<BodyWidget engine={engine} />);\n});\n"
  },
  {
    "path": "diagrams-demo-project/tsconfig.json",
    "content": "{\n\t\"compileOnSave\": false,\n\t\"compilerOptions\": {\n\t\t\"declaration\": false,\n\t\t\"jsx\": \"react\",\n\t\t\"allowJs\": true,\n\t\t\"target\": \"es6\",\n\t\t\"module\": \"CommonJS\"\n\t},\n\t\"include\": [\n\t\t\"./src\"\n\t]\n}\n"
  },
  {
    "path": "diagrams-demo-project/webpack.config.js",
    "content": "const path = require('path');\nconst production = process.env.NODE_ENV === 'production';\nconst TerserPlugin = require('terser-webpack-plugin');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\nmodule.exports = {\n\tmode: production ? 'production' : 'development',\n\tdevtool: 'inline-source-map',\n\tentry: './src/main.tsx',\n\toutput: {\n\t\tpath: path.join(__dirname, 'dist'),\n\t\tfilename: 'bundle.js'\n\t},\n\tresolve: {\n\t\textensions: ['.ts', '.tsx', '.js', '.jsx']\n\t},\n\toptimization: {\n\t\tminimizer: [\n\t\t\tnew TerserPlugin({\n\t\t\t\tparallel: true,\n\t\t\t\tterserOptions: {\n\t\t\t\t\tecma: 6\n\t\t\t\t}\n\t\t\t})\n\t\t]\n\t},\n\tplugins: [\n\t\tnew HtmlWebpackPlugin({\n\t\t\ttemplate: 'index.html'\n\t\t})\n\t],\n\tmodule: {\n\t\trules: [\n\t\t\t{\n\t\t\t\tenforce: 'pre',\n\t\t\t\ttest: /\\.js$/,\n\t\t\t\tloader: 'source-map-loader'\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /\\.css$/,\n\t\t\t\tuse: ['style-loader', 'css-loader']\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /\\.jsx?$/,\n\t\t\t\texclude: /node_modules/,\n\t\t\t\tuse: ['babel-loader']\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /\\.tsx?$/,\n\t\t\t\tloader: 'ts-loader'\n\t\t\t}\n\t\t]\n\t},\n\tdevServer: {\n\t\tclient: {\n\t\t\toverlay: true\n\t\t},\n\t\thot: false,\n\t\tcompress: true\n\t}\n};\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Table of contents\n\n* [Introduction](README.md)\n* [Getting Started](getting-started/README.md)\n  * [Using the library](getting-started/using-the-library.md)\n* [Customizing](customizing/README.md)\n  * [Extending DefaultLinkModel](customizing/extending-default-links.md)\n  * [Custom Nodes](customizing/nodes.md)\n  * [Custom Ports](customizing/ports.md)\n* [About the project](about-the-project/README.md)\n  * [Testing](about-the-project/testing.md)\n  * [Architecture Questions](about-the-project/architecture-questions.md)\n\n"
  },
  {
    "path": "docs/about-the-project/architecture-questions.md",
    "content": "# Architecture Questions\n\nHere I will try to answer any questions relating to the design of the system\n\n## What was the inspiration for this library?\n\nJoint JS \\(a fantastic library\\) + my need for rich HTML nodes + LabView + Blender Composite sub system\n\n## Why render the nodes as HTML Elements and not SVG's?\n\nMy original requirement for this library stemmed from the requirement of wanting HTML nodes that would allow me to embed rich controls such as input fields, dropdowns and have the system treat such nodes as first class citizens. I originally tried to make this work in JointJS, but ran into a number of problems of which this was a relatively big one.\n\nJointJS does allow you to do this, but at the time of writing this library originally, I was having a lot of trouble to make it work exactly like I needed it, and therefore decided from the very beginning that I would attempt this with an HTML first mindset.\n\n## Why Typescript?\n\nFirstly, because it can transpile into any level of ECMAScript. This means that I don't need to break our the refactor tractor every time ECMAScript decides it wants to add features which it should have done years ago.\n\nI also ported it to Typescript to accommodate the heavy architectural changes I was starting to make. Since porting the library to typescript, and seeing the project explode in size and complexity, I consider this the best decision made with regard to this library so far.\n\nPorting to typescript also afforded us a set of powerful features such as generics and static analysis that all the project contributors have made exclusive use of.\n\nTypescript is &lt;3 typescript is life.\n\n## Why not Flow instead of Typescript?\n\nAt the time when I first started evaluating languages that could transpile to ECMAScript, I was not so sold on the supporting environment surrounding flow, and found that there was better tooling to support typescript, they are ultimately trying to do the same thing though, and I guess in the end, typescript just made more sense.\n\n## Why React ?\n\nReact is really efficient at rendering and managing HTML in a declarative manner. React has also become one of the bigger industry standards and has a rich ecosystem that plays really well with typescript. Apart from these notable points, I am really fond of React and wanted a diagramming library that takes full advantage of it, and makes it easy for engineers to use its power as well, when extending this library.\n\n## Why cant the Default models and widgets do this or that ?\n\nThey are intended to illustrate **how** to use this library and act as a good starting point to extend and show the capability. Ultimately I designed this library to be completely pluggable in a way that you can use it as a library and not a framework. If the default widgets are not good enough, then a good place to start is with creating your own models/factories/widgets.\n\n## Model vs Widget\n\nFor those that are new to [Scene Graphs](https://en.wikipedia.org/wiki/Scene_graph) or are not familiar with concepts such as [MVC](https://en.wikipedia.org/wiki/Model–view–controller), this library represents your entire graph as a model. The model is a traversable graph that represents the nodes and links between them in a virtual manner. Your program \\(aka the business logic/layer\\) can mutate this model imperatively or store snapshots decoratively of the complete model \\(via serialization\\) and then the engine and react widgets will take care of the rendering. For this reason every model in the library is represented by a widget, and the factories glue it all together.\n\n## How do I make my own elements?\n\nTake a look at the **demos** directory, with specific attention to the **DefaultNodeWidget**\n\nThat being said, the demos directory is an _example_ of how you can create your own elements. A number of people want to use the defaults as is, which is cool, but is recommended to create your own models/factories/widgets.\n\n## How do I use the library?\n\nTake a look at the demo folders, they have simple and complex examples of the complete usage.\n\nA good example of a real-world example is Demo 5\n\n"
  },
  {
    "path": "docs/about-the-project/testing.md",
    "content": "# Testing\n\n## End to end testing\n\nTo test the functionality of the library, we make use of e2e tests \\(end to end tests\\). In this library, we spin up a headless chrome using puppeteer and interactively and programmatically tell the mouse pointer to click and drag on various elements while making assertions along the way.\n\nWe use Jest for the assertions and the interactivity is handled by puppeteer. Due to the laborious nature of writing e2e tests, there is a helper method that is provided in each test that makes interacting with the diagrams a lot easier. Using this helper, you can easily tell the mouse to drag links between nodes, select them and also easily assert information about them. The important thing here, is that this helper does not touch the model in any way, but is purely a helper for writing the tests themselves. Please make use of this helper when writing tests, as it ensure that the tests are defensive in nature, and also reduces the overhead of physically writing them.\n\n"
  },
  {
    "path": "docs/customizing/README.md",
    "content": "# Customizing\n\nAlmost all components in react-diagrams are customizable. While some customization is better documented than others, the best way to learn about customization is through the examples in the codebase and by looking at the type annotations that come with the library.\n\nMost UI customization can be done through extending existing base classes. While node, port, and link have different data models, they share the same customization pattern:\n\n- they need a **model factory** extended off `AbstractModelFactory`, and that factory needs to be registered with the engine under a different model type\n- optionally, if you data model is different from the default, you can extend existing base classes such as `NodeModel`, `PortModel`, `DefaultLinkModel`, etc.\n- they need to have a **custom component** which renders using its default or customized data model. Some component such as the port can also be extended with composition such as port if you want to simply change the appearance.\n\n## Working with custom links\n\nThis is the easiest way to get started:\n\n[Extending the default Link](./extending-default-links.md)\n\n## Working with custom nodes\n\n[Working with Nodes](./nodes.md)\n\n[Working with Ports](./ports.md)\n"
  },
  {
    "path": "docs/customizing/extending-default-links.md",
    "content": "# Custom Links\n\n## Extending the DefaultLinkModel\n\nMuch like extending nodes, custom links can also be created.\nIn the below example, we have created a link that renders a circle animating from the source port to the target port.\n\n![](./images/custom-link.png)\n\nIn this specific example, we extended the `DefaultLinkModel` because we wanted to retain\na lot of the functionality that it provides in the base class:\n\n```typescript\nexport class AdvancedLinkModel extends DefaultLinkModel {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'advanced', // <-- here we give it a new type\n\t\t\twidth: 10 // we specifically want this to also be width 10\n\t\t});\n\t}\n}\n```\n\nNow we need to create a new link factory to tell the system how our new link model fits into the core system. We specifically are going to extend the `DefaultLinkFactory` because we still want to render a `DefaultLinkWidget`. The only difference is that we want each __path segment__ to be a red line with an animating circle. Fortunately, the `DefaultLinkWidget` already uses the `generateLinkSegment()` method defined in the `DefaultLinkFactory` to accomplish this. The only thing we need to do, is provide a different type of segment:\n\n```typescript\nexport class AdvancedLinkFactory extends DefaultLinkFactory {\n\tconstructor() {\n\t\tsuper('advanced'); // <-- this matches with the link model above\n\t}\n\n\tgenerateModel(): AdvancedLinkModel {\n\t\treturn new AdvancedLinkModel(); // <-- this is how we get new instances\n\t}\n\n    /**\n     * @override the DefaultLinkWidget makes use of this, and it normally renders that\n     * familiar gray line, so in this case we simply make it return a new advanced segment.\n     */\n\tgenerateLinkSegment(model: AdvancedLinkModel, selected: boolean, path: string) {\n\t\treturn (\n\t\t\t<g>\n\t\t\t\t<AdvancedLinkSegment model={model} path={path} />\n\t\t\t</g>\n\t\t);\n\t}\n}\n```\n\nThe actual code for the `AdvancedLinkSegment` [can be found here](https://github.com/projectstorm/react-diagrams/tree/master/diagrams-demo-gallery/demos/demo-custom-link1) (it is in the `demo-custom-link1` folder in the demo gallery).\n\nThis is the easiest and most simple way to get started with custom links. \n"
  },
  {
    "path": "docs/customizing/nodes.md",
    "content": "# Nodes\n\nA node contains the node content itself and its ports. Check [NodeModel source code](https://github.com/projectstorm/react-diagrams/blob/master/packages/react-diagrams-core/src/entities/node/NodeModel.ts#L24), if you want to see what class methods can be extended.\n\n## Extending the NodeModel\n\nIf you want to create a custom node that looks entirely different, then you need to create a component that renders using its default or customized data mode. In the example below, it uses a customized data model `DiamondNodeModel` to render `DiamondNodeWidget`, and both of them are being created in the model factory `DiamondNodeFactory`.\n\n![](./images/diamond-node.png)\n\nBecause our Diamond node always has four ports, we add four default port models into the `DiamondNodeModel`. Depending on the type of node you are creating, this is basically where you store your vertex data in the graph theory sense.\n\n```typescript\n// DiamondNodeModel.ts\nimport { NodeModel, NodeModelGenerics, PortModelAlignment } from '@projectstorm/react-diagrams';\nimport { DiamondPortModel } from './DiamondPortModel';\n\nexport interface DiamondNodeModelGenerics {\n\tPORT: DiamondPortModel;\n}\n\n// this can be further extended for more complicated node types\nexport class DiamondNodeModel extends NodeModel<NodeModelGenerics & DiamondNodeModelGenerics> {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'diamond'\n\t\t});\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.TOP));\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.LEFT));\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.BOTTOM));\n\t\tthis.addPort(new DiamondPortModel(PortModelAlignment.RIGHT));\n\t}\n}\n```\n\nThis is where we create our customized component. This component can be any customized react component as long as they respect the node and engine props. Ports also need to be rendered inside the node component.\n\n```typescript\n// DiamondNodeWidget.tsx\nimport * as React from 'react';\nimport { DiamondNodeModel } from './DiamondNodeModel';\nimport { DiagramEngine, PortModelAlignment, PortWidget } from '@projectstorm/react-diagrams';\nimport styled from '@emotion/styled';\n\nexport interface DiamondNodeWidgetProps {\n\t// node and engine props are required\n\tnode: DiamondNodeModel;\n\tengine: DiagramEngine;\n\tsize?: number;\n}\n\nnamespace S {\n\texport const Port = styled.div`\n\t\twidth: 16px;\n\t\theight: 16px;\n\t\tz-index: 10;\n\t\tbackground: rgba(0, 0, 0, 0.5);\n\t\tborder-radius: 8px;\n\t\tcursor: pointer;\n\t\t&:hover {\n\t\t\tbackground: rgba(0, 0, 0, 1);\n\t\t}\n\t`;\n}\n\n// this can be any customized react component as long as they respect\n// the node and engine props\nexport class DiamondNodeWidget extends React.Component<DiamondNodeWidgetProps> {\n\trender() {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={'diamond-node'}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'relative',\n\t\t\t\t\twidth: this.props.size,\n\t\t\t\t\theight: this.props.size\n\t\t\t\t}}>\n\t\t\t\t<svg\n\t\t\t\t\twidth={this.props.size}\n\t\t\t\t\theight={this.props.size}\n\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t__html:\n\t\t\t\t\t\t\t`\n          <g id=\"Layer_1\">\n          </g>\n          <g id=\"Layer_2\">\n            <polygon fill=\"mediumpurple\" stroke=\"${\n\t\t\t\t\t\t\tthis.props.node.isSelected() ? 'white' : '#000000'\n\t\t\t\t\t\t}\" stroke-width=\"3\" stroke-miterlimit=\"10\" points=\"10,` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t` ` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t`,10 ` +\n\t\t\t\t\t\t\t(this.props.size - 10) +\n\t\t\t\t\t\t\t`,` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t` ` +\n\t\t\t\t\t\t\tthis.props.size / 2 +\n\t\t\t\t\t\t\t`,` +\n\t\t\t\t\t\t\t(this.props.size - 10) +\n\t\t\t\t\t\t\t` \"/>\n          </g>\n        `\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\ttop: this.props.size / 2 - 8,\n\t\t\t\t\t\tleft: -8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.LEFT)}\n\t\t\t\t\tengine={this.props.engine}>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tleft: this.props.size / 2 - 8,\n\t\t\t\t\t\ttop: -8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.TOP)}\n\t\t\t\t\tengine={this.props.engine}>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tleft: this.props.size - 8,\n\t\t\t\t\t\ttop: this.props.size / 2 - 8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.RIGHT)}\n\t\t\t\t\tengine={this.props.engine}>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t\t<PortWidget\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tleft: this.props.size / 2 - 8,\n\t\t\t\t\t\ttop: this.props.size - 8,\n\t\t\t\t\t\tposition: 'absolute'\n\t\t\t\t\t}}\n\t\t\t\t\tport={this.props.node.getPort(PortModelAlignment.BOTTOM)}\n\t\t\t\t\tengine={this.props.engine}>\n\t\t\t\t\t<S.Port />\n\t\t\t\t</PortWidget>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nNow we need to create a new node factory to tell the system how our new node model fits into the core system. We specifically are going to extend the `DefaultLinkFactory` because we want to render a `DiamondNodeWidget` with data model being `DiamondNodeModel`. To accomplish that, we simply extend `generateReactWidget(event)` to return a `DiamondNodeWidget` and extend `generateModel` to return a `DiamondNodeModel` instance.\n\n```typescript\n// DiamondNodeFactory.tsx\nimport { DiamondNodeWidget } from './DiamondNodeWidget';\nimport { DiamondNodeModel } from './DiamondNodeModel';\nimport * as React from 'react';\nimport { AbstractReactFactory } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\n\nexport class DiamondNodeFactory extends AbstractReactFactory<DiamondNodeModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('diamond');\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\t// event.model is basically what's returned from generateModel()\n\t\treturn <DiamondNodeWidget engine={this.engine} size={50} node={event.model} />;\n\t}\n\n\tgenerateModel(event) {\n\t\treturn new DiamondNodeModel();\n\t}\n}\n```\n\nThe actual code for the `DiamondNode` [can be found here](https://github.com/projectstorm/react-diagrams/tree/master/diagrams-demo-gallery/demos/demo-custom-node1) (it is in the `demo-custom-node1` folder in the demo gallery).\n\nThis is the easiest and most simple way to get started with custom nodes. \n"
  },
  {
    "path": "docs/customizing/ports.md",
    "content": "# Ports\n\nPorts allow links to connect to your nodes. Each port that is rendered in a node must also have a corresponding PortModel in the corresponding NodeModel (as is the case with essentially all of the models and widgets in this library).\n\n## Custom port widgets\n\nIf you want to create a custom port that looks entirely different (much like in the image below), then you simply need to create your own widget and wrap it in a `PortWidget`:\n\n```jsx\n<PortWidget\n    port={this.props.node.getPort(\"in\"}\n    engine={this.props.engine} >\n    <div\n        style={{\n            width: 40,\n            height: 40,\n            background: 'orange'\n        }}\n    />\n</PortWidget>\n```\n\nObviously, you can create the React widgets in any way you like. Whether you use __Emotion__, __BEM__ or plain old __CSS__, the only important thing is that your custom port is wrapped inside a `PortWidget`\n\n## Specifying alignment\n\nWhen links enter ports, depending on the alignment specified, they can help the links render differently. Take the following example:\n\n![](./images/diamond-node.png)\n\nIn the above example, the 4 ports on the diamond node model are setup with different alignment:\n\n```typescript\nthis.addPort(new DiamondPortModel(PortModelAlignment.TOP));\nthis.addPort(new DiamondPortModel(PortModelAlignment.LEFT));\nthis.addPort(new DiamondPortModel(PortModelAlignment.BOTTOM));\nthis.addPort(new DiamondPortModel(PortModelAlignment.RIGHT));\n```\n\nEach of the custom `DiamondPortModel` models forwards this through to the base `PortModel` class:\n\n```typescript\nexport class DiamondPortModel extends PortModel {\n    ...\n\tconstructor(alignment: PortModelAlignment) {\n\t\tsuper({\n\t\t\ttype: 'diamond',\n\t\t\tname: alignment,\n\t\t\talignment: alignment // <-- here\n\t\t});\n    }\n    ...\n}\n```\n\n## Specifying if a link can be connected\n\nA port is directly responsible for specifying if a link is allowed to connect to it. When you drag an un-connected link end-point to a target port, the target port lets the link know if it is allowed to connect.\n\n```typescript\nclass PortModel{\n    ...\n    canLinkToPort(port: PortModel): boolean;\n}\n```\n\nIn the above definition, the port argument is the source port that the incoming link is connected to. By default, the method returns true, but you can extend this and overide this method to do more advanced checks.\n\nThe `DefaultPortModel` provided in the defaults package, makes use of this principle to only allow `Out` ports to connect to `In` ports:\n\n```typescript\nclass DefaultPortModel extends PortModel{\n    ...\n    canLinkToPort(port: PortModel): boolean {\n\t\tif (port instanceof DefaultPortModel) {\n\t\t\treturn this.options.in !== port.getOptions().in;\n\t\t}\n\t\treturn true;\n\t}\n}\n```\n\n## Specifying what type of link is generated from a port\n\nWhen a user drags on a port to generate a link, the port is also responsible for specifying\nwhat link is created. This happens through the `createLinkModel()` method:\n\n```typescript\nclass DefaultPortModel extends PortModel{\n    ...\n    createLinkModel(): LinkModel{\n        return new DefaultLinkModel(); // <-- here we generate a DefaultLinkModel\n    }\n}\n```"
  },
  {
    "path": "docs/getting-started/README.md",
    "content": "# Getting Started\n\n## Get the package\n\nThe first thing you need to do, is grab the distribution files on NPM.\n\n**Via yarn:**\n\n```text\nyarn add @projectstorm/react-diagrams\n```\n\n**Via npm:**\n\n```text\nnpm install @projectstorm/react-diagrams\n```\n\n**Via pnpm:**\n\n```text\npnpm add @projectstorm/react-diagrams\n```\n\nWhen you run this in your project directory, this will install the library into `./node_modules/@projectstorm/react-diagrams`. You will then find a **dist** folder that contains all the minified and production ready code."
  },
  {
    "path": "docs/getting-started/using-the-library.md",
    "content": "# Using the library\n\n## Using Typescript\n\nIf you are using typescript, then you are in luck! The library is built in typescript, and includes advanced types for everything you need right out of the box. \n\nLets start by including the things we are going to need:\n\n```typescript\nimport createEngine, { \n    DefaultLinkModel, \n    DefaultNodeModel,\n    DiagramModel \n} from '@projectstorm/react-diagrams';\n\nimport {\n    CanvasWidget\n} from '@projectstorm/react-canvas-core';\n```\n\nNow we call `createEngine` which will bootstrap a **DiagramEngine** for us that contains all the defaults setup.\n\n```typescript\n// create an instance of the engine with all the defaults\nconst engine = createEngine();\n```\n\nNext, we create two nodes:\n\n```typescript\n// node 1\nconst node1 = new DefaultNodeModel({\n\tname: 'Node 1',\n\tcolor: 'rgb(0,192,255)',\n});\nnode1.setPosition(100, 100);\nlet port1 = node1.addOutPort('Out');\n\n// node 2\nconst node2 = new DefaultNodeModel({\n\tname: 'Node 1',\n\tcolor: 'rgb(0,192,255)',\n});\nnode2.setPosition(100, 100);\nlet port2 = node2.addOutPort('Out');\n```\n\nNow we link the two ports of both of the nodes:\n\n```typescript\n// link them and add a label to the link\nconst link = port1.link<DefaultLinkModel>(port2);\nlink.addLabel('Hello World!');\n```\n\nGreat! Now we have setup a simple diagram. All thats left to do, is create a **DiagramModel** to contain everything, add all the elements to it, and then add it to the engine.\n\n```typescript\nconst model = new DiagramModel();\nmodel.addAll(node1, node2, link);\nengine.setModel(model);\n```\n\nAnd then we render with **React**!\n\n```jsx\n<CanvasWidget engine={engine} />\n```\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-diagrams\",\n\t\"author\": \"dylanvorster\",\n\t\"private\": true,\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"scripts\": {\n\t\t\"ncu\": \"ncu -u && pnpm recursive exec -- ncu -u\",\n\t\t\"format\": \"prettier --write \\\"**/*.{ts,tsx,js,jsx}\\\"\",\n\t\t\"clean\": \"rm -rf packages/*/dist\",\n\t\t\"test\": \"pnpm run -r test\",\n\t\t\"build\": \"tsc --build && pnpm run -r build\",\n\t\t\"build:prod\": \"NODE_ENV=production pnpm build\",\n\t\t\"release\": \"pnpm build:prod && pnpm changeset publish\",\n    \t\"release:storybook\": \"tsc --build && cd diagrams-demo-gallery && pnpm storybook:build && ./node_modules/.bin/storybook-to-ghpages --existing-output-dir .out\"\n\t},\n\t\"devDependencies\": {\n    \t\"@changesets/cli\": \"^2.26.2\",\n\t\t\"@types/jest\": \"^29.5.5\",\n\t\t\"@types/node\": \"^20.6.3\",\n\t\t\"jest\": \"^29.7.0\",\n\t\t\"jest-cli\": \"^29.7.0\",\n\t\t\"prettier\": \"^3.0.3\",\n    \t\"rimraf\": \"^5.0.1\",\n\t\t\"source-map-loader\": \"^4.0.1\",\n\t\t\"terser-webpack-plugin\": \"^5.3.9\",\n\t\t\"ts-jest\": \"^29.1.1\",\n\t\t\"ts-loader\": \"^9.4.4\",\n\t\t\"typescript\": \"^5.2.2\",\n\t\t\"webpack\": \"^5.88.2\",\n\t\t\"webpack-cli\": \"^5.1.4\",\n\t\t\"webpack-dev-server\": \"^4.15.1\",\n\t\t\"webpack-node-externals\": \"^3.0.0\"\n\t},\n\t\"pnpm\": {\n\t\t\"overrides\": {\n\t\t\t\"react\": \"^19.0.0\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/.npmignore",
    "content": "*\n!dist/**/*\n!package.json\ndist/tsconfig.tsbuildinfo\n"
  },
  {
    "path": "packages/geometry/CHANGELOG.md",
    "content": "# @projectstorm/geometry\n\n## 7.0.3\n\n### Patch Changes\n\n- 80285fe: refactor: update lodash imports to use individual functions\n\n## 7.0.2\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n\n## 7.0.1\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n"
  },
  {
    "path": "packages/geometry/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/geometry\",\n\t\"version\": \"7.0.3\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"rimraf ./dist\",\n\t\t\"build\": \"../../node_modules/.bin/webpack\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.umd.js\",\n\t\"module\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"lodash\": \"^4.17.21\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/lodash\": \"^4.14.200\"\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/src/BezierCurve.ts",
    "content": "import { Point } from './Point';\nimport { Polygon } from './Polygon';\n\nexport enum BezierCurvepPoints {\n\tSOURCE = 0,\n\tSOURCE_CONTROL = 1,\n\tTARGET_CONTROL = 2,\n\tTARGET = 3\n}\n\nexport class BezierCurve extends Polygon {\n\tconstructor() {\n\t\tsuper([new Point(0, 0), new Point(0, 0), new Point(0, 0), new Point(0, 0)]);\n\t}\n\n\tgetSVGCurve(): string {\n\t\treturn `M${this.getSource().toSVG()} C${this.getSourceControl().toSVG()}, ${this.getTargetControl().toSVG()}, ${this.getTarget().toSVG()}`;\n\t}\n\n\tsetPoints(points: Point[]) {\n\t\tif (points.length !== 4) {\n\t\t\tthrow new Error('BezierCurve must have extactly 4 points');\n\t\t}\n\t\tsuper.setPoints(points);\n\t}\n\n\tgetSource(): Point {\n\t\treturn this.points[BezierCurvepPoints.SOURCE];\n\t}\n\n\tgetSourceControl(): Point {\n\t\treturn this.points[BezierCurvepPoints.SOURCE_CONTROL];\n\t}\n\n\tgetTargetControl(): Point {\n\t\treturn this.points[BezierCurvepPoints.TARGET_CONTROL];\n\t}\n\n\tgetTarget(): Point {\n\t\treturn this.points[BezierCurvepPoints.TARGET];\n\t}\n\n\tsetSource(point: Point) {\n\t\tthis.points[BezierCurvepPoints.SOURCE] = point;\n\t}\n\n\tsetSourceControl(point: Point) {\n\t\tthis.points[BezierCurvepPoints.SOURCE_CONTROL] = point;\n\t}\n\n\tsetTargetControl(point: Point) {\n\t\tthis.points[BezierCurvepPoints.TARGET_CONTROL] = point;\n\t}\n\n\tsetTarget(point: Point) {\n\t\tthis.points[BezierCurvepPoints.TARGET] = point;\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/src/Bounds.ts",
    "content": "import { Point } from './Point';\n\nexport enum BoundsCorner {\n\tTOP_LEFT = 'TL',\n\tTOP_RIGHT = 'TR',\n\tBOTTOM_RIGHT = 'BR',\n\tBOTTOM_LEFT = 'BL'\n}\n\nexport type Bounds = { [k in BoundsCorner]: Point };\n\nexport const boundsFromPositionAndSize = (x: number, y: number, width: number, height: number): Bounds => {\n\treturn {\n\t\t[BoundsCorner.TOP_LEFT]: new Point(x, y),\n\t\t[BoundsCorner.TOP_RIGHT]: new Point(x + width, y),\n\t\t[BoundsCorner.BOTTOM_RIGHT]: new Point(x + width, y + height),\n\t\t[BoundsCorner.BOTTOM_LEFT]: new Point(x, y + height)\n\t};\n};\n\nexport const createEmptyBounds = () => {\n\treturn {\n\t\t[BoundsCorner.TOP_LEFT]: new Point(),\n\t\t[BoundsCorner.TOP_RIGHT]: new Point(),\n\t\t[BoundsCorner.BOTTOM_RIGHT]: new Point(),\n\t\t[BoundsCorner.BOTTOM_LEFT]: new Point()\n\t};\n};\n"
  },
  {
    "path": "packages/geometry/src/Matrix.ts",
    "content": "import { Point } from './Point';\n\nexport class Matrix {\n\tmatrix: number[][];\n\n\tconstructor(matrix: number[][]) {\n\t\tthis.matrix = matrix;\n\t}\n\n\tmmul(matrix: Matrix): Matrix {\n\t\tthis.matrix = this.matrix.map((row, i) =>\n\t\t\tmatrix.asArray()[0].map((_, j) => row.reduce((acc, _, n) => acc + this.matrix[i][n] * matrix.asArray()[n][j], 0))\n\t\t);\n\t\treturn this;\n\t}\n\n\tasArray(): number[][] {\n\t\treturn this.matrix;\n\t}\n\n\tget(rowIndex: number, columnIndex: number): number {\n\t\treturn this.asArray()[rowIndex][columnIndex];\n\t}\n\n\tpublic static multiply(...matrices: Matrix[]): Matrix {\n\t\tlet m: Matrix = matrices[0];\n\t\tfor (let i = 1; i < matrices.length; i++) {\n\t\t\tm = m.mmul(matrices[i]);\n\t\t}\n\t\treturn m;\n\t}\n\n\tpublic static scaleMatrix(x: number, y: number): Matrix {\n\t\treturn new Matrix([\n\t\t\t[x, 0, 0],\n\t\t\t[0, y, 0],\n\t\t\t[0, 0, 1]\n\t\t]);\n\t}\n\n\tpublic static translateMatrix(x: number, y: number): Matrix {\n\t\treturn new Matrix([\n\t\t\t[1, 0, x],\n\t\t\t[0, 1, y],\n\t\t\t[0, 0, 1]\n\t\t]);\n\t}\n\n\tpublic static rotateMatrix(deg: number): Matrix {\n\t\treturn new Matrix([\n\t\t\t[Math.cos(deg), -1 * Math.sin(deg), 0],\n\t\t\t[Math.sin(deg), Math.cos(deg), 0],\n\t\t\t[0, 0, 1]\n\t\t]);\n\t}\n\n\tstatic createScaleMatrix(x, y, origin: Point): Matrix {\n\t\treturn this.multiply(\n\t\t\tMatrix.translateMatrix(origin.x, origin.y),\n\t\t\tMatrix.scaleMatrix(x, y),\n\t\t\tMatrix.translateMatrix(-origin.x, -origin.y)\n\t\t);\n\t}\n\n\tstatic createRotateMatrix(deg: number, origin: Point): Matrix {\n\t\treturn this.multiply(\n\t\t\tMatrix.translateMatrix(origin.x, origin.y),\n\t\t\tMatrix.rotateMatrix(deg),\n\t\t\tMatrix.translateMatrix(-origin.x, -origin.y)\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/src/Point.ts",
    "content": "import { Matrix } from './Matrix';\n\nexport class Point {\n\tx: number;\n\ty: number;\n\n\tconstructor(x: number = 0, y: number = 0) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t}\n\n\ttranslate(x: number, y: number) {\n\t\tthis.x += x;\n\t\tthis.y += y;\n\t}\n\n\tclone() {\n\t\treturn new Point(this.x, this.y);\n\t}\n\n\ttoSVG() {\n\t\treturn this.x + ' ' + this.y;\n\t}\n\n\tasMatrix() {\n\t\treturn new Matrix([[this.x], [this.y], [1]]);\n\t}\n\n\ttransform(matrix: Matrix) {\n\t\tlet final: Matrix = matrix.mmul(this.asMatrix());\n\t\tthis.x = final.get(0, 0);\n\t\tthis.y = final.get(1, 0);\n\t}\n\n\tpublic static middlePoint(pointA: Point, pointB: Point): Point {\n\t\treturn new Point((pointB.x + pointA.x) / 2, (pointB.y + pointA.y) / 2);\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/src/Polygon.ts",
    "content": "import { Point } from './Point';\nimport _forEach from 'lodash/forEach';\nimport _map from 'lodash/map';\nimport { Matrix } from './Matrix';\nimport { boundingBoxFromPoints } from './toolkit';\nimport { Bounds, BoundsCorner } from './Bounds';\n\nexport class Polygon {\n\tprotected points: Point[];\n\n\tconstructor(points: Point[] = []) {\n\t\tthis.points = points;\n\t}\n\n\tserialize() {\n\t\treturn _map(this.points, (point) => {\n\t\t\treturn [point.x, point.y];\n\t\t});\n\t}\n\n\tdeserialize(data: any) {\n\t\tthis.points = _map(data, (point) => {\n\t\t\treturn new Point(point[0], point[1]);\n\t\t});\n\t}\n\n\tscale(x, y, origin: Point) {\n\t\tlet matrix = Matrix.createScaleMatrix(x, y, origin);\n\t\t_forEach(this.points, (point) => {\n\t\t\tpoint.transform(matrix);\n\t\t});\n\t}\n\n\ttransform(matrix: Matrix) {\n\t\t_forEach(this.points, (point) => {\n\t\t\tpoint.transform(matrix);\n\t\t});\n\t}\n\n\tsetPoints(points: Point[]) {\n\t\tthis.points = points;\n\t}\n\n\tgetPoints(): Point[] {\n\t\treturn this.points;\n\t}\n\n\trotate(degrees: number) {\n\t\tthis.transform(Matrix.createRotateMatrix(degrees / (180 / Math.PI), this.getOrigin()));\n\t}\n\n\ttranslate(offsetX: number, offsetY: number) {\n\t\t_forEach(this.points, (point) => {\n\t\t\tpoint.translate(offsetX, offsetY);\n\t\t});\n\t}\n\n\tdoClone(ob: this) {\n\t\tthis.points = _map(ob.points, (point) => {\n\t\t\treturn point.clone();\n\t\t});\n\t}\n\n\tclone(): this {\n\t\tlet ob = Object.create(this);\n\t\tob.doClone(this);\n\t\treturn ob;\n\t}\n\n\tgetOrigin(): Point {\n\t\tif (this.points.length === 0) {\n\t\t\treturn null;\n\t\t}\n\t\tlet dimensions = boundingBoxFromPoints(this.points);\n\t\treturn Point.middlePoint(dimensions[BoundsCorner.TOP_LEFT], dimensions[BoundsCorner.BOTTOM_RIGHT]);\n\t}\n\n\tgetBoundingBox(): Bounds {\n\t\treturn boundingBoxFromPoints(this.points);\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/src/Rectangle.ts",
    "content": "import { Point } from './Point';\nimport { Polygon } from './Polygon';\nimport { Bounds, BoundsCorner, boundsFromPositionAndSize, createEmptyBounds } from './Bounds';\n\nexport class Rectangle extends Polygon {\n\tstatic fromPositionAndSize(x: number, y: number, width: number, height: number) {\n\t\treturn new Rectangle(boundsFromPositionAndSize(x, y, width, height));\n\t}\n\n\tstatic fromPointAndSize(position: Point, width: number, height: number) {\n\t\treturn new Rectangle(boundsFromPositionAndSize(position.x, position.y, width, height));\n\t}\n\n\tconstructor(points?: Bounds) {\n\t\tif (!points) {\n\t\t\tpoints = createEmptyBounds();\n\t\t}\n\n\t\tsuper([\n\t\t\tpoints[BoundsCorner.TOP_LEFT],\n\t\t\tpoints[BoundsCorner.TOP_RIGHT],\n\t\t\tpoints[BoundsCorner.BOTTOM_RIGHT],\n\t\t\tpoints[BoundsCorner.BOTTOM_LEFT]\n\t\t]);\n\t}\n\n\tupdateDimensions(x: number, y: number, width: number, height: number) {\n\t\tconst points = boundsFromPositionAndSize(x, y, width, height);\n\t\tthis.setPoints([\n\t\t\tpoints[BoundsCorner.TOP_LEFT],\n\t\t\tpoints[BoundsCorner.TOP_RIGHT],\n\t\t\tpoints[BoundsCorner.BOTTOM_RIGHT],\n\t\t\tpoints[BoundsCorner.BOTTOM_LEFT]\n\t\t]);\n\t}\n\n\tsetPoints(points: Point[]) {\n\t\tif (points.length !== 4) {\n\t\t\tthrow 'Rectangles must always have 4 points';\n\t\t}\n\t\tsuper.setPoints(points);\n\t}\n\n\tcontainsPoint(point: Point) {\n\t\tconst tl = this.getTopLeft();\n\t\tconst br = this.getBottomRight();\n\n\t\treturn point.x >= tl.x && point.x <= br.x && point.y >= tl.y && point.y <= br.y;\n\t}\n\n\tgetWidth(): number {\n\t\treturn Math.sqrt(\n\t\t\tMath.pow(this.getTopLeft().x - this.getTopRight().x, 2) + Math.pow(this.getTopLeft().y - this.getTopRight().y, 2)\n\t\t);\n\t}\n\n\tgetHeight(): number {\n\t\treturn Math.sqrt(\n\t\t\tMath.pow(this.getBottomLeft().x - this.getTopLeft().x, 2) +\n\t\t\t\tMath.pow(this.getBottomLeft().y - this.getTopLeft().y, 2)\n\t\t);\n\t}\n\n\tgetTopMiddle(): Point {\n\t\treturn Point.middlePoint(this.getTopLeft(), this.getTopRight());\n\t}\n\n\tgetBottomMiddle(): Point {\n\t\treturn Point.middlePoint(this.getBottomLeft(), this.getBottomRight());\n\t}\n\n\tgetLeftMiddle(): Point {\n\t\treturn Point.middlePoint(this.getBottomLeft(), this.getTopLeft());\n\t}\n\n\tgetRightMiddle(): Point {\n\t\treturn Point.middlePoint(this.getBottomRight(), this.getTopRight());\n\t}\n\n\tgetTopLeft(): Point {\n\t\treturn this.points[0];\n\t}\n\n\tgetTopRight(): Point {\n\t\treturn this.points[1];\n\t}\n\n\tgetBottomRight(): Point {\n\t\treturn this.points[2];\n\t}\n\n\tgetBottomLeft(): Point {\n\t\treturn this.points[3];\n\t}\n}\n"
  },
  {
    "path": "packages/geometry/src/index.ts",
    "content": "export * from './Point';\nexport * from './Matrix';\nexport * from './Polygon';\nexport * from './Rectangle';\nexport * from './BezierCurve';\nexport * from './toolkit';\nexport * from './Bounds';\n"
  },
  {
    "path": "packages/geometry/src/toolkit.ts",
    "content": "import { Point } from './Point';\nimport _flatMap from 'lodash/flatMap';\nimport { Polygon } from './Polygon';\nimport { Bounds, BoundsCorner, createEmptyBounds } from './Bounds';\n\nexport const boundingBoxFromPoints = (points: Point[]): Bounds => {\n\tif (points.length === 0) {\n\t\treturn createEmptyBounds();\n\t}\n\n\tlet minX = points[0].x;\n\tlet maxX = points[0].x;\n\tlet minY = points[0].y;\n\tlet maxY = points[0].y;\n\n\tfor (let i = 1; i < points.length; i++) {\n\t\tif (points[i].x < minX) {\n\t\t\tminX = points[i].x;\n\t\t}\n\t\tif (points[i].x > maxX) {\n\t\t\tmaxX = points[i].x;\n\t\t}\n\t\tif (points[i].y < minY) {\n\t\t\tminY = points[i].y;\n\t\t}\n\t\tif (points[i].y > maxY) {\n\t\t\tmaxY = points[i].y;\n\t\t}\n\t}\n\n\treturn {\n\t\t[BoundsCorner.TOP_LEFT]: new Point(minX, minY),\n\t\t[BoundsCorner.TOP_RIGHT]: new Point(maxX, minY),\n\t\t[BoundsCorner.BOTTOM_RIGHT]: new Point(maxX, maxY),\n\t\t[BoundsCorner.BOTTOM_LEFT]: new Point(minX, maxY)\n\t};\n};\n\nexport const boundingBoxFromPolygons = (polygons: Polygon[]): Bounds => {\n\treturn boundingBoxFromPoints(\n\t\t_flatMap(polygons, (polygon) => {\n\t\t\treturn polygon.getPoints();\n\t\t})\n\t);\n};\n"
  },
  {
    "path": "packages/geometry/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.base.json\",\n\t\"compilerOptions\": {\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"sourceMap\": true,\n\t\t\"declarationDir\": \"dist/@types\",\n\t\t\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"\n\t},\n\t\"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "packages/geometry/webpack.config.js",
    "content": "const config = require('../../webpack.shared')(__dirname);\nmodule.exports = {\n\t...config,\n\toutput: {\n\t\t...config.output,\n\t\tlibrary: '@projectstorm/react-diagrams-geometry'\n\t}\n};\n"
  },
  {
    "path": "packages/react-canvas-core/.npmignore",
    "content": "*\n!dist/**/*\n!package.json\ndist/tsconfig.tsbuildinfo\n"
  },
  {
    "path": "packages/react-canvas-core/CHANGELOG.md",
    "content": "# @projectstorm/react-canvas-core\n\n## 7.0.3\n\n### Patch Changes\n\n- 09ed60f: Allow more derived State classes to provide a generic type\n- 80285fe: refactor: update lodash imports to use individual functions\n- Updated dependencies [80285fe]\n  - @projectstorm/geometry@7.0.3\n\n## 7.0.2\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n- Updated dependencies [66c687a]\n  - @projectstorm/geometry@7.0.2\n\n## 7.0.1\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/geometry@7.0.1\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/geometry@7.0.0\n"
  },
  {
    "path": "packages/react-canvas-core/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-canvas-core\",\n\t\"version\": \"7.0.3\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"rimraf ./dist\",\n\t\t\"build\": \"../../node_modules/.bin/webpack\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.umd.js\",\n\t\"module\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"@emotion/react\": \"^11.14.0\",\n\t\t\"@emotion/styled\": \"^11.11.0\",\n\t\t\"@projectstorm/geometry\": \"workspace:*\",\n\t\t\"lodash\": \"^4.17.21\",\n\t\t\"react\": \"^19.0.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/lodash\": \"^4.14.200\",\n\t\t\"@types/react\": \"^19.0.12\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/CanvasEngine.ts",
    "content": "import _debounce from 'lodash/debounce';\nimport { CanvasModel } from './entities/canvas/CanvasModel';\nimport { FactoryBank } from './core/FactoryBank';\nimport { AbstractReactFactory } from './core/AbstractReactFactory';\nimport { LayerModel } from './entities/layer/LayerModel';\nimport { BaseListener, BaseObserver } from './core/BaseObserver';\nimport { MouseEvent } from 'react';\nimport { BaseModel } from './core-models/BaseModel';\nimport { Point } from '@projectstorm/geometry';\nimport { ActionEventBus } from './core-actions/ActionEventBus';\nimport { PanAndZoomCanvasAction } from './actions/PanAndZoomCanvasAction';\nimport { ZoomCanvasAction } from './actions/ZoomCanvasAction';\nimport { DeleteItemsAction } from './actions/DeleteItemsAction';\nimport { StateMachine } from './core-state/StateMachine';\n\nexport interface CanvasEngineListener extends BaseListener {\n\tcanvasReady?(): void;\n\n\trepaintCanvas?(): void;\n\n\trendered?(): void;\n}\n\n/**\n * Defines the CanvasEngine options\n */\nexport interface CanvasEngineOptions {\n\tregisterDefaultDeleteItemsAction?: boolean;\n\tregisterDefaultPanAndZoomCanvasAction?: boolean;\n\tregisterDefaultZoomCanvasAction?: boolean;\n\t/**\n\t * Defines the debounce wait time in milliseconds if > 0\n\t */\n\trepaintDebounceMs?: number;\n}\n\nexport class CanvasEngine<\n\tL extends CanvasEngineListener = CanvasEngineListener,\n\tM extends CanvasModel = CanvasModel\n> extends BaseObserver<L> {\n\tprotected model: M;\n\tprotected layerFactories: FactoryBank<AbstractReactFactory<LayerModel>>;\n\tprotected canvas: HTMLDivElement;\n\tprotected eventBus: ActionEventBus;\n\tprotected stateMachine: StateMachine;\n\tprotected options: CanvasEngineOptions;\n\n\tconstructor(options: CanvasEngineOptions = {}) {\n\t\tsuper();\n\t\tthis.model = null;\n\t\tthis.eventBus = new ActionEventBus(this);\n\t\tthis.stateMachine = new StateMachine(this);\n\t\tthis.layerFactories = new FactoryBank();\n\t\tthis.registerFactoryBank(this.layerFactories);\n\n\t\t/**\n\t\t * Overrides the standard options with the possible given options\n\t\t */\n\t\tthis.options = {\n\t\t\tregisterDefaultDeleteItemsAction: true,\n\t\t\tregisterDefaultZoomCanvasAction: true,\n\t\t\trepaintDebounceMs: 0,\n\t\t\t...options\n\t\t};\n\t\tif (this.options.registerDefaultZoomCanvasAction === true) {\n\t\t\tthis.eventBus.registerAction(new ZoomCanvasAction());\n\t\t} else if (this.options.registerDefaultPanAndZoomCanvasAction === true) {\n\t\t\tthis.eventBus.registerAction(new PanAndZoomCanvasAction());\n\t\t}\n\t\tif (this.options.registerDefaultDeleteItemsAction === true) {\n\t\t\tthis.eventBus.registerAction(new DeleteItemsAction());\n\t\t}\n\t}\n\n\tgetStateMachine() {\n\t\treturn this.stateMachine;\n\t}\n\n\tgetRelativeMousePoint(event: { clientX: number; clientY: number }): Point {\n\t\tconst point = this.getRelativePoint(event.clientX, event.clientY);\n\t\treturn new Point(\n\t\t\t(point.x - this.model.getOffsetX()) / (this.model.getZoomLevel() / 100.0),\n\t\t\t(point.y - this.model.getOffsetY()) / (this.model.getZoomLevel() / 100.0)\n\t\t);\n\t}\n\n\tgetRelativePoint(x, y): Point {\n\t\tconst canvasRect = this.canvas.getBoundingClientRect();\n\t\treturn new Point(x - canvasRect.left, y - canvasRect.top);\n\t}\n\n\tregisterFactoryBank(factory: FactoryBank) {\n\t\tfactory.registerListener({\n\t\t\tfactoryAdded: (event) => {\n\t\t\t\tevent.factory.setDiagramEngine(this);\n\t\t\t},\n\t\t\tfactoryRemoved: (event) => {\n\t\t\t\tevent.factory.setDiagramEngine(null);\n\t\t\t}\n\t\t});\n\t}\n\n\tgetActionEventBus() {\n\t\treturn this.eventBus;\n\t}\n\n\tgetLayerFactories() {\n\t\treturn this.layerFactories;\n\t}\n\n\tgetFactoryForLayer<F extends AbstractReactFactory<LayerModel>>(layer: LayerModel | string) {\n\t\tif (typeof layer === 'string') {\n\t\t\treturn this.layerFactories.getFactory(layer);\n\t\t}\n\t\treturn this.layerFactories.getFactory(layer.getType());\n\t}\n\n\tsetModel(model: M) {\n\t\tthis.model = model;\n\t\tif (this.canvas) {\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tthis.repaintCanvas();\n\t\t\t});\n\t\t}\n\t}\n\n\tgetModel(): M {\n\t\treturn this.model;\n\t}\n\n\trepaintCanvas(promise: true): Promise<any>;\n\trepaintCanvas(): void;\n\trepaintCanvas(promise?): Promise<any> | void {\n\t\tconst { repaintDebounceMs } = this.options;\n\n\t\t/**\n\t\t * The actual repaint function\n\t\t */\n\t\tconst repaint = () => {\n\t\t\tthis.iterateListeners((listener) => {\n\t\t\t\tif (listener.repaintCanvas) {\n\t\t\t\t\tlistener.repaintCanvas();\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t// if the `repaintDebounceMs` option is > 0, then apply the debounce\n\t\tlet repaintFn = repaint;\n\n\t\tif (repaintDebounceMs > 0) {\n\t\t\trepaintFn = _debounce(repaint, repaintDebounceMs);\n\t\t}\n\n\t\tif (promise) {\n\t\t\treturn new Promise<void>((resolve) => {\n\t\t\t\tconst l = this.registerListener({\n\t\t\t\t\trendered: () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t\tl.deregister();\n\t\t\t\t\t}\n\t\t\t\t} as L);\n\t\t\t\trepaintFn();\n\t\t\t});\n\t\t}\n\n\t\trepaintFn();\n\t}\n\n\tsetCanvas(canvas?: HTMLDivElement) {\n\t\tif (this.canvas !== canvas) {\n\t\t\tthis.canvas = canvas;\n\t\t\tif (canvas) {\n\t\t\t\tthis.fireEvent({}, 'canvasReady');\n\t\t\t}\n\t\t}\n\t}\n\n\tgetCanvas() {\n\t\treturn this.canvas;\n\t}\n\n\tgetMouseElement(event: MouseEvent): BaseModel {\n\t\treturn null;\n\t}\n\n\tzoomToFit() {\n\t\tconst xFactor = this.canvas.clientWidth / this.canvas.scrollWidth;\n\t\tconst yFactor = this.canvas.clientHeight / this.canvas.scrollHeight;\n\t\tconst zoomFactor = xFactor < yFactor ? xFactor : yFactor;\n\n\t\tthis.model.setZoomLevel(this.model.getZoomLevel() * zoomFactor);\n\t\tthis.model.setOffset(0, 0);\n\t\tthis.repaintCanvas();\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/Toolkit.ts",
    "content": "export class Toolkit {\n\tstatic TESTING: boolean = false;\n\tstatic TESTING_UID = 0;\n\n\t/**\n\t * Generats a unique ID (thanks Stack overflow :3)\n\t * @returns {String}\n\t */\n\tpublic static UID(): string {\n\t\tif (Toolkit.TESTING) {\n\t\t\tToolkit.TESTING_UID++;\n\t\t\treturn `${Toolkit.TESTING_UID}`;\n\t\t}\n\t\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n\t\t\tconst r = (Math.random() * 16) | 0;\n\t\t\tconst v = c === 'x' ? r : (r & 0x3) | 0x8;\n\t\t\treturn v.toString(16);\n\t\t});\n\t}\n\n\tpublic static closest(element: Element, selector: string) {\n\t\tif (!Element.prototype.closest) {\n\t\t\tElement.prototype.closest = function (s) {\n\t\t\t\tvar el = this;\n\n\t\t\t\tdo {\n\t\t\t\t\tif (Element.prototype.matches.call(el, s)) return el;\n\t\t\t\t\tel = el.parentElement || el.parentNode;\n\t\t\t\t} while (el !== null && el.nodeType === 1);\n\t\t\t\treturn null;\n\t\t\t};\n\t\t}\n\t\treturn element.closest(selector);\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/actions/DeleteItemsAction.ts",
    "content": "import { Action, ActionEvent, InputType } from '../core-actions/Action';\nimport { KeyboardEvent } from 'react';\nimport _forEach from 'lodash/forEach';\nimport _isEqual from 'lodash/isEqual';\n\nexport interface DeleteItemsActionOptions {\n\tkeyCodes?: number[];\n\tmodifiers?: {\n\t\tctrlKey?: boolean;\n\t\tshiftKey?: boolean;\n\t\taltKey?: boolean;\n\t\tmetaKey?: boolean;\n\t};\n}\n\n/**\n * Deletes all selected items\n */\nexport class DeleteItemsAction extends Action {\n\tconstructor(options: DeleteItemsActionOptions = {}) {\n\t\tconst keyCodes = options.keyCodes || [46, 8];\n\t\tconst modifiers = {\n\t\t\tctrlKey: false,\n\t\t\tshiftKey: false,\n\t\t\taltKey: false,\n\t\t\tmetaKey: false,\n\t\t\t...options.modifiers\n\t\t};\n\n\t\tsuper({\n\t\t\ttype: InputType.KEY_DOWN,\n\t\t\tfire: (event: ActionEvent<KeyboardEvent>) => {\n\t\t\t\tconst { keyCode, ctrlKey, shiftKey, altKey, metaKey } = event.event;\n\n\t\t\t\tif (keyCodes.indexOf(keyCode) !== -1 && _isEqual({ ctrlKey, shiftKey, altKey, metaKey }, modifiers)) {\n\t\t\t\t\t_forEach(this.engine.getModel().getSelectedEntities(), (model) => {\n\t\t\t\t\t\t// only delete items which are not locked\n\t\t\t\t\t\tif (!model.isLocked()) {\n\t\t\t\t\t\t\tmodel.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/actions/PanAndZoomCanvasAction.ts",
    "content": "import { WheelEvent } from 'react';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\n\nexport interface PanAndZoomCanvasActionOptions {\n\tinverseZoom?: boolean;\n}\n\nexport class PanAndZoomCanvasAction extends Action {\n\tconstructor(options: PanAndZoomCanvasActionOptions = {}) {\n\t\tsuper({\n\t\t\ttype: InputType.MOUSE_WHEEL,\n\t\t\tfire: (actionEvent: ActionEvent<WheelEvent>) => {\n\t\t\t\tconst { event } = actionEvent;\n\t\t\t\t// we can block layer rendering because we are only targeting the transforms\n\t\t\t\tfor (let layer of this.engine.getModel().getLayers()) {\n\t\t\t\t\tlayer.allowRepaint(false);\n\t\t\t\t}\n\n\t\t\t\tconst model = this.engine.getModel();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tif (event.ctrlKey) {\n\t\t\t\t\t// Pinch and zoom gesture\n\t\t\t\t\tconst oldZoomFactor = this.engine.getModel().getZoomLevel() / 100;\n\n\t\t\t\t\tlet scrollDelta = options.inverseZoom ? event.deltaY : -event.deltaY;\n\t\t\t\t\tscrollDelta /= 3;\n\n\t\t\t\t\tif (model.getZoomLevel() + scrollDelta > 10) {\n\t\t\t\t\t\tmodel.setZoomLevel(model.getZoomLevel() + scrollDelta);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst zoomFactor = model.getZoomLevel() / 100;\n\n\t\t\t\t\tconst boundingRect = event.currentTarget.getBoundingClientRect();\n\t\t\t\t\tconst clientWidth = boundingRect.width;\n\t\t\t\t\tconst clientHeight = boundingRect.height;\n\t\t\t\t\t// compute difference between rect before and after scroll\n\t\t\t\t\tconst widthDiff = clientWidth * zoomFactor - clientWidth * oldZoomFactor;\n\t\t\t\t\tconst heightDiff = clientHeight * zoomFactor - clientHeight * oldZoomFactor;\n\t\t\t\t\t// compute mouse coords relative to canvas\n\t\t\t\t\tconst clientX = event.clientX - boundingRect.left;\n\t\t\t\t\tconst clientY = event.clientY - boundingRect.top;\n\n\t\t\t\t\t// compute width and height increment factor\n\t\t\t\t\tconst xFactor = (clientX - model.getOffsetX()) / oldZoomFactor / clientWidth;\n\t\t\t\t\tconst yFactor = (clientY - model.getOffsetY()) / oldZoomFactor / clientHeight;\n\n\t\t\t\t\tmodel.setOffset(model.getOffsetX() - widthDiff * xFactor, model.getOffsetY() - heightDiff * yFactor);\n\t\t\t\t} else {\n\t\t\t\t\t// Pan gesture\n\t\t\t\t\tlet yDelta = options.inverseZoom ? -event.deltaY : event.deltaY;\n\t\t\t\t\tlet xDelta = options.inverseZoom ? -event.deltaX : event.deltaX;\n\t\t\t\t\tmodel.setOffset(model.getOffsetX() - xDelta, model.getOffsetY() - yDelta);\n\t\t\t\t}\n\t\t\t\tthis.engine.repaintCanvas();\n\n\t\t\t\t// re-enable rendering\n\t\t\t\tfor (let layer of this.engine.getModel().getLayers()) {\n\t\t\t\t\tlayer.allowRepaint(true);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/actions/ZoomCanvasAction.ts",
    "content": "import { WheelEvent } from 'react';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\n\nexport interface ZoomCanvasActionOptions {\n\tinverseZoom?: boolean;\n}\n\nexport class ZoomCanvasAction extends Action {\n\tconstructor(options: ZoomCanvasActionOptions = {}) {\n\t\tsuper({\n\t\t\ttype: InputType.MOUSE_WHEEL,\n\t\t\tfire: (actionEvent: ActionEvent<WheelEvent>) => {\n\t\t\t\tconst { event } = actionEvent;\n\t\t\t\t// we can block layer rendering because we are only targeting the transforms\n\t\t\t\tfor (let layer of this.engine.getModel().getLayers()) {\n\t\t\t\t\tlayer.allowRepaint(false);\n\t\t\t\t}\n\n\t\t\t\tconst model = this.engine.getModel();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tconst oldZoomFactor = this.engine.getModel().getZoomLevel() / 100;\n\t\t\t\tlet scrollDelta = options.inverseZoom ? -event.deltaY : event.deltaY;\n\t\t\t\t//check if it is pinch gesture\n\t\t\t\tif (event.ctrlKey && scrollDelta % 1 !== 0) {\n\t\t\t\t\t/*\n\t\t\t\t\t\tChrome and Firefox sends wheel event with deltaY that\n\t\t\t\t\t\thave fractional part, also `ctrlKey` prop of the event is true\n\t\t\t\t\t\tthough ctrl isn't pressed\n\t\t\t\t\t*/\n\t\t\t\t\tscrollDelta /= 3;\n\t\t\t\t} else {\n\t\t\t\t\tscrollDelta /= 60;\n\t\t\t\t}\n\t\t\t\tif (model.getZoomLevel() + scrollDelta > 10) {\n\t\t\t\t\tmodel.setZoomLevel(model.getZoomLevel() + scrollDelta);\n\t\t\t\t}\n\n\t\t\t\tconst zoomFactor = model.getZoomLevel() / 100;\n\n\t\t\t\tconst boundingRect = event.currentTarget.getBoundingClientRect();\n\t\t\t\tconst clientWidth = boundingRect.width;\n\t\t\t\tconst clientHeight = boundingRect.height;\n\t\t\t\t// compute difference between rect before and after scroll\n\t\t\t\tconst widthDiff = clientWidth * zoomFactor - clientWidth * oldZoomFactor;\n\t\t\t\tconst heightDiff = clientHeight * zoomFactor - clientHeight * oldZoomFactor;\n\t\t\t\t// compute mouse coords relative to canvas\n\t\t\t\tconst clientX = event.clientX - boundingRect.left;\n\t\t\t\tconst clientY = event.clientY - boundingRect.top;\n\n\t\t\t\t// compute width and height increment factor\n\t\t\t\tconst xFactor = (clientX - model.getOffsetX()) / oldZoomFactor / clientWidth;\n\t\t\t\tconst yFactor = (clientY - model.getOffsetY()) / oldZoomFactor / clientHeight;\n\n\t\t\t\tmodel.setOffset(model.getOffsetX() - widthDiff * xFactor, model.getOffsetY() - heightDiff * yFactor);\n\t\t\t\tthis.engine.repaintCanvas();\n\n\t\t\t\t// re-enable rendering\n\t\t\t\tfor (let layer of this.engine.getModel().getLayers()) {\n\t\t\t\t\tlayer.allowRepaint(true);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core/AbstractFactory.ts",
    "content": "import { CanvasEngine } from '../CanvasEngine';\nimport { FactoryBank } from './FactoryBank';\n\n/**\n * Base factory for all the different types of entities.\n * Gets registered with the engine, and is used to generate models\n */\nexport abstract class AbstractFactory<E extends CanvasEngine = CanvasEngine> {\n\t/**\n\t * Couples the factory with the models it generates\n\t */\n\tprotected type: string;\n\t/**\n\t * The engine gets injected when the factory is registered\n\t */\n\tprotected engine: E;\n\tprotected bank: FactoryBank;\n\n\tconstructor(type: string) {\n\t\tthis.type = type;\n\t}\n\n\tsetDiagramEngine(engine: E) {\n\t\tthis.engine = engine;\n\t}\n\n\tsetFactoryBank(bank: FactoryBank) {\n\t\tthis.bank = bank;\n\t}\n\n\tgetType(): string {\n\t\treturn this.type;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core/AbstractModelFactory.ts",
    "content": "import { AbstractFactory } from './AbstractFactory';\nimport { BaseModel } from '../core-models/BaseModel';\nimport { CanvasEngine } from '../CanvasEngine';\n\nexport interface GenerateModelEvent {\n\tinitialConfig?: any;\n}\n\nexport abstract class AbstractModelFactory<\n\tT extends BaseModel = BaseModel,\n\tE extends CanvasEngine = CanvasEngine\n> extends AbstractFactory<E> {\n\t/**\n\t * Generates new models (the core factory pattern)\n\t */\n\tabstract generateModel(event: GenerateModelEvent): T;\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core/AbstractReactFactory.tsx",
    "content": "import { BaseModel } from '../core-models/BaseModel';\nimport { AbstractModelFactory } from './AbstractModelFactory';\nimport { CanvasEngine } from '../CanvasEngine';\nimport { JSX } from 'react';\n\nexport interface GenerateWidgetEvent<T extends BaseModel> {\n\tmodel: T;\n}\n\n/**\n * Further extends the AbstractFactory to add widget generation capability.\n */\nexport abstract class AbstractReactFactory<\n\tT extends BaseModel = BaseModel,\n\tE extends CanvasEngine = CanvasEngine\n> extends AbstractModelFactory<T, E> {\n\t/**\n\t * Generates React widgets from the model contained in the event object\n\t */\n\tabstract generateReactWidget(event: GenerateWidgetEvent<T>): JSX.Element;\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core/BaseObserver.ts",
    "content": "import { Toolkit } from '../Toolkit';\n\nexport interface BaseEvent {\n\tfiring: boolean;\n\tstopPropagation: () => any;\n}\n\nexport interface BaseEventProxy extends BaseEvent {\n\tfunction: string;\n}\n\n/**\n * Listeners are always in the form of an object that contains methods that take events\n */\nexport type BaseListener = {\n\t/**\n\t * Generic event that fires before a specific event was fired\n\t */\n\teventWillFire?: (event: BaseEvent & { function: string }) => void;\n\n\t/**\n\t * Generic event that fires after a specific event was fired (even if it was consumed)\n\t */\n\teventDidFire?: (event: BaseEvent & { function: string }) => void;\n} & {\n\t/**\n\t * Type for other events that will fire\n\t */\n\t[key: string]: (event: BaseEvent) => any;\n};\n\nexport interface ListenerHandle {\n\t/**\n\t * Used to degister the listener\n\t */\n\tderegister: () => any;\n\t/**\n\t * Original ID of the listener\n\t */\n\tid: string;\n\n\t/**\n\t * Original Listener\n\t */\n\tlistener: BaseListener;\n}\n\n/**\n * Base observer pattern class for working with listeners\n */\nexport class BaseObserver<L extends BaseListener = BaseListener> {\n\tprotected listeners: { [id: string]: L };\n\n\tconstructor() {\n\t\tthis.listeners = {};\n\t}\n\n\tprivate fireEventInternal(fire: boolean, k: keyof L, event: BaseEvent) {\n\t\tthis.iterateListeners((listener) => {\n\t\t\t// returning false here will instruct itteration to stop\n\t\t\tif (!fire && !event.firing) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// fire selected listener\n\t\t\tif (listener[k]) {\n\t\t\t\tlistener[k](event as BaseEvent);\n\t\t\t}\n\t\t});\n\t}\n\n\tfireEvent<K extends keyof L>(event: Partial<Parameters<L[K]>[0]>, k: keyof L) {\n\t\tevent = {\n\t\t\tfiring: true,\n\t\t\tstopPropagation: () => {\n\t\t\t\tevent.firing = false;\n\t\t\t},\n\t\t\t...event\n\t\t};\n\n\t\t// fire pre\n\t\tthis.fireEventInternal(true, 'eventWillFire', {\n\t\t\t...event,\n\t\t\tfunction: k\n\t\t} as BaseEventProxy);\n\n\t\t// fire main event\n\t\tthis.fireEventInternal(false, k, event as BaseEvent);\n\n\t\t// fire post\n\t\tthis.fireEventInternal(true, 'eventDidFire', {\n\t\t\t...event,\n\t\t\tfunction: k\n\t\t} as BaseEventProxy);\n\t}\n\n\titerateListeners(cb: (listener: L) => any) {\n\t\tfor (let id in this.listeners) {\n\t\t\tconst res = cb(this.listeners[id]);\n\t\t\t// cancel itteration on false\n\t\t\tif (res === false) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tgetListenerHandle(listener: L): ListenerHandle {\n\t\tfor (let id in this.listeners) {\n\t\t\tif (this.listeners[id] === listener) {\n\t\t\t\treturn {\n\t\t\t\t\tid: id,\n\t\t\t\t\tlistener: listener,\n\t\t\t\t\tderegister: () => {\n\t\t\t\t\t\tdelete this.listeners[id];\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tregisterListener(listener: L): ListenerHandle {\n\t\tconst id = Toolkit.UID();\n\t\tthis.listeners[id] = listener;\n\t\treturn {\n\t\t\tid: id,\n\t\t\tlistener: listener,\n\t\t\tderegister: () => {\n\t\t\t\tdelete this.listeners[id];\n\t\t\t}\n\t\t};\n\t}\n\n\tderegisterListener(listener: L | ListenerHandle) {\n\t\tif (typeof listener === 'object') {\n\t\t\t(listener as ListenerHandle).deregister();\n\t\t\treturn true;\n\t\t}\n\t\tconst handle = this.getListenerHandle(listener);\n\t\tif (handle) {\n\t\t\thandle.deregister();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core/FactoryBank.ts",
    "content": "import { BaseEvent, BaseListener, BaseObserver } from './BaseObserver';\nimport { AbstractFactory } from './AbstractFactory';\nimport _values from 'lodash/values';\n\nexport interface FactoryBankListener<F extends AbstractFactory = AbstractFactory> extends BaseListener {\n\t/**\n\t * Factory as added to rhe bank\n\t */\n\tfactoryAdded?: (event: BaseEvent & { factory: F }) => any;\n\n\t/**\n\t * Factory was removed from the bank\n\t */\n\tfactoryRemoved?: (event: BaseEvent & { factory: F }) => any;\n}\n\n/**\n * Store and managed Factories that extend from Abstractfactory\n */\nexport class FactoryBank<\n\tF extends AbstractFactory = AbstractFactory,\n\tL extends FactoryBankListener<F> = FactoryBankListener<F>\n> extends BaseObserver<L> {\n\tprotected factories: { [type: string]: F };\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.factories = {};\n\t}\n\n\tgetFactories(): F[] {\n\t\treturn _values(this.factories);\n\t}\n\n\tclearFactories() {\n\t\tfor (let factory in this.factories) {\n\t\t\tthis.deregisterFactory(factory);\n\t\t}\n\t}\n\n\tgetFactory<T extends F = F>(type: string): T {\n\t\tif (!this.factories[type]) {\n\t\t\tthrow new Error(`Cannot find factory with type [${type}]`);\n\t\t}\n\t\treturn this.factories[type] as T;\n\t}\n\n\tregisterFactory(factory: F) {\n\t\tfactory.setFactoryBank(this);\n\t\tthis.factories[factory.getType()] = factory;\n\t\t// todo fixme\n\t\tthis.fireEvent<'factoryAdded'>({ factory } as any, 'factoryAdded');\n\t}\n\n\tderegisterFactory(type: string) {\n\t\tconst factory = this.factories[type];\n\t\tfactory.setFactoryBank(null);\n\t\tdelete this.factories[type];\n\t\t// todo fixme\n\t\tthis.fireEvent<'factoryRemoved'>({ factory } as any, 'factoryRemoved');\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core/ModelGeometryInterface.ts",
    "content": "import { Rectangle } from '@projectstorm/geometry';\n\nexport interface ModelGeometryInterface {\n\tgetBoundingBox(): Rectangle;\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-actions/Action.ts",
    "content": "import { MouseEvent, KeyboardEvent, WheelEvent, TouchEvent, SyntheticEvent } from 'react';\nimport { Toolkit } from '../Toolkit';\nimport { CanvasEngine } from '../CanvasEngine';\nimport { BaseModel } from '../core-models/BaseModel';\n\nexport enum InputType {\n\tMOUSE_DOWN = 'mouse-down',\n\tMOUSE_UP = 'mouse-up',\n\tMOUSE_MOVE = 'mouse-move',\n\tMOUSE_WHEEL = 'mouse-wheel',\n\tKEY_DOWN = 'key-down',\n\tKEY_UP = 'key-up',\n\tTOUCH_START = 'touch-start',\n\tTOUCH_END = 'touch-end',\n\tTOUCH_MOVE = 'touch-move'\n}\n\nexport interface Mapping {\n\t[InputType.MOUSE_DOWN]: MouseEvent;\n\t[InputType.MOUSE_UP]: MouseEvent;\n\t[InputType.MOUSE_MOVE]: MouseEvent;\n\t[InputType.MOUSE_WHEEL]: WheelEvent;\n\t[InputType.KEY_DOWN]: KeyboardEvent;\n\t[InputType.KEY_UP]: KeyboardEvent;\n\t[InputType.TOUCH_START]: TouchEvent;\n\t[InputType.TOUCH_END]: TouchEvent;\n\t[InputType.TOUCH_MOVE]: TouchEvent;\n}\n\nexport interface ActionEvent<Event extends SyntheticEvent = SyntheticEvent, Model extends BaseModel = BaseModel> {\n\tevent: Event;\n\tmodel?: Model;\n}\n\nexport interface ActionOptions {\n\ttype: InputType;\n\tfire: (event: ActionEvent<Mapping[this['type']]>) => void;\n}\n\nexport class Action<T extends CanvasEngine = CanvasEngine> {\n\toptions: ActionOptions;\n\tid: string;\n\tengine: T;\n\n\tconstructor(options: ActionOptions) {\n\t\tthis.options = options;\n\t\tthis.id = Toolkit.UID();\n\t}\n\n\tsetEngine(engine: T) {\n\t\tthis.engine = engine;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-actions/ActionEventBus.ts",
    "content": "import { Action, ActionEvent, InputType } from './Action';\nimport { KeyboardEvent, MouseEvent } from 'react';\nimport _filter from 'lodash/filter';\nimport _keys from 'lodash/keys';\nimport { CanvasEngine } from '../CanvasEngine';\nimport { BaseModel } from '../core-models/BaseModel';\n\nexport class ActionEventBus {\n\tprotected actions: { [id: string]: Action };\n\tprotected engine: CanvasEngine;\n\tprotected keys: { [key: string]: boolean };\n\n\tconstructor(engine: CanvasEngine) {\n\t\tthis.actions = {};\n\t\tthis.engine = engine;\n\t\tthis.keys = {};\n\t}\n\n\tgetKeys(): string[] {\n\t\treturn _keys(this.keys);\n\t}\n\n\tregisterAction(action: Action): () => void {\n\t\taction.setEngine(this.engine);\n\t\tthis.actions[action.id] = action;\n\t\treturn () => {\n\t\t\tthis.deregisterAction(action);\n\t\t};\n\t}\n\n\tderegisterAction(action: Action) {\n\t\taction.setEngine(null);\n\t\tdelete this.actions[action.id];\n\t}\n\n\tgetActionsForType(type: InputType): Action[] {\n\t\treturn _filter(this.actions, (action) => {\n\t\t\treturn action.options.type === type;\n\t\t});\n\t}\n\n\tgetModelForEvent(actionEvent: ActionEvent<MouseEvent>): BaseModel {\n\t\tif (actionEvent.model) {\n\t\t\treturn actionEvent.model;\n\t\t}\n\t\treturn this.engine.getMouseElement(actionEvent.event);\n\t}\n\n\tgetActionsForEvent(actionEvent: ActionEvent): Action[] {\n\t\tconst { event } = actionEvent;\n\t\tif (event.type === 'mousedown') {\n\t\t\treturn this.getActionsForType(InputType.MOUSE_DOWN);\n\t\t} else if (event.type === 'mouseup') {\n\t\t\treturn this.getActionsForType(InputType.MOUSE_UP);\n\t\t} else if (event.type === 'keydown') {\n\t\t\t// store the recorded key\n\t\t\tthis.keys[(event as KeyboardEvent).key.toLowerCase()] = true;\n\t\t\treturn this.getActionsForType(InputType.KEY_DOWN);\n\t\t} else if (event.type === 'keyup') {\n\t\t\t// delete the recorded key\n\t\t\tdelete this.keys[(event as KeyboardEvent).key.toLowerCase()];\n\t\t\treturn this.getActionsForType(InputType.KEY_UP);\n\t\t} else if (event.type === 'mousemove') {\n\t\t\treturn this.getActionsForType(InputType.MOUSE_MOVE);\n\t\t} else if (event.type === 'wheel') {\n\t\t\treturn this.getActionsForType(InputType.MOUSE_WHEEL);\n\t\t} else if (event.type === 'touchstart') {\n\t\t\treturn this.getActionsForType(InputType.TOUCH_START);\n\t\t} else if (event.type === 'touchend') {\n\t\t\treturn this.getActionsForType(InputType.TOUCH_END);\n\t\t} else if (event.type === 'touchmove') {\n\t\t\treturn this.getActionsForType(InputType.TOUCH_MOVE);\n\t\t}\n\n\t\treturn [];\n\t}\n\n\tfireAction(actionEvent: ActionEvent) {\n\t\tconst actions = this.getActionsForEvent(actionEvent);\n\t\tfor (let action of actions) {\n\t\t\taction.options.fire(actionEvent as any);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-models/BaseEntity.ts",
    "content": "import { Toolkit } from '../Toolkit';\nimport _cloneDeep from 'lodash/cloneDeep';\nimport { CanvasEngine } from '../CanvasEngine';\nimport { BaseEvent, BaseListener, BaseObserver } from '../core/BaseObserver';\nimport { BaseModel } from './BaseModel';\n\nexport interface BaseEntityEvent<T extends BaseEntity = BaseEntity> extends BaseEvent {\n\tentity: T;\n}\n\nexport interface BaseEntityListener<T extends BaseEntity = BaseEntity> extends BaseListener {\n\tlockChanged?(event: BaseEntityEvent<T> & { locked: boolean }): void;\n}\n\n/**\n * @TODO move to enums\n */\nexport type BaseEntityType = 'node' | 'link' | 'port' | 'point';\n\nexport interface BaseEntityOptions {\n\tid?: string;\n\tlocked?: boolean;\n}\n\nexport type BaseEntityGenerics = {\n\tLISTENER: BaseEntityListener;\n\tOPTIONS: BaseEntityOptions;\n};\n\nexport interface DeserializeEvent<T extends BaseEntity = BaseEntity> {\n\tengine: CanvasEngine;\n\tdata: ReturnType<T['serialize']>;\n\tregisterModel(model: BaseModel);\n\tgetModel<T extends BaseModel>(id: string): Promise<T>;\n}\n\nexport class BaseEntity<T extends BaseEntityGenerics = BaseEntityGenerics> extends BaseObserver<T['LISTENER']> {\n\tprotected options: T['OPTIONS'];\n\n\tconstructor(options: T['OPTIONS'] = {}) {\n\t\tsuper();\n\t\tthis.options = {\n\t\t\tid: Toolkit.UID(),\n\t\t\t...options\n\t\t};\n\t}\n\n\tgetOptions() {\n\t\treturn this.options;\n\t}\n\n\tgetID() {\n\t\treturn this.options.id;\n\t}\n\n\tdoClone(lookupTable: { [s: string]: any } = {}, clone: any) {\n\t\t/*noop*/\n\t}\n\n\tclone(lookupTable: { [s: string]: any } = {}) {\n\t\t// try and use an existing clone first\n\t\tif (lookupTable[this.options.id]) {\n\t\t\treturn lookupTable[this.options.id];\n\t\t}\n\t\tlet clone = _cloneDeep(this);\n\t\tclone.options = {\n\t\t\t...this.options,\n\t\t\tid: Toolkit.UID()\n\t\t};\n\t\tclone.clearListeners();\n\t\tlookupTable[this.options.id] = clone;\n\n\t\tthis.doClone(lookupTable, clone);\n\t\treturn clone;\n\t}\n\n\tclearListeners() {\n\t\tthis.listeners = {};\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tthis.options.id = event.data.id;\n\t\tthis.options.locked = event.data.locked;\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\tid: this.options.id,\n\t\t\tlocked: this.options.locked\n\t\t};\n\t}\n\n\tfireEvent<L extends Partial<BaseEntityEvent> & object>(event: L, k: keyof T['LISTENER']) {\n\t\tsuper.fireEvent(\n\t\t\t{\n\t\t\t\tentity: this,\n\t\t\t\t...event\n\t\t\t},\n\t\t\tk\n\t\t);\n\t}\n\n\tpublic isLocked(): boolean {\n\t\treturn this.options.locked;\n\t}\n\n\tpublic setLocked(locked: boolean = true) {\n\t\tthis.options.locked = locked;\n\t\tthis.fireEvent(\n\t\t\t{\n\t\t\t\tlocked: locked\n\t\t\t},\n\t\t\t'lockChanged'\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-models/BaseModel.ts",
    "content": "import {\n\tBaseEntity,\n\tBaseEntityEvent,\n\tBaseEntityGenerics,\n\tBaseEntityListener,\n\tBaseEntityOptions,\n\tDeserializeEvent\n} from './BaseEntity';\nimport { CanvasModel } from '../entities/canvas/CanvasModel';\n\nexport interface BaseModelListener extends BaseEntityListener {\n\tselectionChanged?(event: BaseEntityEvent<BaseModel> & { isSelected: boolean }): void;\n\n\tentityRemoved?(event: BaseEntityEvent<BaseModel>): void;\n}\n\nexport interface BaseModelOptions extends BaseEntityOptions {\n\ttype?: string;\n\tselected?: boolean;\n\textras?: any;\n}\n\nexport interface BaseModelGenerics extends BaseEntityGenerics {\n\tLISTENER: BaseModelListener;\n\tPARENT: BaseEntity;\n\tOPTIONS: BaseModelOptions;\n}\n\nexport class BaseModel<G extends BaseModelGenerics = BaseModelGenerics> extends BaseEntity<G> {\n\tprotected parent: G['PARENT'];\n\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper(options);\n\t}\n\n\tperformanceTune() {\n\t\treturn true;\n\t}\n\n\tgetParentCanvasModel(): CanvasModel {\n\t\tif (!this.parent) {\n\t\t\treturn null;\n\t\t}\n\t\tif (this.parent instanceof CanvasModel) {\n\t\t\treturn this.parent;\n\t\t} else if (this.parent instanceof BaseModel) {\n\t\t\treturn this.parent.getParentCanvasModel();\n\t\t}\n\t\treturn null;\n\t}\n\n\tgetParent(): G['PARENT'] {\n\t\treturn this.parent;\n\t}\n\n\tsetParent(parent: G['PARENT']) {\n\t\tthis.parent = parent;\n\t}\n\n\tgetSelectionEntities(): Array<BaseModel> {\n\t\treturn [this];\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\ttype: this.options.type,\n\t\t\tselected: this.options.selected,\n\t\t\textras: this.options.extras\n\t\t};\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.extras = event.data.extras;\n\t\tthis.options.selected = event.data.selected;\n\t}\n\n\tgetType(): string {\n\t\treturn this.options.type;\n\t}\n\n\tisSelected(): boolean {\n\t\treturn this.options.selected;\n\t}\n\n\tisLocked(): boolean {\n\t\tconst locked = super.isLocked();\n\t\tif (locked) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// delegate this call up to the parent\n\t\tif (this.parent) {\n\t\t\treturn this.parent.isLocked();\n\t\t}\n\t\treturn false;\n\t}\n\n\tsetSelected(selected: boolean = true) {\n\t\tif (this.options.selected !== selected) {\n\t\t\tthis.options.selected = selected;\n\n\t\t\tthis.fireEvent(\n\t\t\t\t{\n\t\t\t\t\tisSelected: selected\n\t\t\t\t},\n\t\t\t\t'selectionChanged'\n\t\t\t);\n\t\t}\n\t}\n\n\tremove() {\n\t\tthis.fireEvent({}, 'entityRemoved');\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-models/BasePositionModel.ts",
    "content": "import { BaseModel, BaseModelGenerics, BaseModelListener, BaseModelOptions } from './BaseModel';\nimport { BaseEntityEvent, DeserializeEvent } from './BaseEntity';\nimport { Point, Rectangle } from '@projectstorm/geometry';\nimport { ModelGeometryInterface } from '../core/ModelGeometryInterface';\n\nexport interface BasePositionModelListener extends BaseModelListener {\n\tpositionChanged?(event: BaseEntityEvent<BasePositionModel>): void;\n}\n\nexport interface BasePositionModelOptions extends BaseModelOptions {\n\tposition?: Point;\n}\n\nexport interface BasePositionModelGenerics extends BaseModelGenerics {\n\tLISTENER: BasePositionModelListener;\n\tOPTIONS: BasePositionModelOptions;\n}\n\nexport class BasePositionModel<G extends BasePositionModelGenerics = BasePositionModelGenerics>\n\textends BaseModel<G>\n\timplements ModelGeometryInterface\n{\n\tprotected position: Point;\n\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper(options);\n\t\tthis.position = options.position || new Point(0, 0);\n\t}\n\n\tsetPosition(point: Point): void;\n\tsetPosition(x: number, y: number): void;\n\tsetPosition(x: number | Point, y?: number): void {\n\t\tif (x instanceof Point) {\n\t\t\tthis.position = x;\n\t\t} else {\n\t\t\tthis.position = new Point(x, y);\n\t\t}\n\t\tthis.fireEvent({}, 'positionChanged');\n\t}\n\n\tgetBoundingBox(): Rectangle {\n\t\treturn Rectangle.fromPointAndSize(this.position, 0, 0);\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.position = new Point(event.data.x, event.data.y);\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tx: this.position.x,\n\t\t\ty: this.position.y\n\t\t};\n\t}\n\n\tgetPosition(): Point {\n\t\treturn this.position;\n\t}\n\n\tgetX() {\n\t\treturn this.position.x;\n\t}\n\n\tgetY() {\n\t\treturn this.position.y;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-state/AbstractDisplacementState.ts",
    "content": "import { State, StateOptions } from './State';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\nimport { CanvasEngine } from '../CanvasEngine';\n\nexport interface AbstractDisplacementStateEvent {\n\tdisplacementX: number;\n\tdisplacementY: number;\n\tvirtualDisplacementX: number;\n\tvirtualDisplacementY: number;\n\tevent: React.MouseEvent | React.TouchEvent;\n}\n\nexport abstract class AbstractDisplacementState<E extends CanvasEngine = CanvasEngine> extends State<E> {\n\tinitialX: number;\n\tinitialY: number;\n\tinitialXRelative: number;\n\tinitialYRelative: number;\n\n\tconstructor(options: StateOptions) {\n\t\tsuper(options);\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (actionEvent: ActionEvent<React.MouseEvent>) => {\n\t\t\t\t\tconst { clientX, clientY } = actionEvent.event;\n\t\t\t\t\tthis.handleMoveStart(clientX, clientY);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_MOVE,\n\t\t\t\tfire: (actionEvent: ActionEvent<React.MouseEvent>) => {\n\t\t\t\t\tconst { event } = actionEvent;\n\n\t\t\t\t\tif (event.buttons === 0) {\n\t\t\t\t\t\t// If buttons is 0, it means the mouse is not down, the user may have released it\n\t\t\t\t\t\t// outside of the canvas, then we eject the state\n\t\t\t\t\t\tthis.eject();\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst { clientX, clientY } = event;\n\t\t\t\t\tthis.handleMove(clientX, clientY, event);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_UP,\n\t\t\t\tfire: () => this.handleMoveEnd()\n\t\t\t})\n\t\t);\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.TOUCH_START,\n\t\t\t\tfire: (actionEvent: ActionEvent<React.TouchEvent>) => {\n\t\t\t\t\tconst { clientX, clientY } = actionEvent.event.touches[0];\n\t\t\t\t\tthis.handleMoveStart(clientX, clientY);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.TOUCH_MOVE,\n\t\t\t\tfire: (actionEvent: ActionEvent<React.TouchEvent>) => {\n\t\t\t\t\tconst { event } = actionEvent;\n\t\t\t\t\tconst { clientX, clientY } = event.touches[0];\n\t\t\t\t\tthis.handleMove(clientX, clientY, event);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.TOUCH_END,\n\t\t\t\tfire: () => this.handleMoveEnd()\n\t\t\t})\n\t\t);\n\t}\n\n\tprotected handleMoveStart(x: number, y: number): void {\n\t\tthis.initialX = x;\n\t\tthis.initialY = y;\n\t\tconst rel = this.engine.getRelativePoint(x, y);\n\t\tthis.initialXRelative = rel.x;\n\t\tthis.initialYRelative = rel.y;\n\t}\n\n\tprotected handleMove(x: number, y: number, event: React.MouseEvent | React.TouchEvent): void {\n\t\tthis.fireMouseMoved({\n\t\t\tdisplacementX: x - this.initialX,\n\t\t\tdisplacementY: y - this.initialY,\n\t\t\tvirtualDisplacementX: (x - this.initialX) / (this.engine.getModel().getZoomLevel() / 100.0),\n\t\t\tvirtualDisplacementY: (y - this.initialY) / (this.engine.getModel().getZoomLevel() / 100.0),\n\t\t\tevent\n\t\t});\n\t}\n\n\tprotected handleMoveEnd(): void {\n\t\tthis.eject();\n\t}\n\n\tabstract fireMouseMoved(event: AbstractDisplacementStateEvent);\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-state/State.ts",
    "content": "import { CanvasEngine } from '../CanvasEngine';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\nimport { SyntheticEvent } from 'react';\nimport _intersection from 'lodash/intersection';\n\nexport interface StateOptions {\n\tname: string;\n}\n\nexport abstract class State<E extends CanvasEngine = CanvasEngine> {\n\tprotected engine: E;\n\tprotected actions: Action[];\n\tprotected keys: string[];\n\tprotected options: StateOptions;\n\tprotected childStates: State[];\n\n\tprivate handler1;\n\tprivate handler2;\n\n\tconstructor(options: StateOptions) {\n\t\tthis.actions = [];\n\t\tthis.keys = [];\n\t\tthis.childStates = [];\n\t\tthis.options = options;\n\t}\n\n\tsetEngine(engine: E) {\n\t\tthis.engine = engine;\n\t}\n\n\tgetOptions() {\n\t\treturn this.options;\n\t}\n\n\teject() {\n\t\tthis.engine.getStateMachine().popState();\n\t}\n\n\ttransitionWithEvent(state: State, event: ActionEvent<SyntheticEvent>) {\n\t\tthis.engine.getStateMachine().pushState(state);\n\t\tthis.engine.getActionEventBus().fireAction(event);\n\t}\n\n\tregisterAction(action: Action) {\n\t\tthis.actions.push(action);\n\t}\n\n\ttryActivateParentState(keys: string[]) {\n\t\tif (this.keys.length > 0 && !this.isKeysFullfilled(keys)) {\n\t\t\tthis.eject();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\ttryActivateChildState(keys: string[]) {\n\t\tconst state = this.findStateToActivate(keys);\n\t\tif (state) {\n\t\t\tthis.engine.getStateMachine().pushState(state);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tfindStateToActivate(keys: string[]) {\n\t\tfor (let child of this.childStates) {\n\t\t\tif (child.isKeysFullfilled(keys)) {\n\t\t\t\treturn child;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tisKeysFullfilled(keys: string[]) {\n\t\treturn _intersection(this.keys, keys).length === this.keys.length;\n\t}\n\n\tactivated(previous: State) {\n\t\tconst keys = this.engine.getActionEventBus().getKeys();\n\n\t\tif (this.tryActivateParentState(keys) || this.tryActivateChildState(keys)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// perhaps we need to pop again?\n\t\tthis.handler1 = this.engine.getActionEventBus().registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.KEY_DOWN,\n\t\t\t\tfire: () => {\n\t\t\t\t\tthis.tryActivateChildState(this.engine.getActionEventBus().getKeys());\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.handler2 = this.engine.getActionEventBus().registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.KEY_UP,\n\t\t\t\tfire: () => {\n\t\t\t\t\tthis.tryActivateParentState(this.engine.getActionEventBus().getKeys());\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tfor (let action of this.actions) {\n\t\t\tthis.engine.getActionEventBus().registerAction(action);\n\t\t}\n\t}\n\n\tdeactivated(next: State) {\n\t\tif (this.handler1) {\n\t\t\tthis.handler1();\n\t\t}\n\t\tif (this.handler2) {\n\t\t\tthis.handler2();\n\t\t}\n\t\t// if this happens, we are going into heirachial state machine mode\n\t\tfor (let action of this.actions) {\n\t\t\tthis.engine.getActionEventBus().deregisterAction(action);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/core-state/StateMachine.ts",
    "content": "import { State } from './State';\nimport _last from 'lodash/last';\nimport { CanvasEngine } from '../CanvasEngine';\nimport { BaseEvent, BaseListener, BaseObserver } from '../core/BaseObserver';\n\nexport interface StateMachineListener extends BaseListener {\n\tstateChanged?: (event: BaseEvent & { newState: State }) => any;\n}\n\nexport class StateMachine extends BaseObserver<StateMachineListener> {\n\tprotected currentState: State;\n\tprotected stateStack: State[];\n\tprotected engine: CanvasEngine;\n\n\tconstructor(engine: CanvasEngine) {\n\t\tsuper();\n\t\tthis.engine = engine;\n\t\tthis.stateStack = [];\n\t}\n\n\tgetCurrentState() {\n\t\treturn this.currentState;\n\t}\n\n\tpushState(state: State) {\n\t\tthis.stateStack.push(state);\n\t\tthis.setState(state);\n\t}\n\n\tpopState() {\n\t\tthis.stateStack.pop();\n\t\tthis.setState(_last(this.stateStack));\n\t}\n\n\tsetState(state: State) {\n\t\tstate.setEngine(this.engine);\n\n\t\t// if no state object, get the initial state\n\t\tif (this.currentState) {\n\t\t\tthis.currentState.deactivated(state);\n\t\t}\n\t\tconst old = this.currentState;\n\t\tthis.currentState = state;\n\t\tif (this.currentState) {\n\t\t\tthis.currentState.activated(old);\n\t\t\tthis.fireEvent<'stateChanged'>(\n\t\t\t\t{\n\t\t\t\t\tnewState: state\n\t\t\t\t},\n\t\t\t\t'stateChanged'\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/canvas/CanvasModel.ts",
    "content": "import _filter from 'lodash/filter';\nimport _flatMap from 'lodash/flatMap';\nimport _forEach from 'lodash/forEach';\nimport _map from 'lodash/map';\nimport _values from 'lodash/values';\nimport {\n\tBaseEntity,\n\tBaseEntityEvent,\n\tBaseEntityGenerics,\n\tBaseEntityListener,\n\tBaseEntityOptions,\n\tDeserializeEvent\n} from '../../core-models/BaseEntity';\nimport { LayerModel } from '../layer/LayerModel';\nimport { BaseModel } from '../../core-models/BaseModel';\nimport { CanvasEngine } from '../../CanvasEngine';\n\nexport interface CanvasModelListener extends BaseEntityListener {\n\toffsetUpdated?(event: BaseEntityEvent<CanvasModel> & { offsetX: number; offsetY: number }): void;\n\n\tzoomUpdated?(event: BaseEntityEvent<CanvasModel> & { zoom: number }): void;\n\n\tgridUpdated?(event: BaseEntityEvent<CanvasModel> & { size: number }): void;\n}\n\nexport interface CanvasModelOptions extends BaseEntityOptions {\n\toffsetX?: number;\n\toffsetY?: number;\n\tzoom?: number;\n\tgridSize?: number;\n}\n\nexport interface CanvasModelGenerics extends BaseEntityGenerics {\n\tLISTENER: CanvasModelListener;\n\tOPTIONS: CanvasModelOptions;\n\tLAYER: LayerModel;\n}\n\nexport class CanvasModel<G extends CanvasModelGenerics = CanvasModelGenerics> extends BaseEntity<G> {\n\tprotected layers: G['LAYER'][];\n\n\tconstructor(options: G['OPTIONS'] = {}) {\n\t\tsuper({\n\t\t\tzoom: 100,\n\t\t\tgridSize: 0,\n\t\t\toffsetX: 0,\n\t\t\toffsetY: 0,\n\t\t\t...options\n\t\t});\n\t\tthis.layers = [];\n\t}\n\n\tgetSelectionEntities(): BaseModel[] {\n\t\treturn _flatMap(this.layers, (layer) => {\n\t\t\treturn layer.getSelectionEntities();\n\t\t});\n\t}\n\n\tgetSelectedEntities(): BaseModel[] {\n\t\treturn _filter(this.getSelectionEntities(), (ob) => {\n\t\t\treturn ob.isSelected();\n\t\t});\n\t}\n\n\tclearSelection() {\n\t\t_forEach(this.getSelectedEntities(), (element) => {\n\t\t\telement.setSelected(false);\n\t\t});\n\t}\n\n\tgetModels(): BaseModel[] {\n\t\treturn _flatMap(this.layers, (layer) => {\n\t\t\treturn _values(layer.getModels());\n\t\t});\n\t}\n\n\taddLayer(layer: LayerModel) {\n\t\tlayer.setParent(this);\n\t\tlayer.registerListener({\n\t\t\tentityRemoved: (event: BaseEntityEvent<BaseModel>): void => {}\n\t\t});\n\t\tthis.layers.push(layer);\n\t}\n\n\tremoveLayer(layer: LayerModel) {\n\t\tconst index = this.layers.indexOf(layer);\n\t\tif (index !== -1) {\n\t\t\tthis.layers.splice(index, 1);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tgetLayers() {\n\t\treturn this.layers;\n\t}\n\n\tsetGridSize(size: number = 0) {\n\t\tthis.options.gridSize = size;\n\t\tthis.fireEvent({ size: size }, 'gridUpdated');\n\t}\n\n\tgetGridPosition(pos: number) {\n\t\tif (this.options.gridSize === 0) {\n\t\t\treturn pos;\n\t\t}\n\t\treturn this.options.gridSize * Math.floor((pos + this.options.gridSize / 2) / this.options.gridSize);\n\t}\n\n\tdeserializeModel(data: ReturnType<this['serialize']>, engine: CanvasEngine) {\n\t\tconst models: {\n\t\t\t[id: string]: BaseModel;\n\t\t} = {};\n\t\tconst promises: {\n\t\t\t[id: string]: Promise<BaseModel>;\n\t\t} = {};\n\t\tconst resolvers: {\n\t\t\t[id: string]: (model: BaseModel) => any;\n\t\t} = {};\n\n\t\tconst event: DeserializeEvent = {\n\t\t\tdata: data,\n\t\t\tengine: engine,\n\t\t\tregisterModel: (model: BaseModel) => {\n\t\t\t\tmodels[model.getID()] = model;\n\t\t\t\tif (resolvers[model.getID()]) {\n\t\t\t\t\tresolvers[model.getID()](model);\n\t\t\t\t}\n\t\t\t},\n\t\t\tgetModel<T extends BaseModel>(id: string): Promise<T> {\n\t\t\t\tif (models[id]) {\n\t\t\t\t\treturn Promise.resolve(models[id]) as Promise<T>;\n\t\t\t\t}\n\t\t\t\tif (!promises[id]) {\n\t\t\t\t\tpromises[id] = new Promise((resolve) => {\n\t\t\t\t\t\tresolvers[id] = resolve;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn promises[id] as Promise<T>;\n\t\t\t}\n\t\t};\n\t\tthis.deserialize(event);\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.offsetX = event.data.offsetX;\n\t\tthis.options.offsetY = event.data.offsetY;\n\t\tthis.options.zoom = event.data.zoom;\n\t\tthis.options.gridSize = event.data.gridSize;\n\t\t_forEach(event.data.layers, (layer) => {\n\t\t\tconst layerOb = event.engine.getFactoryForLayer(layer.type).generateModel({\n\t\t\t\tinitialConfig: layer\n\t\t\t});\n\t\t\tlayerOb.deserialize({\n\t\t\t\t...event,\n\t\t\t\tdata: layer\n\t\t\t});\n\t\t\tthis.addLayer(layerOb);\n\t\t});\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\toffsetX: this.options.offsetX,\n\t\t\toffsetY: this.options.offsetY,\n\t\t\tzoom: this.options.zoom,\n\t\t\tgridSize: this.options.gridSize,\n\t\t\tlayers: _map(this.layers, (layer) => {\n\t\t\t\treturn layer.serialize();\n\t\t\t})\n\t\t};\n\t}\n\n\tsetZoomLevel(zoom: number) {\n\t\tthis.options.zoom = zoom;\n\t\tthis.fireEvent({ zoom }, 'zoomUpdated');\n\t}\n\n\tsetOffset(offsetX: number, offsetY: number) {\n\t\tthis.options.offsetX = offsetX;\n\t\tthis.options.offsetY = offsetY;\n\t\tthis.fireEvent({ offsetX, offsetY }, 'offsetUpdated');\n\t}\n\n\tsetOffsetX(offsetX: number) {\n\t\tthis.setOffset(offsetX, this.options.offsetY);\n\t}\n\n\tsetOffsetY(offsetY: number) {\n\t\tthis.setOffset(this.options.offsetX, offsetY);\n\t}\n\n\tgetOffsetY() {\n\t\treturn this.options.offsetY;\n\t}\n\n\tgetOffsetX() {\n\t\treturn this.options.offsetX;\n\t}\n\n\tgetZoomLevel() {\n\t\treturn this.options.zoom;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/canvas/CanvasWidget.tsx",
    "content": "import * as React from 'react';\nimport { CanvasEngine } from '../../CanvasEngine';\nimport { TransformLayerWidget } from '../layer/TransformLayerWidget';\nimport styled from '@emotion/styled';\nimport { SmartLayerWidget } from '../layer/SmartLayerWidget';\n\nexport interface DiagramProps {\n\tengine: CanvasEngine;\n\tclassName?: string;\n}\n\nnamespace S {\n\texport const Canvas = styled.div`\n\t\tposition: relative;\n\t\tcursor: move;\n\t\toverflow: hidden;\n\t`;\n}\n\nexport class CanvasWidget extends React.Component<DiagramProps> {\n\tref: React.RefObject<HTMLDivElement>;\n\tkeyUp: any;\n\tkeyDown: any;\n\tcanvasListener: any;\n\n\tconstructor(props: DiagramProps) {\n\t\tsuper(props);\n\n\t\tthis.ref = React.createRef();\n\t\tthis.state = {\n\t\t\taction: null,\n\t\t\tdiagramEngineListener: null\n\t\t};\n\t}\n\n\tcomponentWillUnmount() {\n\t\tthis.props.engine.deregisterListener(this.canvasListener);\n\t\tthis.props.engine.setCanvas(null);\n\n\t\tdocument.removeEventListener('keyup', this.keyUp);\n\t\tdocument.removeEventListener('keydown', this.keyDown);\n\t}\n\n\tregisterCanvas() {\n\t\tthis.props.engine.setCanvas(this.ref.current);\n\t\tthis.props.engine.iterateListeners((list) => {\n\t\t\tlist.rendered && list.rendered();\n\t\t});\n\t}\n\n\tcomponentDidUpdate() {\n\t\tthis.registerCanvas();\n\t}\n\n\tcomponentDidMount() {\n\t\tthis.canvasListener = this.props.engine.registerListener({\n\t\t\trepaintCanvas: () => {\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\t\t});\n\n\t\tthis.keyDown = (event) => {\n\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t};\n\t\tthis.keyUp = (event) => {\n\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t};\n\n\t\tdocument.addEventListener('keyup', this.keyUp);\n\t\tdocument.addEventListener('keydown', this.keyDown);\n\t\tthis.registerCanvas();\n\t}\n\n\trender() {\n\t\tconst engine = this.props.engine;\n\t\tconst model = engine.getModel();\n\n\t\treturn (\n\t\t\t<S.Canvas\n\t\t\t\tclassName={this.props.className}\n\t\t\t\tref={this.ref}\n\t\t\t\tonWheel={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t\tonMouseDown={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t\tonMouseUp={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t\tonMouseMove={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t\tonTouchStart={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t\tonTouchEnd={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t\tonTouchMove={(event) => {\n\t\t\t\t\tthis.props.engine.getActionEventBus().fireAction({ event });\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{model.getLayers().map((layer) => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<TransformLayerWidget layer={layer} key={layer.getID()}>\n\t\t\t\t\t\t\t<SmartLayerWidget layer={layer} engine={this.props.engine} key={layer.getID()} />\n\t\t\t\t\t\t</TransformLayerWidget>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</S.Canvas>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/layer/LayerModel.ts",
    "content": "import { BaseModel, BaseModelGenerics, BaseModelOptions } from '../../core-models/BaseModel';\nimport { CanvasModel } from '../canvas/CanvasModel';\nimport _flatMap from 'lodash/flatMap';\nimport _forEach from 'lodash/forEach';\nimport _mapValues from 'lodash/mapValues';\nimport { CanvasEngine } from '../../CanvasEngine';\nimport { FactoryBank } from '../../core/FactoryBank';\nimport { AbstractModelFactory } from '../../core/AbstractModelFactory';\nimport { DeserializeEvent } from '../../core-models/BaseEntity';\n\nexport interface LayerModelOptions extends BaseModelOptions {\n\tisSvg?: boolean;\n\ttransformed?: boolean;\n}\n\nexport interface LayerModelGenerics extends BaseModelGenerics {\n\tOPTIONS: LayerModelOptions;\n\tPARENT: CanvasModel;\n\tCHILDREN: BaseModel;\n\tENGINE: CanvasEngine;\n}\n\nexport abstract class LayerModel<G extends LayerModelGenerics = LayerModelGenerics> extends BaseModel<G> {\n\tprotected models: { [id: string]: G['CHILDREN'] };\n\tprotected repaintEnabled: boolean;\n\n\tconstructor(options: G['OPTIONS'] = {}) {\n\t\tsuper(options);\n\t\tthis.models = {};\n\t\tthis.repaintEnabled = true;\n\t}\n\n\t/**\n\t * This is used for deserialization\n\t */\n\tabstract getChildModelFactoryBank(engine: G['ENGINE']): FactoryBank<AbstractModelFactory<BaseModel>>;\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.isSvg = !!event.data.isSvg;\n\t\tthis.options.transformed = !!event.data.transformed;\n\t\t_forEach(event.data.models, (model) => {\n\t\t\tconst modelOb = this.getChildModelFactoryBank(event.engine).getFactory(model.type).generateModel({\n\t\t\t\tinitialConfig: model\n\t\t\t});\n\t\t\tmodelOb.deserialize({\n\t\t\t\t...event,\n\t\t\t\tdata: model\n\t\t\t});\n\t\t\tthis.addModel(modelOb);\n\t\t});\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tisSvg: this.options.isSvg,\n\t\t\ttransformed: this.options.transformed,\n\t\t\tmodels: _mapValues(this.models, (model) => {\n\t\t\t\treturn model.serialize();\n\t\t\t})\n\t\t};\n\t}\n\n\tisRepaintEnabled() {\n\t\treturn this.repaintEnabled;\n\t}\n\n\tallowRepaint(allow: boolean = true) {\n\t\tthis.repaintEnabled = allow;\n\t}\n\n\tremove() {\n\t\tif (this.parent) {\n\t\t\tthis.parent.removeLayer(this);\n\t\t}\n\t\tsuper.remove();\n\t}\n\n\taddModel(model: G['CHILDREN']) {\n\t\tmodel.setParent(this);\n\t\tthis.models[model.getID()] = model;\n\t}\n\n\tgetSelectionEntities(): Array<BaseModel> {\n\t\treturn _flatMap(this.models, (model) => {\n\t\t\treturn model.getSelectionEntities();\n\t\t});\n\t}\n\n\tgetModels() {\n\t\treturn this.models;\n\t}\n\n\tgetModel(id: string) {\n\t\treturn this.models[id];\n\t}\n\n\tremoveModel(id: string | G['CHILDREN']): boolean {\n\t\tconst _id = typeof id === 'string' ? id : id.getID();\n\t\tif (this.models[_id]) {\n\t\t\tdelete this.models[_id];\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/layer/SmartLayerWidget.tsx",
    "content": "import * as React from 'react';\nimport { LayerModel } from './LayerModel';\nimport { CanvasEngine } from '../../CanvasEngine';\n\nexport interface SmartLayerWidgetProps {\n\tlayer: LayerModel;\n\tengine: CanvasEngine;\n}\n\nexport class SmartLayerWidget extends React.Component<SmartLayerWidgetProps> {\n\tshouldComponentUpdate(): boolean {\n\t\treturn this.props.layer.isRepaintEnabled();\n\t}\n\n\trender() {\n\t\treturn this.props.engine.getFactoryForLayer(this.props.layer).generateReactWidget({ model: this.props.layer });\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/layer/TransformLayerWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\nimport { CSSProperties } from 'react';\nimport { LayerModel } from './LayerModel';\nimport { css } from '@emotion/react';\n\nexport interface TransformLayerWidgetProps {\n\tlayer: LayerModel;\n}\n\nnamespace S {\n\tconst shared = css`\n\t\ttop: 0;\n\t\tleft: 0;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tposition: absolute;\n\t\tpointer-events: none;\n\t\ttransform-origin: 0 0;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\toverflow: visible;\n\t`;\n\n\texport const DivLayer = styled.div`\n\t\t${shared}\n\t`;\n\n\texport const SvgLayer = styled.svg`\n\t\t${shared}\n\t`;\n}\n\nexport class TransformLayerWidget extends React.Component<React.PropsWithChildren<TransformLayerWidgetProps>> {\n\tconstructor(props: TransformLayerWidgetProps) {\n\t\tsuper(props);\n\t\tthis.state = {};\n\t}\n\n\tgetTransform() {\n\t\tconst model = this.props.layer.getParent();\n\t\treturn `\n\t\t\ttranslate(\n\t\t\t\t${model.getOffsetX()}px,\n\t\t\t\t${model.getOffsetY()}px)\n\t\t\tscale(\n\t\t\t\t${model.getZoomLevel() / 100.0}\n\t\t\t)\n  \t`;\n\t}\n\n\tgetTransformStyle(): CSSProperties {\n\t\tif (this.props.layer.getOptions().transformed) {\n\t\t\treturn {\n\t\t\t\ttransform: this.getTransform()\n\t\t\t};\n\t\t}\n\t\treturn {};\n\t}\n\n\trender() {\n\t\tif (this.props.layer.getOptions().isSvg) {\n\t\t\treturn <S.SvgLayer style={this.getTransformStyle()}>{this.props.children}</S.SvgLayer>;\n\t\t}\n\t\treturn <S.DivLayer style={this.getTransformStyle()}>{this.props.children}</S.DivLayer>;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/selection/SelectionBoxLayerFactory.tsx",
    "content": "import * as React from 'react';\nimport { AbstractReactFactory, GenerateWidgetEvent } from '../../core/AbstractReactFactory';\nimport { SelectionLayerModel } from './SelectionLayerModel';\nimport { GenerateModelEvent } from '../../core/AbstractModelFactory';\nimport { SelectionBoxWidget } from './SelectionBoxWidget';\nimport { JSX } from 'react';\n\nexport class SelectionBoxLayerFactory extends AbstractReactFactory<SelectionLayerModel> {\n\tconstructor() {\n\t\tsuper('selection');\n\t}\n\n\tgenerateModel(event: GenerateModelEvent): SelectionLayerModel {\n\t\treturn new SelectionLayerModel();\n\t}\n\n\tgenerateReactWidget(event: GenerateWidgetEvent<SelectionLayerModel>): JSX.Element {\n\t\treturn <SelectionBoxWidget rect={event.model.box} />;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/selection/SelectionBoxWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\nimport { SimpleClientRect } from '../../states/SelectionBoxState';\n\nexport interface SelectionBoxWidgetProps {\n\trect: SimpleClientRect;\n}\n\nnamespace S {\n\texport const Container = styled.div`\n\t\tposition: absolute;\n\t\tbackground-color: rgba(0, 192, 255, 0.2);\n\t\tborder: solid 2px rgb(0, 192, 255);\n\t`;\n}\n\nexport class SelectionBoxWidget extends React.Component<SelectionBoxWidgetProps> {\n\trender() {\n\t\tconst { rect } = this.props;\n\n\t\tif (!rect) return null;\n\n\t\treturn (\n\t\t\t<S.Container\n\t\t\t\tstyle={{\n\t\t\t\t\ttop: rect.top,\n\t\t\t\t\tleft: rect.left,\n\t\t\t\t\twidth: rect.width,\n\t\t\t\t\theight: rect.height\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/entities/selection/SelectionLayerModel.ts",
    "content": "import { LayerModel } from '../layer/LayerModel';\nimport { FactoryBank } from '../../core/FactoryBank';\nimport { AbstractModelFactory } from '../../core/AbstractModelFactory';\nimport { BaseModel } from '../../core-models/BaseModel';\nimport { SimpleClientRect } from '../../states/SelectionBoxState';\n\nexport class SelectionLayerModel extends LayerModel {\n\tbox: SimpleClientRect;\n\n\tconstructor() {\n\t\tsuper({\n\t\t\ttransformed: false,\n\t\t\tisSvg: false,\n\t\t\ttype: 'selection'\n\t\t});\n\t}\n\n\tsetBox(rect: SimpleClientRect) {\n\t\tthis.box = rect;\n\t}\n\n\tgetChildModelFactoryBank(): FactoryBank<AbstractModelFactory<BaseModel>> {\n\t\t// is not used as it doesnt serialize\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/index.ts",
    "content": "export * from './CanvasEngine';\nexport * from './Toolkit';\nexport * from './entities/canvas/CanvasModel';\n\nexport * from './core/AbstractFactory';\nexport * from './core/AbstractModelFactory';\nexport * from './core/AbstractReactFactory';\nexport * from './core/BaseObserver';\nexport * from './core/FactoryBank';\nexport * from './core/ModelGeometryInterface';\n\nexport * from './core-actions/Action';\nexport * from './core-actions/ActionEventBus';\n\nexport * from './core-models/BaseEntity';\nexport * from './core-models/BaseModel';\nexport * from './core-models/BasePositionModel';\n\nexport * from './entities/canvas/CanvasModel';\nexport * from './entities/canvas/CanvasWidget';\n\nexport * from './entities/layer/LayerModel';\nexport * from './entities/layer/TransformLayerWidget';\nexport * from './entities/layer/SmartLayerWidget';\n\nexport * from './entities/selection/SelectionBoxLayerFactory';\nexport * from './entities/selection/SelectionBoxWidget';\nexport * from './entities/selection/SelectionLayerModel';\n\nexport * from './widgets/PeformanceWidget';\n\nexport * from './core-state/AbstractDisplacementState';\nexport * from './core-state/State';\nexport * from './core-state/StateMachine';\n\nexport * from './states/DefaultState';\nexport * from './states/DragCanvasState';\nexport * from './states/SelectingState';\nexport * from './states/SelectionBoxState';\nexport * from './states/MoveItemsState';\n\nexport * from './actions/DeleteItemsAction';\nexport * from './actions/ZoomCanvasAction';\nexport * from './actions/PanAndZoomCanvasAction';\n"
  },
  {
    "path": "packages/react-canvas-core/src/states/DefaultState.ts",
    "content": "import { State } from '../core-state/State';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\nimport { MouseEvent, TouchEvent } from 'react';\nimport { DragCanvasState } from './DragCanvasState';\nimport { SelectingState } from './SelectingState';\nimport { MoveItemsState } from './MoveItemsState';\n\nexport class DefaultState extends State {\n\tconstructor() {\n\t\tsuper({\n\t\t\tname: 'default'\n\t\t});\n\t\tthis.childStates = [new SelectingState()];\n\n\t\t// determine what was clicked on\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(event);\n\n\t\t\t\t\t// the canvas was clicked on, transition to the dragging canvas state\n\t\t\t\t\tif (!element) {\n\t\t\t\t\t\tthis.transitionWithEvent(new DragCanvasState(), event);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.transitionWithEvent(new MoveItemsState(), event);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\t// touch drags the canvas\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.TOUCH_START,\n\t\t\t\tfire: (event: ActionEvent<TouchEvent>) => {\n\t\t\t\t\tthis.transitionWithEvent(new DragCanvasState(), event);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/states/DragCanvasState.ts",
    "content": "import { CanvasEngine } from '../CanvasEngine';\nimport { AbstractDisplacementState, AbstractDisplacementStateEvent } from '../core-state/AbstractDisplacementState';\nimport { State } from '../core-state/State';\n\nexport interface DragCanvasStateOptions {\n\t/**\n\t * If enabled, the canvas is available to drag\n\t */\n\tallowDrag?: boolean;\n}\n\nexport class DragCanvasState<E extends CanvasEngine = CanvasEngine> extends AbstractDisplacementState<E> {\n\t// store this as we drag the canvas\n\tinitialCanvasX: number;\n\tinitialCanvasY: number;\n\tconfig: DragCanvasStateOptions;\n\n\tconstructor(options: DragCanvasStateOptions = {}) {\n\t\tsuper({\n\t\t\tname: 'drag-canvas'\n\t\t});\n\t\tthis.config = {\n\t\t\tallowDrag: true,\n\t\t\t...options\n\t\t};\n\t}\n\n\tasync activated(prev) {\n\t\tsuper.activated(prev);\n\t\tthis.engine.getModel().clearSelection();\n\t\tawait this.engine.repaintCanvas(true);\n\n\t\t// we can block layer rendering because we are only targeting the transforms\n\t\tfor (let layer of this.engine.getModel().getLayers()) {\n\t\t\tlayer.allowRepaint(false);\n\t\t}\n\n\t\tthis.initialCanvasX = this.engine.getModel().getOffsetX();\n\t\tthis.initialCanvasY = this.engine.getModel().getOffsetY();\n\t}\n\n\tdeactivated(next: State) {\n\t\tsuper.deactivated(next);\n\t\tfor (let layer of this.engine.getModel().getLayers()) {\n\t\t\tlayer.allowRepaint(true);\n\t\t}\n\t}\n\n\tfireMouseMoved(event: AbstractDisplacementStateEvent) {\n\t\tif (this.config.allowDrag) {\n\t\t\tthis.engine\n\t\t\t\t.getModel()\n\t\t\t\t.setOffset(this.initialCanvasX + event.displacementX, this.initialCanvasY + event.displacementY);\n\t\t\tthis.engine.repaintCanvas();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/states/MoveItemsState.ts",
    "content": "import { AbstractDisplacementState, AbstractDisplacementStateEvent } from '../core-state/AbstractDisplacementState';\nimport { State } from '../core-state/State';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\nimport { BasePositionModel } from '../core-models/BasePositionModel';\nimport { Point } from '@projectstorm/geometry';\nimport { CanvasEngine } from '../CanvasEngine';\n\nexport class MoveItemsState<E extends CanvasEngine = CanvasEngine> extends AbstractDisplacementState<E> {\n\tinitialPositions: {\n\t\t[id: string]: {\n\t\t\tpoint: Point;\n\t\t\titem: BasePositionModel;\n\t\t};\n\t};\n\n\tconstructor() {\n\t\tsuper({\n\t\t\tname: 'move-items'\n\t\t});\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (event: ActionEvent<React.MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(event);\n\t\t\t\t\tif (!element) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!element.isSelected()) {\n\t\t\t\t\t\tthis.engine.getModel().clearSelection();\n\t\t\t\t\t}\n\t\t\t\t\telement.setSelected(true);\n\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\tactivated(previous: State) {\n\t\tsuper.activated(previous);\n\t\tthis.initialPositions = {};\n\t}\n\n\tfireMouseMoved(event: AbstractDisplacementStateEvent) {\n\t\tconst items = this.engine.getModel().getSelectedEntities();\n\t\tconst model = this.engine.getModel();\n\t\tfor (let item of items) {\n\t\t\tif (item instanceof BasePositionModel) {\n\t\t\t\tif (item.isLocked()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!this.initialPositions[item.getID()]) {\n\t\t\t\t\tthis.initialPositions[item.getID()] = {\n\t\t\t\t\t\tpoint: item.getPosition(),\n\t\t\t\t\t\titem: item\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst pos = this.initialPositions[item.getID()].point;\n\t\t\t\titem.setPosition(\n\t\t\t\t\tmodel.getGridPosition(pos.x + event.virtualDisplacementX),\n\t\t\t\t\tmodel.getGridPosition(pos.y + event.virtualDisplacementY)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.engine.repaintCanvas();\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/states/SelectingState.ts",
    "content": "import { State } from '../core-state/State';\nimport { Action, ActionEvent, InputType } from '../core-actions/Action';\nimport { SelectionBoxState } from './SelectionBoxState';\nimport { MouseEvent } from 'react';\nimport { CanvasEngine } from '../CanvasEngine';\n\nexport class SelectingState<E extends CanvasEngine = CanvasEngine> extends State<E> {\n\tconstructor() {\n\t\tsuper({\n\t\t\tname: 'selecting'\n\t\t});\n\t\tthis.keys = ['shift'];\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(event);\n\n\t\t\t\t\t// go into a selection box on the canvas state\n\t\t\t\t\tif (!element) {\n\t\t\t\t\t\tthis.transitionWithEvent(new SelectionBoxState(), event);\n\t\t\t\t\t} else {\n\t\t\t\t\t\telement.setSelected(true);\n\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/states/SelectionBoxState.ts",
    "content": "import { AbstractDisplacementState, AbstractDisplacementStateEvent } from '../core-state/AbstractDisplacementState';\nimport { State } from '../core-state/State';\nimport { SelectionLayerModel } from '../entities/selection/SelectionLayerModel';\nimport { Point, Rectangle } from '@projectstorm/geometry';\nimport { BasePositionModel } from '../core-models/BasePositionModel';\nimport { ModelGeometryInterface } from '../core/ModelGeometryInterface';\nimport { CanvasEngine } from '../CanvasEngine';\n\nexport interface SimpleClientRect {\n\tleft: number;\n\tright: number;\n\twidth: number;\n\theight: number;\n\ttop: number;\n\tbottom: number;\n}\n\nexport class SelectionBoxState<E extends CanvasEngine = CanvasEngine> extends AbstractDisplacementState<E> {\n\tlayer: SelectionLayerModel;\n\n\tconstructor() {\n\t\tsuper({\n\t\t\tname: 'selection-box'\n\t\t});\n\t}\n\n\tactivated(previous: State) {\n\t\tsuper.activated(previous);\n\t\tthis.layer = new SelectionLayerModel();\n\t\tthis.engine.getModel().addLayer(this.layer);\n\t}\n\n\tdeactivated(next: State) {\n\t\tsuper.deactivated(next);\n\t\tthis.layer.remove();\n\t\tthis.engine.repaintCanvas();\n\t}\n\n\tgetBoxDimensions(event: AbstractDisplacementStateEvent): SimpleClientRect {\n\t\tlet rel: Point;\n\n\t\tif ('touches' in event.event) {\n\t\t\tconst touch = event.event.touches[0];\n\t\t\trel = this.engine.getRelativePoint(touch.clientX, touch.clientY);\n\t\t} else {\n\t\t\trel = this.engine.getRelativePoint(event.event.clientX, event.event.clientY);\n\t\t}\n\n\t\treturn {\n\t\t\tleft: rel.x > this.initialXRelative ? this.initialXRelative : rel.x,\n\t\t\ttop: rel.y > this.initialYRelative ? this.initialYRelative : rel.y,\n\t\t\twidth: Math.abs(rel.x - this.initialXRelative),\n\t\t\theight: Math.abs(rel.y - this.initialYRelative),\n\t\t\tright: rel.x < this.initialXRelative ? this.initialXRelative : rel.x,\n\t\t\tbottom: rel.y < this.initialYRelative ? this.initialYRelative : rel.y\n\t\t};\n\t}\n\n\tfireMouseMoved(event: AbstractDisplacementStateEvent) {\n\t\tthis.layer.setBox(this.getBoxDimensions(event));\n\n\t\tconst relative = this.engine.getRelativeMousePoint({\n\t\t\tclientX: this.initialX,\n\t\t\tclientY: this.initialY\n\t\t});\n\t\tif (event.virtualDisplacementX < 0) {\n\t\t\trelative.x -= Math.abs(event.virtualDisplacementX);\n\t\t}\n\t\tif (event.virtualDisplacementY < 0) {\n\t\t\trelative.y -= Math.abs(event.virtualDisplacementY);\n\t\t}\n\t\tconst rect = Rectangle.fromPointAndSize(\n\t\t\trelative,\n\t\t\tMath.abs(event.virtualDisplacementX),\n\t\t\tMath.abs(event.virtualDisplacementY)\n\t\t);\n\n\t\tfor (let model of this.engine.getModel().getSelectionEntities()) {\n\t\t\tif ((model as unknown as ModelGeometryInterface).getBoundingBox) {\n\t\t\t\tconst bounds = (model as unknown as ModelGeometryInterface).getBoundingBox();\n\t\t\t\tif (rect.containsPoint(bounds.getTopLeft()) && rect.containsPoint(bounds.getBottomRight())) {\n\t\t\t\t\tmodel.setSelected(true);\n\t\t\t\t} else {\n\t\t\t\t\tmodel.setSelected(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.engine.repaintCanvas();\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/src/widgets/PeformanceWidget.tsx",
    "content": "import * as React from 'react';\nimport _isEqual from 'lodash/isEqual';\nimport { BaseModel } from '../core-models/BaseModel';\nimport { JSX } from 'react';\n\nexport interface PeformanceWidgetProps {\n\tchildren: () => JSX.Element;\n\tserialized: object;\n\tmodel: BaseModel;\n}\n\nexport interface PeformanceWidgetState {}\n\nexport class PeformanceWidget extends React.Component<PeformanceWidgetProps, PeformanceWidgetState> {\n\tshouldComponentUpdate(\n\t\tnextProps: Readonly<PeformanceWidgetProps>,\n\t\tnextState: Readonly<PeformanceWidgetState>,\n\t\tnextContext: any\n\t): boolean {\n\t\tif (!this.props.model.performanceTune()) {\n\t\t\treturn true;\n\t\t}\n\t\t// deserialization event\n\t\tif (this.props.model !== nextProps.model) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// change event\n\t\treturn !_isEqual(this.props.serialized, nextProps.serialized);\n\t}\n\n\trender() {\n\t\treturn this.props.children();\n\t}\n}\n"
  },
  {
    "path": "packages/react-canvas-core/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.base.json\",\n\t\"compilerOptions\": {\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"declarationDir\": \"dist/@types\",\n\t\t\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"\n\t},\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"../geometry\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "packages/react-canvas-core/webpack.config.js",
    "content": "const config = require('../../webpack.shared')(__dirname);\nmodule.exports = {\n\t...config,\n\toutput: {\n\t\t...config.output,\n\t\tlibrary: 'projectstorm/react-canvas-core'\n\t}\n};\n"
  },
  {
    "path": "packages/react-diagrams/.npmignore",
    "content": "*\n!dist/**/*\n!package.json\ndist/tsconfig.tsbuildinfo\n"
  },
  {
    "path": "packages/react-diagrams/CHANGELOG.md",
    "content": "# @projectstorm/react-diagrams\n\n## 7.0.4\n\n### Patch Changes\n\n- Updated dependencies [09ed60f]\n- Updated dependencies [20766f5]\n- Updated dependencies [80285fe]\n  - @projectstorm/react-canvas-core@7.0.3\n  - @projectstorm/react-diagrams-core@7.0.3\n  - @projectstorm/react-diagrams-defaults@7.1.3\n  - @projectstorm/react-diagrams-routing@7.1.3\n\n## 7.0.3\n\n### Patch Changes\n\n- Updated dependencies [66c687a]\n  - @projectstorm/react-diagrams-defaults@7.1.2\n  - @projectstorm/react-diagrams-routing@7.1.2\n  - @projectstorm/react-diagrams-core@7.0.2\n  - @projectstorm/react-canvas-core@7.0.2\n\n## 7.0.2\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/react-canvas-core@7.0.1\n  - @projectstorm/react-diagrams-core@7.0.1\n  - @projectstorm/react-diagrams-defaults@7.1.1\n  - @projectstorm/react-diagrams-routing@7.1.1\n\n## 7.0.1\n\n### Patch Changes\n\n- Updated dependencies [e0d21f1]\n  - @projectstorm/react-diagrams-defaults@7.1.0\n  - @projectstorm/react-diagrams-routing@7.1.0\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/react-diagrams-defaults@7.0.0\n  - @projectstorm/react-diagrams-routing@7.0.0\n  - @projectstorm/react-diagrams-core@7.0.0\n  - @projectstorm/react-canvas-core@7.0.0\n"
  },
  {
    "path": "packages/react-diagrams/README.md",
    "content": ""
  },
  {
    "path": "packages/react-diagrams/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-diagrams\",\n\t\"version\": \"7.0.4\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"rimraf ./dist\",\n\t\t\"build\": \"../../node_modules/.bin/webpack\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.umd.js\",\n\t\"module\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"@projectstorm/react-canvas-core\": \"workspace:*\",\n\t\t\"@projectstorm/react-diagrams-core\": \"workspace:*\",\n\t\t\"@projectstorm/react-diagrams-defaults\": \"workspace:*\",\n\t\t\"@projectstorm/react-diagrams-routing\": \"workspace:*\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams/src/index.ts",
    "content": "import {\n\tDefaultDiagramState,\n\tDiagramEngine,\n\tLinkLayerFactory,\n\tNodeLayerFactory\n} from '@projectstorm/react-diagrams-core';\nimport {\n\tDefaultLabelFactory,\n\tDefaultLinkFactory,\n\tDefaultNodeFactory,\n\tDefaultPortFactory\n} from '@projectstorm/react-diagrams-defaults';\nimport { PathFindingLinkFactory } from '@projectstorm/react-diagrams-routing';\nimport { SelectionBoxLayerFactory, CanvasEngineOptions } from '@projectstorm/react-canvas-core';\n\nexport * from '@projectstorm/react-canvas-core';\nexport * from '@projectstorm/react-diagrams-core';\nexport * from '@projectstorm/react-diagrams-defaults';\nexport * from '@projectstorm/react-diagrams-routing';\n\n/**\n * Construct an engine with the defaults installed\n */\nexport default (options: CanvasEngineOptions = {}): DiagramEngine => {\n\tconst engine = new DiagramEngine(options);\n\n\t// register model factories\n\tengine.getLayerFactories().registerFactory(new NodeLayerFactory());\n\tengine.getLayerFactories().registerFactory(new LinkLayerFactory());\n\tengine.getLayerFactories().registerFactory(new SelectionBoxLayerFactory());\n\n\tengine.getLabelFactories().registerFactory(new DefaultLabelFactory());\n\tengine.getNodeFactories().registerFactory(new DefaultNodeFactory()); // i cant figure out why\n\tengine.getLinkFactories().registerFactory(new DefaultLinkFactory());\n\tengine.getLinkFactories().registerFactory(new PathFindingLinkFactory());\n\tengine.getPortFactories().registerFactory(new DefaultPortFactory());\n\n\t// register the default interaction behaviours\n\tengine.getStateMachine().pushState(new DefaultDiagramState());\n\treturn engine;\n};\n"
  },
  {
    "path": "packages/react-diagrams/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.base.json\",\n\t\"compilerOptions\": {\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"declarationDir\": \"dist/@types\",\n\t\t\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"\n\t},\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"../react-canvas-core\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"../react-diagrams-defaults\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"../react-diagrams-routing\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "packages/react-diagrams/webpack.config.js",
    "content": "const config = require('../../webpack.shared')(__dirname);\nmodule.exports = {\n\t...config,\n\toutput: {\n\t\t...config.output,\n\t\tlibrary: 'projectstorm/react-diagrams'\n\t}\n};\n"
  },
  {
    "path": "packages/react-diagrams-core/.npmignore",
    "content": "*\n!dist/**/*\n!package.json\ndist/tsconfig.tsbuildinfo\n"
  },
  {
    "path": "packages/react-diagrams-core/CHANGELOG.md",
    "content": "# Changelog\n\n## 7.0.3\n\n### Patch Changes\n\n- 09ed60f: Allow more derived State classes to provide a generic type\n- 80285fe: refactor: update lodash imports to use individual functions\n- Updated dependencies [09ed60f]\n- Updated dependencies [80285fe]\n  - @projectstorm/react-canvas-core@7.0.3\n  - @projectstorm/geometry@7.0.3\n\n## 7.0.2\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n- Updated dependencies [66c687a]\n  - @projectstorm/react-canvas-core@7.0.2\n  - @projectstorm/geometry@7.0.2\n\n## 7.0.1\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/geometry@7.0.1\n  - @projectstorm/react-canvas-core@7.0.1\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/react-canvas-core@7.0.0\n  - @projectstorm/geometry@7.0.0\n\n## 6.0.0\n\n### Breaking changes\n\n- `AbstractFactory:getNewInstance` renamed to `AbstractFactory:generateModel` and now gets given an event object\n  so that we can add to the event object without relying on more parameters\n\n- `AbstractFactory::generateReactWidget` now receives an event object\n\n- Moved factories in the diagramEngine into `FactoryBank`'s, which means we can remove the listeners in the DiagramEngine.\n  methods such as factoryAdded and factoryRemoved are now available on the FactoryBank (better design that allows more control)\n\n- `addListener` renamed to `registerListener`\n"
  },
  {
    "path": "packages/react-diagrams-core/README.md",
    "content": "# Project STORM > React Diagrams > Core\n\nThis workspace houses the default models\n"
  },
  {
    "path": "packages/react-diagrams-core/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-diagrams-core\",\n\t\"version\": \"7.0.3\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"rimraf ./dist\",\n\t\t\"build\": \"../../node_modules/.bin/webpack\",\n\t\t\"build:es\": \"../../node_modules/.bin/tsc\",\n\t\t\"build:prod\": \"NODE_ENV=production ../../node_modules/.bin/webpack && NODE_ENV=production  ../../node_modules/.bin/tsc\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.umd.js\",\n\t\"module\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"@emotion/styled\": \"^11.11.0\",\n\t\t\"@projectstorm/geometry\": \"workspace:*\",\n\t\t\"@projectstorm/react-canvas-core\": \"workspace:*\",\n\t\t\"lodash\": \"^4.17.21\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"resize-observer-polyfill\": \"^1.5.1\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/lodash\": \"^4.14.200\",\n\t\t\"@types/react\": \"^19.0.12\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/DiagramEngine.ts",
    "content": "import { NodeModel } from './entities/node/NodeModel';\nimport { PortModel } from './entities/port/PortModel';\nimport { LinkModel } from './entities/link/LinkModel';\nimport { LabelModel } from './entities/label/LabelModel';\nimport { boundingBoxFromPolygons, Point, Rectangle } from '@projectstorm/geometry';\nimport { JSX, MouseEvent } from 'react';\nimport {\n\tAbstractModelFactory,\n\tAbstractReactFactory,\n\tBaseModel,\n\tCanvasEngine,\n\tCanvasEngineListener,\n\tCanvasEngineOptions,\n\tFactoryBank,\n\tToolkit\n} from '@projectstorm/react-canvas-core';\nimport { DiagramModel } from './models/DiagramModel';\n\n/**\n * Passed as a parameter to the DiagramWidget\n */\nexport class DiagramEngine extends CanvasEngine<CanvasEngineListener, DiagramModel> {\n\tprotected nodeFactories: FactoryBank<AbstractReactFactory<NodeModel, DiagramEngine>>;\n\tprotected linkFactories: FactoryBank<AbstractReactFactory<LinkModel, DiagramEngine>>;\n\tprotected portFactories: FactoryBank<AbstractModelFactory<PortModel, DiagramEngine>>;\n\tprotected labelFactories: FactoryBank<AbstractReactFactory<LabelModel, DiagramEngine>>;\n\n\tmaxNumberPointsPerLink: number;\n\n\tconstructor(options: CanvasEngineOptions = {}) {\n\t\tsuper(options);\n\t\tthis.maxNumberPointsPerLink = 1000;\n\n\t\t// create banks for the different factory types\n\t\tthis.nodeFactories = new FactoryBank();\n\t\tthis.linkFactories = new FactoryBank();\n\t\tthis.portFactories = new FactoryBank();\n\t\tthis.labelFactories = new FactoryBank();\n\n\t\tconst setup = (factory: FactoryBank) => {\n\t\t\tfactory.registerListener({\n\t\t\t\tfactoryAdded: (event) => {\n\t\t\t\t\tevent.factory.setDiagramEngine(this);\n\t\t\t\t},\n\t\t\t\tfactoryRemoved: (event) => {\n\t\t\t\t\tevent.factory.setDiagramEngine(null);\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tsetup(this.nodeFactories);\n\t\tsetup(this.linkFactories);\n\t\tsetup(this.portFactories);\n\t\tsetup(this.labelFactories);\n\t}\n\n\t/**\n\t * Gets a model and element under the mouse cursor\n\t */\n\tgetMouseElement(event: MouseEvent): BaseModel {\n\t\tvar target = event.target as Element;\n\t\tvar diagramModel = this.model;\n\n\t\t//is it a port\n\t\tvar element = Toolkit.closest(target, '.port[data-name]');\n\t\tif (element) {\n\t\t\tvar nodeElement = Toolkit.closest(target, '.node[data-nodeid]') as HTMLElement;\n\t\t\treturn diagramModel.getNode(nodeElement.getAttribute('data-nodeid')).getPort(element.getAttribute('data-name'));\n\t\t}\n\n\t\t//look for a point\n\t\telement = Toolkit.closest(target, '.point[data-id]');\n\t\tif (element) {\n\t\t\treturn diagramModel.getLink(element.getAttribute('data-linkid')).getPointModel(element.getAttribute('data-id'));\n\t\t}\n\n\t\t//look for a link\n\t\telement = Toolkit.closest(target, '[data-linkid]');\n\t\tif (element) {\n\t\t\treturn diagramModel.getLink(element.getAttribute('data-linkid'));\n\t\t}\n\n\t\t//look for a node\n\t\telement = Toolkit.closest(target, '.node[data-nodeid]');\n\t\tif (element) {\n\t\t\treturn diagramModel.getNode(element.getAttribute('data-nodeid'));\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t//!-------------- FACTORIES ------------\n\n\tgetNodeFactories() {\n\t\treturn this.nodeFactories;\n\t}\n\n\tgetLinkFactories() {\n\t\treturn this.linkFactories;\n\t}\n\n\tgetLabelFactories() {\n\t\treturn this.labelFactories;\n\t}\n\n\tgetPortFactories() {\n\t\treturn this.portFactories;\n\t}\n\n\tgetFactoryForNode<F extends AbstractReactFactory<NodeModel, DiagramEngine>>(node: NodeModel | string) {\n\t\tif (typeof node === 'string') {\n\t\t\treturn this.nodeFactories.getFactory(node);\n\t\t}\n\t\treturn this.nodeFactories.getFactory(node.getType());\n\t}\n\n\tgetFactoryForLink<F extends AbstractReactFactory<LinkModel, DiagramEngine>>(link: LinkModel | string) {\n\t\tif (typeof link === 'string') {\n\t\t\treturn this.linkFactories.getFactory<F>(link);\n\t\t}\n\t\treturn this.linkFactories.getFactory<F>(link.getType());\n\t}\n\n\tgetFactoryForLabel<F extends AbstractReactFactory<LabelModel, DiagramEngine>>(label: LabelModel) {\n\t\tif (typeof label === 'string') {\n\t\t\treturn this.labelFactories.getFactory<F>(label);\n\t\t}\n\t\treturn this.labelFactories.getFactory<F>(label.getType());\n\t}\n\n\tgetFactoryForPort<F extends AbstractModelFactory<PortModel, DiagramEngine>>(port: PortModel) {\n\t\tif (typeof port === 'string') {\n\t\t\treturn this.portFactories.getFactory<F>(port);\n\t\t}\n\t\treturn this.portFactories.getFactory<F>(port.getType());\n\t}\n\n\tgenerateWidgetForLink(link: LinkModel): JSX.Element {\n\t\treturn this.getFactoryForLink(link).generateReactWidget({ model: link });\n\t}\n\n\tgenerateWidgetForNode(node: NodeModel): JSX.Element {\n\t\treturn this.getFactoryForNode(node).generateReactWidget({ model: node });\n\t}\n\n\tgetNodeElement(node: NodeModel): Element {\n\t\tconst selector = this.canvas.querySelector(`.node[data-nodeid=\"${node.getID()}\"]`);\n\t\tif (selector === null) {\n\t\t\tthrow new Error('Cannot find Node element with nodeID: [' + node.getID() + ']');\n\t\t}\n\t\treturn selector;\n\t}\n\n\tgetNodePortElement(port: PortModel): any {\n\t\tvar selector = this.canvas.querySelector(\n\t\t\t`.port[data-name=\"${port.getName()}\"][data-nodeid=\"${port.getParent().getID()}\"]`\n\t\t);\n\t\tif (selector === null) {\n\t\t\tthrow new Error(\n\t\t\t\t'Cannot find Node Port element with nodeID: [' +\n\t\t\t\t\tport.getParent().getID() +\n\t\t\t\t\t'] and name: [' +\n\t\t\t\t\tport.getName() +\n\t\t\t\t\t']'\n\t\t\t);\n\t\t}\n\t\treturn selector;\n\t}\n\n\tgetPortCenter(port: PortModel): Point {\n\t\treturn this.getPortCoords(port).getOrigin();\n\t}\n\n\t/**\n\t * Calculate rectangular coordinates of the port passed in.\n\t */\n\tgetPortCoords(port: PortModel, element?: HTMLDivElement): Rectangle {\n\t\tif (!this.canvas) {\n\t\t\tthrow new Error('Canvas needs to be set first');\n\t\t}\n\t\tif (!element) {\n\t\t\telement = this.getNodePortElement(port);\n\t\t}\n\t\tconst sourceRect = element.getBoundingClientRect();\n\t\tconst point = this.getRelativeMousePoint({\n\t\t\tclientX: sourceRect.left,\n\t\t\tclientY: sourceRect.top\n\t\t});\n\t\tconst zoom = this.model.getZoomLevel() / 100.0;\n\t\treturn Rectangle.fromPointAndSize(point, sourceRect.width / zoom, sourceRect.height / zoom);\n\t}\n\n\t/**\n\t * Determine the width and height of the node passed in.\n\t * It currently assumes nodes have a rectangular shape, can be overriden for customised shapes.\n\t */\n\tgetNodeDimensions(node: NodeModel): { width: number; height: number } {\n\t\tif (!this.canvas) {\n\t\t\treturn {\n\t\t\t\twidth: 0,\n\t\t\t\theight: 0\n\t\t\t};\n\t\t}\n\n\t\tconst nodeElement = this.getNodeElement(node);\n\t\tconst nodeRect = nodeElement.getBoundingClientRect();\n\n\t\treturn {\n\t\t\twidth: nodeRect.width,\n\t\t\theight: nodeRect.height\n\t\t};\n\t}\n\n\tgetBoundingNodesRect(nodes: NodeModel[]): Rectangle {\n\t\tif (nodes) {\n\t\t\tif (nodes.length === 0) {\n\t\t\t\treturn new Rectangle();\n\t\t\t}\n\t\t\treturn new Rectangle(boundingBoxFromPolygons(nodes.map((node) => node.getBoundingBox())));\n\t\t}\n\t}\n\n\tzoomToFitSelectedNodes(options: { margin?: number; maxZoom?: number }) {\n\t\tconst nodes: NodeModel[] = this.model\n\t\t\t.getSelectedEntities()\n\t\t\t.filter((entity) => entity instanceof NodeModel) as NodeModel[];\n\t\tthis.zoomToFitNodes({\n\t\t\tmargin: options.margin,\n\t\t\tmaxZoom: options.maxZoom,\n\t\t\tnodes: nodes.length > 0 ? nodes : null\n\t\t});\n\t}\n\n\tzoomToFitNodes(options: { margin?: number; nodes?: NodeModel[]; maxZoom?: number });\n\t/**\n\t * @deprecated\n\t */\n\tzoomToFitNodes(margin: number);\n\tzoomToFitNodes(options) {\n\t\tlet margin = options || 0;\n\t\tlet nodes: NodeModel[] = [];\n\t\tlet maxZoom: number | null = null;\n\t\tif (!!options && typeof options == 'object') {\n\t\t\tmargin = options.margin || 0;\n\t\t\tnodes = options.nodes || [];\n\t\t\tmaxZoom = options.maxZoom || null;\n\t\t}\n\n\t\t// no node selected\n\t\tif (nodes.length === 0) {\n\t\t\tnodes = this.model.getNodes();\n\t\t}\n\t\tconst nodesRect = this.getBoundingNodesRect(nodes);\n\t\tif (nodesRect) {\n\t\t\t// there is something we should zoom on\n\t\t\tlet canvasRect = this.canvas.getBoundingClientRect();\n\n\t\t\tconst calculate = (margin: number = 0) => {\n\t\t\t\t// work out zoom\n\t\t\t\tconst xFactor = this.canvas.clientWidth / (nodesRect.getWidth() + margin * 2);\n\t\t\t\tconst yFactor = this.canvas.clientHeight / (nodesRect.getHeight() + margin * 2);\n\n\t\t\t\tlet zoomFactor = xFactor < yFactor ? xFactor : yFactor;\n\t\t\t\tif (maxZoom && zoomFactor > maxZoom) {\n\t\t\t\t\tzoomFactor = maxZoom;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tzoom: zoomFactor,\n\t\t\t\t\tx:\n\t\t\t\t\t\tcanvasRect.width / 2 -\n\t\t\t\t\t\t((nodesRect.getWidth() + margin * 2) / 2 + nodesRect.getTopLeft().x) * zoomFactor +\n\t\t\t\t\t\tmargin,\n\t\t\t\t\ty:\n\t\t\t\t\t\tcanvasRect.height / 2 -\n\t\t\t\t\t\t((nodesRect.getHeight() + margin * 2) / 2 + nodesRect.getTopLeft().y) * zoomFactor +\n\t\t\t\t\t\tmargin\n\t\t\t\t};\n\t\t\t};\n\n\t\t\tlet params = calculate(0);\n\t\t\tif (margin) {\n\t\t\t\tif (params.x < margin || params.y < margin) {\n\t\t\t\t\tparams = calculate(margin);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// apply\n\t\t\tthis.model.setZoomLevel(params.zoom * 100);\n\t\t\tthis.model.setOffset(params.x, params.y);\n\t\t\tthis.repaintCanvas();\n\t\t}\n\t}\n\n\tgetMaxNumberPointsPerLink(): number {\n\t\treturn this.maxNumberPointsPerLink;\n\t}\n\n\tsetMaxNumberPointsPerLink(max: number) {\n\t\tthis.maxNumberPointsPerLink = max;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/label/LabelModel.ts",
    "content": "import { LinkModel } from '../link/LinkModel';\nimport { BaseModel, BaseModelGenerics, BaseModelOptions, DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport interface LabelModelOptions extends BaseModelOptions {\n\toffsetX?: number;\n\toffsetY?: number;\n}\n\nexport interface LabelModelGenerics extends BaseModelGenerics {\n\tPARENT: LinkModel;\n\tOPTIONS: LabelModelOptions;\n}\n\nexport class LabelModel<G extends LabelModelGenerics = LabelModelGenerics> extends BaseModel<G> {\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\toffsetX: options.offsetX || 0,\n\t\t\toffsetY: options.offsetY || 0\n\t\t});\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.offsetX = event.data.offsetX;\n\t\tthis.options.offsetY = event.data.offsetY;\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\toffsetX: this.options.offsetX,\n\t\t\toffsetY: this.options.offsetY\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/label/LabelWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { LabelModel } from './LabelModel';\nimport styled from '@emotion/styled';\n\nexport interface LabelWidgetProps {\n\tengine: DiagramEngine;\n\tlabel: LabelModel;\n\tindex: number;\n}\n\nnamespace S {\n\texport const Label = styled.div`\n\t\tdisplay: inline-block;\n\t\tposition: absolute;\n\t`;\n\n\texport const Foreign = styled.foreignObject`\n\t\tpointer-events: none;\n\t\toverflow: visible;\n\t`;\n}\n\nexport class LabelWidget extends React.Component<LabelWidgetProps> {\n\tref: React.RefObject<HTMLDivElement>;\n\n\tconstructor(props: LabelWidgetProps) {\n\t\tsuper(props);\n\t\tthis.ref = React.createRef();\n\t}\n\n\tcomponentDidUpdate() {\n\t\twindow.requestAnimationFrame(this.calculateLabelPosition);\n\t}\n\n\tcomponentDidMount() {\n\t\twindow.requestAnimationFrame(this.calculateLabelPosition);\n\t}\n\n\tfindPathAndRelativePositionToRenderLabel = (index: number): { path: SVGPathElement; position: number } => {\n\t\t// an array to hold all path lengths, making sure we hit the DOM only once to fetch this information\n\t\tconst link = this.props.label.getParent();\n\t\tconst lengths = link.getRenderedPath().map((path) => path.getTotalLength());\n\n\t\t// calculate the point where we want to display the label\n\t\tlet labelPosition =\n\t\t\tlengths.reduce((previousValue, currentValue) => previousValue + currentValue, 0) *\n\t\t\t(index / (link.getLabels().length + 1));\n\n\t\t// find the path where the label will be rendered and calculate the relative position\n\t\tlet pathIndex = 0;\n\t\twhile (pathIndex < link.getRenderedPath().length) {\n\t\t\tif (labelPosition - lengths[pathIndex] < 0) {\n\t\t\t\treturn {\n\t\t\t\t\tpath: link.getRenderedPath()[pathIndex],\n\t\t\t\t\tposition: labelPosition\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// keep searching\n\t\t\tlabelPosition -= lengths[pathIndex];\n\t\t\tpathIndex++;\n\t\t}\n\t};\n\n\tcalculateLabelPosition = () => {\n\t\tconst found = this.findPathAndRelativePositionToRenderLabel(this.props.index + 1);\n\t\tif (!found) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { path, position } = found;\n\n\t\tconst labelDimensions = {\n\t\t\twidth: this.ref.current.offsetWidth,\n\t\t\theight: this.ref.current.offsetHeight\n\t\t};\n\n\t\tconst pathCentre = path.getPointAtLength(position);\n\n\t\tconst labelCoordinates = {\n\t\t\tx: pathCentre.x - labelDimensions.width / 2 + this.props.label.getOptions().offsetX,\n\t\t\ty: pathCentre.y - labelDimensions.height / 2 + this.props.label.getOptions().offsetY\n\t\t};\n\n\t\tthis.ref.current.style.transform = `translate(${labelCoordinates.x}px, ${labelCoordinates.y}px)`;\n\t};\n\n\trender() {\n\t\tconst canvas = this.props.engine.getCanvas();\n\n\t\treturn (\n\t\t\t<S.Foreign key={this.props.label.getID()} width={canvas?.offsetWidth} height={canvas?.offsetHeight}>\n\t\t\t\t<S.Label ref={this.ref}>\n\t\t\t\t\t{this.props.engine.getFactoryForLabel(this.props.label).generateReactWidget({ model: this.props.label })}\n\t\t\t\t</S.Label>\n\t\t\t</S.Foreign>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/link/LinkModel.ts",
    "content": "import { PortModel } from '../port/PortModel';\nimport { PointModel } from './PointModel';\nimport _forEach from 'lodash/forEach';\nimport _map from 'lodash/map';\nimport _slice from 'lodash/slice';\nimport { LabelModel } from '../label/LabelModel';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { DiagramModel } from '../../models/DiagramModel';\nimport { boundingBoxFromPoints, Point, Rectangle } from '@projectstorm/geometry';\nimport {\n\tBaseEntityEvent,\n\tBaseModel,\n\tBaseModelGenerics,\n\tBaseModelListener,\n\tDeserializeEvent,\n\tModelGeometryInterface\n} from '@projectstorm/react-canvas-core';\n\nexport interface LinkModelListener extends BaseModelListener {\n\tsourcePortChanged?(event: BaseEntityEvent<LinkModel> & { port: null | PortModel }): void;\n\n\ttargetPortChanged?(event: BaseEntityEvent<LinkModel> & { port: null | PortModel }): void;\n}\n\nexport interface LinkModelGenerics extends BaseModelGenerics {\n\tLISTENER: LinkModelListener;\n\tPARENT: DiagramModel;\n}\n\nexport class LinkModel<G extends LinkModelGenerics = LinkModelGenerics>\n\textends BaseModel<G>\n\timplements ModelGeometryInterface\n{\n\tprotected sourcePort: PortModel | null;\n\tprotected targetPort: PortModel | null;\n\n\tprotected labels: LabelModel[];\n\tprotected points: PointModel[];\n\n\tprotected renderedPaths: SVGPathElement[];\n\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper(options);\n\t\tthis.points = [\n\t\t\tnew PointModel({\n\t\t\t\tlink: this\n\t\t\t}),\n\t\t\tnew PointModel({\n\t\t\t\tlink: this\n\t\t\t})\n\t\t];\n\t\tthis.sourcePort = null;\n\t\tthis.targetPort = null;\n\t\tthis.renderedPaths = [];\n\t\tthis.labels = [];\n\t}\n\n\tgetBoundingBox(): Rectangle {\n\t\treturn new Rectangle(\n\t\t\tboundingBoxFromPoints(\n\t\t\t\t_map(this.points, (point: PointModel) => {\n\t\t\t\t\treturn point.getPosition();\n\t\t\t\t})\n\t\t\t)\n\t\t);\n\t}\n\n\tgetSelectionEntities(): Array<BaseModel> {\n\t\tif (this.getTargetPort() && this.getSourcePort()) {\n\t\t\treturn super.getSelectionEntities().concat(_slice(this.points, 1, this.points.length - 1));\n\t\t}\n\t\t// allow selection of the first point\n\t\tif (!this.getSourcePort()) {\n\t\t\treturn super.getSelectionEntities().concat(_slice(this.points, 0, this.points.length - 1));\n\t\t}\n\t\t// allow selection of the last point\n\t\tif (!this.getTargetPort()) {\n\t\t\treturn super.getSelectionEntities().concat(_slice(this.points, 1, this.points.length));\n\t\t}\n\t\treturn super.getSelectionEntities().concat(this.points);\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.points = _map(event.data.points || [], (point) => {\n\t\t\tvar p = new PointModel({\n\t\t\t\tlink: this,\n\t\t\t\tposition: new Point(point.x, point.y)\n\t\t\t});\n\t\t\tp.deserialize({\n\t\t\t\t...event,\n\t\t\t\tdata: point\n\t\t\t});\n\t\t\treturn p;\n\t\t});\n\n\t\t//deserialize labels\n\t\t_forEach(event.data.labels || [], (label: any) => {\n\t\t\tlet labelOb = (event.engine as DiagramEngine).getFactoryForLabel(label.type).generateModel({});\n\t\t\tlabelOb.deserialize({\n\t\t\t\t...event,\n\t\t\t\tdata: label\n\t\t\t});\n\t\t\tthis.addLabel(labelOb);\n\t\t});\n\n\t\t// these happen async, so we use the promises for these (they need to be done like this without the async keyword\n\t\t// because we need the deserailize method to finish for other methods while this happen\n\t\tif (event.data.target) {\n\t\t\tevent.getModel(event.data.targetPort).then((model: PortModel) => {\n\t\t\t\tthis.setTargetPort(model);\n\t\t\t});\n\t\t}\n\t\tif (event.data.source) {\n\t\t\tevent.getModel(event.data.sourcePort).then((model: PortModel) => {\n\t\t\t\tthis.setSourcePort(model);\n\t\t\t});\n\t\t}\n\t}\n\n\tgetRenderedPath(): SVGPathElement[] {\n\t\treturn this.renderedPaths;\n\t}\n\n\tsetRenderedPaths(paths: SVGPathElement[]) {\n\t\tthis.renderedPaths = paths;\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tsource: this.sourcePort ? this.sourcePort.getParent().getID() : null,\n\t\t\tsourcePort: this.sourcePort ? this.sourcePort.getID() : null,\n\t\t\ttarget: this.targetPort ? this.targetPort.getParent().getID() : null,\n\t\t\ttargetPort: this.targetPort ? this.targetPort.getID() : null,\n\t\t\tpoints: _map(this.points, (point) => {\n\t\t\t\treturn point.serialize();\n\t\t\t}),\n\t\t\tlabels: _map(this.labels, (label) => {\n\t\t\t\treturn label.serialize();\n\t\t\t})\n\t\t};\n\t}\n\n\tdoClone(lookupTable = {}, clone) {\n\t\tclone.setPoints(\n\t\t\t_map(this.getPoints(), (point: PointModel) => {\n\t\t\t\treturn point.clone(lookupTable);\n\t\t\t})\n\t\t);\n\t\tif (this.sourcePort) {\n\t\t\tclone.setSourcePort(this.sourcePort.clone(lookupTable));\n\t\t}\n\t\tif (this.targetPort) {\n\t\t\tclone.setTargetPort(this.targetPort.clone(lookupTable));\n\t\t}\n\t}\n\n\tclearPort(port: PortModel) {\n\t\tif (this.sourcePort === port) {\n\t\t\tthis.setSourcePort(null);\n\t\t} else if (this.targetPort === port) {\n\t\t\tthis.setTargetPort(null);\n\t\t}\n\t}\n\n\tremove() {\n\t\tif (this.sourcePort) {\n\t\t\tthis.sourcePort.removeLink(this);\n\t\t\tdelete this.sourcePort;\n\t\t}\n\t\tif (this.targetPort) {\n\t\t\tthis.targetPort.removeLink(this);\n\t\t\tdelete this.targetPort;\n\t\t}\n\t\tsuper.remove();\n\t}\n\n\tisLastPoint(point: PointModel) {\n\t\tvar index = this.getPointIndex(point);\n\t\treturn index === this.points.length - 1;\n\t}\n\n\tgetPointIndex(point: PointModel) {\n\t\treturn this.points.indexOf(point);\n\t}\n\n\tgetPointModel(id: string): PointModel | null {\n\t\tfor (var i = 0; i < this.points.length; i++) {\n\t\t\tif (this.points[i].getID() === id) {\n\t\t\t\treturn this.points[i];\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tgetPortForPoint(point: PointModel): PortModel {\n\t\tif (this.sourcePort !== null && this.getFirstPoint().getID() === point.getID()) {\n\t\t\treturn this.sourcePort;\n\t\t}\n\t\tif (this.targetPort !== null && this.getLastPoint().getID() === point.getID()) {\n\t\t\treturn this.targetPort;\n\t\t}\n\t\treturn null;\n\t}\n\n\tgetPointForPort(port: PortModel): PointModel {\n\t\tif (this.sourcePort !== null && this.sourcePort.getID() === port.getID()) {\n\t\t\treturn this.getFirstPoint();\n\t\t}\n\t\tif (this.targetPort !== null && this.targetPort.getID() === port.getID()) {\n\t\t\treturn this.getLastPoint();\n\t\t}\n\t\treturn null;\n\t}\n\n\tgetFirstPoint(): PointModel {\n\t\treturn this.points[0];\n\t}\n\n\tgetLastPoint(): PointModel {\n\t\treturn this.points[this.points.length - 1];\n\t}\n\n\tsetSourcePort(port: PortModel | null) {\n\t\tif (port !== null) {\n\t\t\tport.addLink(this);\n\t\t}\n\t\tif (this.sourcePort !== null) {\n\t\t\tthis.sourcePort.removeLink(this);\n\t\t}\n\t\tthis.sourcePort = port;\n\t\tthis.fireEvent({ port }, 'sourcePortChanged');\n\t\tif (port?.reportedPosition) {\n\t\t\tthis.getPointForPort(port).setPosition(port.getCenter());\n\t\t}\n\t}\n\n\tgetSourcePort(): PortModel {\n\t\treturn this.sourcePort;\n\t}\n\n\tgetTargetPort(): PortModel {\n\t\treturn this.targetPort;\n\t}\n\n\tsetTargetPort(port: PortModel | null) {\n\t\tif (port !== null) {\n\t\t\tport.addLink(this);\n\t\t}\n\t\tif (this.targetPort !== null) {\n\t\t\tthis.targetPort.removeLink(this);\n\t\t}\n\t\tthis.targetPort = port;\n\t\tthis.fireEvent({ port }, 'targetPortChanged');\n\t\tif (port?.reportedPosition) {\n\t\t\tthis.getPointForPort(port).setPosition(port.getCenter());\n\t\t}\n\t}\n\n\tpoint(x: number, y: number, index: number = 1): PointModel {\n\t\treturn this.addPoint(this.generatePoint(x, y), index);\n\t}\n\n\taddLabel(label: LabelModel) {\n\t\tlabel.setParent(this);\n\t\tthis.labels.push(label);\n\t}\n\n\tgetPoints(): PointModel[] {\n\t\treturn this.points;\n\t}\n\n\tgetLabels() {\n\t\treturn this.labels;\n\t}\n\n\tsetPoints(points: PointModel[]) {\n\t\t_forEach(points, (point) => {\n\t\t\tpoint.setParent(this);\n\t\t});\n\t\tthis.points = points;\n\t}\n\n\tremovePoint(pointModel: PointModel) {\n\t\tif (this.isLastPoint(pointModel)) this.remove();\n\t\tthis.points.splice(this.getPointIndex(pointModel), 1);\n\t}\n\n\tremovePointsBefore(pointModel: PointModel) {\n\t\tthis.points.splice(0, this.getPointIndex(pointModel));\n\t}\n\n\tremovePointsAfter(pointModel: PointModel) {\n\t\tthis.points.splice(this.getPointIndex(pointModel) + 1);\n\t}\n\n\tremoveMiddlePoints() {\n\t\tif (this.points.length > 2) {\n\t\t\tthis.points.splice(1, this.points.length - 2);\n\t\t}\n\t}\n\n\taddPoint<P extends PointModel>(pointModel: P, index = 1): P {\n\t\tpointModel.setParent(this);\n\t\tthis.points.splice(index, 0, pointModel);\n\t\treturn pointModel;\n\t}\n\n\tgeneratePoint(x: number = 0, y: number = 0): PointModel {\n\t\treturn new PointModel({\n\t\t\tlink: this,\n\t\t\tposition: new Point(x, y)\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/link/LinkWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { LinkModel } from './LinkModel';\nimport { PointModel } from './PointModel';\nimport _map from 'lodash/map';\nimport { LabelWidget } from '../label/LabelWidget';\nimport { BaseEntityEvent, BasePositionModel, ListenerHandle, PeformanceWidget } from '@projectstorm/react-canvas-core';\nimport { PortModel } from '../port/PortModel';\n\nexport interface LinkProps {\n\tlink: LinkModel;\n\tdiagramEngine: DiagramEngine;\n}\n\nexport interface LinkState {\n\tsourcePort: PortModel;\n\ttargetPort: PortModel;\n}\n\nexport class LinkWidget extends React.Component<LinkProps, LinkState> {\n\tsourceListener: ListenerHandle;\n\ttargetListener: ListenerHandle;\n\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\tsourcePort: null,\n\t\t\ttargetPort: null\n\t\t};\n\t}\n\n\tcomponentWillUnmount(): void {\n\t\tif (this.sourceListener) {\n\t\t\tthis.sourceListener.deregister();\n\t\t}\n\t\tif (this.targetListener) {\n\t\t\tthis.targetListener.deregister();\n\t\t}\n\t}\n\n\tstatic getDerivedStateFromProps(nextProps: LinkProps, prevState: LinkState): LinkState {\n\t\treturn {\n\t\t\tsourcePort: nextProps.link.getSourcePort(),\n\t\t\ttargetPort: nextProps.link.getTargetPort()\n\t\t};\n\t}\n\n\tinstallTarget() {\n\t\tthis.targetListener && this.targetListener.deregister();\n\n\t\tif (!this.props.link.getTargetPort()) return;\n\t\tthis.targetListener = this.props.link.getTargetPort().registerListener({\n\t\t\treportInitialPosition: (event: BaseEntityEvent<BasePositionModel>) => {\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\t\t});\n\t}\n\n\tinstallSource() {\n\t\tthis.sourceListener && this.sourceListener.deregister();\n\n\t\tif (!this.props.link.getSourcePort()) return;\n\t\tthis.sourceListener = this.props.link.getSourcePort().registerListener({\n\t\t\treportInitialPosition: (event: BaseEntityEvent<BasePositionModel>) => {\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\t\t});\n\t}\n\n\tcomponentDidUpdate(prevProps: Readonly<LinkProps>, prevState: Readonly<LinkState>, snapshot) {\n\t\tif (prevState.sourcePort !== this.state.sourcePort) {\n\t\t\tthis.installSource();\n\t\t}\n\t\tif (prevState.targetPort !== this.state.targetPort) {\n\t\t\tthis.installTarget();\n\t\t}\n\t}\n\n\tpublic static generateLinePath(firstPoint: PointModel, lastPoint: PointModel): string {\n\t\treturn `M${firstPoint.getX()},${firstPoint.getY()} L ${lastPoint.getX()},${lastPoint.getY()}`;\n\t}\n\n\tcomponentDidMount(): void {\n\t\tif (this.props.link.getSourcePort()) {\n\t\t\tthis.installSource();\n\t\t}\n\t\tif (this.props.link.getTargetPort()) {\n\t\t\tthis.installTarget();\n\t\t}\n\t}\n\n\trender() {\n\t\tconst { link } = this.props;\n\n\t\t// only draw the link when we have reported positions\n\t\tif (link.getSourcePort() && !link.getSourcePort().reportedPosition) {\n\t\t\treturn null;\n\t\t}\n\t\tif (link.getTargetPort() && !link.getTargetPort().reportedPosition) {\n\t\t\treturn null;\n\t\t}\n\n\t\t//generate links\n\t\treturn (\n\t\t\t<PeformanceWidget model={this.props.link} serialized={this.props.link.serialize()}>\n\t\t\t\t{() => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<g data-linkid={this.props.link.getID()}>\n\t\t\t\t\t\t\t{this.props.diagramEngine.generateWidgetForLink(link)}\n\t\t\t\t\t\t\t{_map(this.props.link.getLabels(), (labelModel, index) => {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<LabelWidget\n\t\t\t\t\t\t\t\t\t\tkey={labelModel.getID()}\n\t\t\t\t\t\t\t\t\t\tengine={this.props.diagramEngine}\n\t\t\t\t\t\t\t\t\t\tlabel={labelModel}\n\t\t\t\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t</PeformanceWidget>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/link/PointModel.ts",
    "content": "import { LinkModel } from './LinkModel';\nimport {\n\tBaseModelListener,\n\tBasePositionModel,\n\tBasePositionModelGenerics,\n\tBasePositionModelOptions\n} from '@projectstorm/react-canvas-core';\n\nexport interface PointModelOptions extends Omit<BasePositionModelOptions, 'type'> {\n\tlink: LinkModel;\n}\n\nexport interface PointModelGenerics {\n\tPARENT: LinkModel;\n\tOPTIONS: PointModelOptions;\n\tLISTENER: BaseModelListener;\n}\n\nexport class PointModel<G extends PointModelGenerics = PointModelGenerics> extends BasePositionModel<\n\tG & BasePositionModelGenerics\n> {\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\ttype: 'point'\n\t\t});\n\t\tthis.parent = options.link;\n\t}\n\n\tisConnectedToPort(): boolean {\n\t\treturn this.parent.getPortForPoint(this) !== null;\n\t}\n\n\tgetLink(): LinkModel {\n\t\treturn this.getParent();\n\t}\n\n\tremove() {\n\t\t//clear references\n\t\tif (this.parent) {\n\t\t\tthis.parent.removePoint(this);\n\t\t}\n\t\tsuper.remove();\n\t}\n\n\tisLocked() {\n\t\treturn super.isLocked() || this.getParent().isLocked();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/link-layer/LinkLayerFactory.tsx",
    "content": "import * as React from 'react';\nimport { AbstractReactFactory, GenerateModelEvent, GenerateWidgetEvent } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { LinkLayerModel } from './LinkLayerModel';\nimport { LinkLayerWidget } from './LinkLayerWidget';\nimport { JSX } from 'react';\n\nexport class LinkLayerFactory extends AbstractReactFactory<LinkLayerModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('diagram-links');\n\t}\n\n\tgenerateModel(event: GenerateModelEvent): LinkLayerModel {\n\t\treturn new LinkLayerModel();\n\t}\n\n\tgenerateReactWidget(event: GenerateWidgetEvent<LinkLayerModel>): JSX.Element {\n\t\treturn <LinkLayerWidget layer={event.model} engine={this.engine} />;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/link-layer/LinkLayerModel.ts",
    "content": "import { LayerModel, LayerModelGenerics } from '@projectstorm/react-canvas-core';\nimport { LinkModel } from '../link/LinkModel';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { DiagramModel } from '../../models/DiagramModel';\n\nexport interface LinkLayerModelGenerics extends LayerModelGenerics {\n\tCHILDREN: LinkModel;\n\tENGINE: DiagramEngine;\n}\n\nexport class LinkLayerModel<G extends LinkLayerModelGenerics = LinkLayerModelGenerics> extends LayerModel<G> {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'diagram-links',\n\t\t\tisSvg: true,\n\t\t\ttransformed: true\n\t\t});\n\t}\n\n\taddModel(model: G['CHILDREN']): void {\n\t\tif (!(model instanceof LinkModel)) {\n\t\t\tthrow new Error('Can only add links to this layer');\n\t\t}\n\t\tmodel.registerListener({\n\t\t\tentityRemoved: () => {\n\t\t\t\t(this.getParent() as DiagramModel).removeLink(model);\n\t\t\t}\n\t\t});\n\t\tsuper.addModel(model);\n\t}\n\n\tgetLinks() {\n\t\treturn this.getModels();\n\t}\n\n\tgetChildModelFactoryBank(engine: G['ENGINE']) {\n\t\treturn engine.getLinkFactories();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/link-layer/LinkLayerWidget.tsx",
    "content": "import * as React from 'react';\nimport styled from '@emotion/styled';\nimport _map from 'lodash/map';\nimport { LinkWidget } from '../link/LinkWidget';\nimport { LinkLayerModel } from './LinkLayerModel';\nimport { DiagramEngine } from '../../DiagramEngine';\n\nexport interface LinkLayerWidgetProps {\n\tlayer: LinkLayerModel;\n\tengine: DiagramEngine;\n}\n\nnamespace S {\n\texport const Container = styled.div``;\n}\n\nexport class LinkLayerWidget extends React.Component<LinkLayerWidgetProps> {\n\trender() {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{\n\t\t\t\t\t//only perform these actions when we have a diagram\n\t\t\t\t\t_map(this.props.layer.getLinks(), (link) => {\n\t\t\t\t\t\treturn <LinkWidget key={link.getID()} link={link} diagramEngine={this.props.engine} />;\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t</>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/node/NodeModel.ts",
    "content": "import _forEach from 'lodash/forEach';\nimport _map from 'lodash/map';\nimport _values from 'lodash/values';\nimport { DiagramModel } from '../../models/DiagramModel';\nimport { PortModel } from '../port/PortModel';\nimport { LinkModel } from '../link/LinkModel';\nimport { Point, Rectangle } from '@projectstorm/geometry';\nimport {\n\tBaseEntityEvent,\n\tBaseModelListener,\n\tBasePositionModel,\n\tBasePositionModelGenerics,\n\tDeserializeEvent\n} from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '../../DiagramEngine';\n\nexport interface NodeModelListener extends BaseModelListener {\n\tpositionChanged?(event: BaseEntityEvent<NodeModel>): void;\n}\n\nexport interface NodeModelGenerics extends BasePositionModelGenerics {\n\tLISTENER: NodeModelListener;\n\tPARENT: DiagramModel;\n}\n\nexport class NodeModel<G extends NodeModelGenerics = NodeModelGenerics> extends BasePositionModel<G> {\n\tprotected ports: { [s: string]: PortModel };\n\n\t// calculated post rendering so routing can be done correctly\n\twidth: number;\n\theight: number;\n\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper(options);\n\t\tthis.ports = {};\n\t\tthis.width = 0;\n\t\tthis.height = 0;\n\t}\n\n\tgetBoundingBox(): Rectangle {\n\t\treturn Rectangle.fromPointAndSize(this.getPosition(), this.width, this.height);\n\t}\n\n\tsetPosition(point: Point): void;\n\tsetPosition(x: number, y: number): void;\n\tsetPosition(x: number | Point, y?: number): void {\n\t\tconst old = this.position;\n\n\t\tif (x instanceof Point) {\n\t\t\tsuper.setPosition(x);\n\t\t} else {\n\t\t\tsuper.setPosition(x, y);\n\t\t}\n\n\t\t//also update the port co-ordinates (for make glorious speed)\n\t\t_forEach(this.ports, (port) => {\n\t\t\tport.setPosition(port.getX() + this.position.x - old.x, port.getY() + this.position.y - old.y);\n\t\t});\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\n\t\t//deserialize ports\n\t\t_forEach(event.data.ports, (port: any) => {\n\t\t\tlet portOb = (event.engine as DiagramEngine).getFactoryForPort(port.type).generateModel({});\n\t\t\tportOb.deserialize({\n\t\t\t\t...event,\n\t\t\t\tdata: port\n\t\t\t});\n\t\t\t// the links need these\n\t\t\tevent.registerModel(portOb);\n\t\t\tthis.addPort(portOb);\n\t\t});\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tports: _map(this.ports, (port) => {\n\t\t\t\treturn port.serialize();\n\t\t\t})\n\t\t};\n\t}\n\n\tdoClone(lookupTable = {}, clone) {\n\t\t// also clone the ports\n\t\tclone.ports = {};\n\t\t_forEach(this.ports, (port) => {\n\t\t\tclone.addPort(port.clone(lookupTable));\n\t\t});\n\t}\n\n\tremove() {\n\t\tsuper.remove();\n\t\t_forEach(this.ports, (port) => {\n\t\t\t_forEach(port.getLinks(), (link) => {\n\t\t\t\tlink.remove();\n\t\t\t});\n\t\t});\n\t}\n\n\tgetPortFromID(id): PortModel | null {\n\t\tfor (var i in this.ports) {\n\t\t\tif (this.ports[i].getID() === id) {\n\t\t\t\treturn this.ports[i];\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tgetLink(id: string): LinkModel {\n\t\tfor (let portID in this.ports) {\n\t\t\tconst links = this.ports[portID].getLinks();\n\t\t\tif (links[id]) {\n\t\t\t\treturn links[id];\n\t\t\t}\n\t\t}\n\t}\n\n\tgetPort(name: string): PortModel | null {\n\t\treturn this.ports[name];\n\t}\n\n\tgetPorts(): { [s: string]: PortModel } {\n\t\treturn this.ports;\n\t}\n\n\tremovePort(port: PortModel) {\n\t\t// clear the port from the links\n\t\tfor (let link of _values(port.getLinks())) {\n\t\t\tlink.clearPort(port);\n\t\t}\n\t\t//clear the parent node reference\n\t\tif (this.ports[port.getName()]) {\n\t\t\tthis.ports[port.getName()].setParent(null);\n\t\t\tdelete this.ports[port.getName()];\n\t\t}\n\t}\n\n\taddPort(port: PortModel): PortModel {\n\t\tport.setParent(this);\n\t\tthis.ports[port.getName()] = port;\n\t\treturn port;\n\t}\n\n\tupdateDimensions({ width, height }: { width: number; height: number }) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/node/NodeWidget.tsx",
    "content": "import * as React from 'react';\nimport _forEach from 'lodash/forEach';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { NodeModel } from './NodeModel';\nimport { BaseEntityEvent, BaseModel, ListenerHandle, PeformanceWidget } from '@projectstorm/react-canvas-core';\nimport styled from '@emotion/styled';\nimport ResizeObserver from 'resize-observer-polyfill';\n\nexport interface NodeProps {\n\tnode: NodeModel;\n\tchildren?: any;\n\tdiagramEngine: DiagramEngine;\n}\n\nnamespace S {\n\texport const Node = styled.div`\n\t\tposition: absolute;\n\t\t-webkit-touch-callout: none; /* iOS Safari */\n\t\t-webkit-user-select: none; /* Chrome/Safari/Opera */\n\t\tuser-select: none;\n\t\tcursor: move;\n\t\tpointer-events: all;\n\t`;\n}\n\nexport class NodeWidget extends React.Component<NodeProps> {\n\tob: any;\n\tref: React.RefObject<HTMLDivElement>;\n\tlistener: ListenerHandle;\n\n\tconstructor(props: NodeProps) {\n\t\tsuper(props);\n\t\tthis.ref = React.createRef();\n\t}\n\n\tcomponentWillUnmount(): void {\n\t\tthis.ob.disconnect();\n\t\tthis.ob = null;\n\n\t\tthis.listener?.deregister();\n\t\tthis.listener = null;\n\t}\n\n\tcomponentDidUpdate(prevProps: Readonly<NodeProps>, prevState: Readonly<any>, snapshot?: any): void {\n\t\tif (this.listener && this.props.node !== prevProps.node) {\n\t\t\tthis.listener.deregister();\n\t\t\tthis.installSelectionListener();\n\t\t}\n\t}\n\n\tinstallSelectionListener() {\n\t\tthis.listener = this.props.node.registerListener({\n\t\t\tselectionChanged: (event: BaseEntityEvent<BaseModel> & { isSelected: boolean }) => {\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\t\t});\n\t}\n\n\tupdateSize(width: number, height: number) {\n\t\tthis.props.node.updateDimensions({ width, height });\n\n\t\t//now mark the links as dirty\n\t\ttry {\n\t\t\t_forEach(this.props.node.getPorts(), (port) => {\n\t\t\t\tport.updateCoords(this.props.diagramEngine.getPortCoords(port));\n\t\t\t});\n\t\t} catch (ex) {}\n\t}\n\n\tcomponentDidMount(): void {\n\t\t// @ts-ignore\n\t\tthis.ob = new ResizeObserver((entities) => {\n\t\t\tconst bounds = entities[0].contentRect;\n\t\t\tthis.updateSize(bounds.width, bounds.height);\n\t\t});\n\n\t\tconst b = this.ref.current.getBoundingClientRect();\n\t\tthis.updateSize(b.width, b.height);\n\t\tthis.ob.observe(this.ref.current);\n\t\tthis.installSelectionListener();\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<PeformanceWidget model={this.props.node} serialized={this.props.node.serialize()}>\n\t\t\t\t{() => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<S.Node\n\t\t\t\t\t\t\tclassName=\"node\"\n\t\t\t\t\t\t\tref={this.ref}\n\t\t\t\t\t\t\tdata-nodeid={this.props.node.getID()}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\ttop: this.props.node.getY(),\n\t\t\t\t\t\t\t\tleft: this.props.node.getX()\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{this.props.diagramEngine.generateWidgetForNode(this.props.node)}\n\t\t\t\t\t\t</S.Node>\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t</PeformanceWidget>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/node-layer/NodeLayerFactory.tsx",
    "content": "import * as React from 'react';\nimport { AbstractReactFactory, GenerateModelEvent, GenerateWidgetEvent } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { NodeLayerModel } from './NodeLayerModel';\nimport { NodeLayerWidget } from './NodeLayerWidget';\nimport { JSX } from 'react';\n\nexport class NodeLayerFactory extends AbstractReactFactory<NodeLayerModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('diagram-nodes');\n\t}\n\n\tgenerateModel(event: GenerateModelEvent): NodeLayerModel {\n\t\treturn new NodeLayerModel();\n\t}\n\n\tgenerateReactWidget(event: GenerateWidgetEvent<NodeLayerModel>): JSX.Element {\n\t\treturn <NodeLayerWidget layer={event.model} engine={this.engine} />;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/node-layer/NodeLayerModel.ts",
    "content": "import { LayerModel, LayerModelGenerics } from '@projectstorm/react-canvas-core';\nimport { NodeModel } from '../node/NodeModel';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { DiagramModel } from '../../models/DiagramModel';\n\nexport interface NodeLayerModelGenerics extends LayerModelGenerics {\n\tCHILDREN: NodeModel;\n\tENGINE: DiagramEngine;\n}\n\nexport class NodeLayerModel<G extends NodeLayerModelGenerics = NodeLayerModelGenerics> extends LayerModel<G> {\n\tconstructor() {\n\t\tsuper({\n\t\t\ttype: 'diagram-nodes',\n\t\t\tisSvg: false,\n\t\t\ttransformed: true\n\t\t});\n\t}\n\n\taddModel(model: G['CHILDREN']): void {\n\t\tif (!(model instanceof NodeModel)) {\n\t\t\tthrow new Error('Can only add nodes to this layer');\n\t\t}\n\t\tmodel.registerListener({\n\t\t\tentityRemoved: () => {\n\t\t\t\t(this.getParent() as DiagramModel).removeNode(model);\n\t\t\t}\n\t\t});\n\t\tsuper.addModel(model);\n\t}\n\n\tgetChildModelFactoryBank(engine: G['ENGINE']) {\n\t\treturn engine.getNodeFactories();\n\t}\n\n\tgetNodes() {\n\t\treturn this.getModels();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/node-layer/NodeLayerWidget.tsx",
    "content": "import * as React from 'react';\nimport _map from 'lodash/map';\nimport { NodeModel } from '../node/NodeModel';\nimport { NodeWidget } from '../node/NodeWidget';\nimport { NodeLayerModel } from './NodeLayerModel';\nimport { DiagramEngine } from '../../DiagramEngine';\n\nexport interface NodeLayerWidgetProps {\n\tlayer: NodeLayerModel;\n\tengine: DiagramEngine;\n}\n\nexport class NodeLayerWidget extends React.Component<NodeLayerWidgetProps> {\n\trender() {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{_map(this.props.layer.getNodes(), (node: NodeModel) => {\n\t\t\t\t\treturn <NodeWidget key={node.getID()} diagramEngine={this.props.engine} node={node} />;\n\t\t\t\t})}\n\t\t\t</>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/port/PortModel.ts",
    "content": "import { NodeModel } from '../node/NodeModel';\nimport { LinkModel } from '../link/LinkModel';\nimport _forEach from 'lodash/forEach';\nimport _isFinite from 'lodash/isFinite';\nimport _map from 'lodash/map';\nimport _size from 'lodash/size';\nimport _values from 'lodash/values';\nimport { Point, Rectangle } from '@projectstorm/geometry';\nimport {\n\tBaseEntityEvent,\n\tBaseModelOptions,\n\tBasePositionModel,\n\tBasePositionModelGenerics,\n\tBasePositionModelListener,\n\tDeserializeEvent\n} from '@projectstorm/react-canvas-core';\n\nexport enum PortModelAlignment {\n\tTOP = 'top',\n\tLEFT = 'left',\n\tBOTTOM = 'bottom',\n\tRIGHT = 'right'\n}\n\nexport interface PortModelListener extends BasePositionModelListener {\n\t/**\n\t * fires when it first receives positional information\n\t */\n\treportInitialPosition?: (event: BaseEntityEvent<PortModel>) => void;\n}\n\nexport interface PortModelOptions extends BaseModelOptions {\n\talignment?: PortModelAlignment;\n\tmaximumLinks?: number;\n\tname: string;\n}\n\nexport interface PortModelGenerics extends BasePositionModelGenerics {\n\tOPTIONS: PortModelOptions;\n\tPARENT: NodeModel;\n\tLISTENER: PortModelListener;\n}\n\nexport class PortModel<G extends PortModelGenerics = PortModelGenerics> extends BasePositionModel<G> {\n\tlinks: { [id: string]: LinkModel };\n\n\t// calculated post rendering so routing can be done correctly\n\twidth: number;\n\theight: number;\n\treportedPosition: boolean;\n\n\tconstructor(options: G['OPTIONS']) {\n\t\tsuper(options);\n\t\tthis.links = {};\n\t\tthis.reportedPosition = false;\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.reportedPosition = false;\n\t\tthis.options.name = event.data.name;\n\t\tthis.options.alignment = event.data.alignment;\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tname: this.options.name,\n\t\t\talignment: this.options.alignment,\n\t\t\tparentNode: this.parent.getID(),\n\t\t\tlinks: _map(this.links, (link) => {\n\t\t\t\treturn link.getID();\n\t\t\t})\n\t\t};\n\t}\n\n\tsetPosition(point: Point);\n\tsetPosition(x: number, y: number);\n\tsetPosition(x, y?) {\n\t\tlet old = this.position;\n\t\tsuper.setPosition(x, y);\n\t\t_forEach(this.getLinks(), (link) => {\n\t\t\tlet point = link.getPointForPort(this);\n\t\t\tpoint.setPosition(point.getX() + x - old.x, point.getY() + y - old.y);\n\t\t});\n\t}\n\n\tdoClone(lookupTable = {}, clone: PortModel) {\n\t\tclone.links = {};\n\t\tclone.parent = this.getParent().clone(lookupTable);\n\t}\n\n\tgetNode(): NodeModel {\n\t\treturn this.getParent();\n\t}\n\n\tgetName(): string {\n\t\treturn this.options.name;\n\t}\n\n\tgetMaximumLinks(): number {\n\t\treturn this.options.maximumLinks;\n\t}\n\n\tsetMaximumLinks(maximumLinks: number) {\n\t\tthis.options.maximumLinks = maximumLinks;\n\t}\n\n\tremoveLink(link: LinkModel) {\n\t\tdelete this.links[link.getID()];\n\t}\n\n\taddLink(link: LinkModel) {\n\t\tthis.links[link.getID()] = link;\n\t}\n\n\tgetLinks(): { [id: string]: LinkModel } {\n\t\treturn this.links;\n\t}\n\n\tpublic createLinkModel(): LinkModel | null {\n\t\tif (_isFinite(this.options.maximumLinks)) {\n\t\t\tvar numberOfLinks: number = _size(this.links);\n\t\t\tif (this.options.maximumLinks === 1 && numberOfLinks >= 1) {\n\t\t\t\treturn _values(this.links)[0];\n\t\t\t} else if (numberOfLinks >= this.options.maximumLinks) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\treportPosition() {\n\t\t_forEach(this.getLinks(), (link) => {\n\t\t\tlink.getPointForPort(this).setPosition(this.getCenter());\n\t\t});\n\t\tthis.fireEvent(\n\t\t\t{\n\t\t\t\tentity: this\n\t\t\t},\n\t\t\t'reportInitialPosition'\n\t\t);\n\t}\n\n\tgetCenter(): Point {\n\t\treturn new Point(this.getX() + this.width / 2, this.getY() + this.height / 2);\n\t}\n\n\tgetBoundingBox(): Rectangle {\n\t\treturn Rectangle.fromPointAndSize(this.position, this.width, this.height);\n\t}\n\n\tupdateCoords(coords: Rectangle) {\n\t\tthis.width = coords.getWidth();\n\t\tthis.height = coords.getHeight();\n\t\tthis.setPosition(coords.getTopLeft());\n\t\tthis.reportedPosition = true;\n\t\tthis.reportPosition();\n\t}\n\n\tcanLinkToPort(port: PortModel): boolean {\n\t\treturn true;\n\t}\n\n\tisLocked() {\n\t\treturn super.isLocked() || this.getParent().isLocked();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/entities/port/PortWidget.tsx",
    "content": "import * as React from 'react';\nimport _keys from 'lodash/keys';\nimport { PortModel } from './PortModel';\nimport { DiagramEngine } from '../../DiagramEngine';\nimport { ListenerHandle, Toolkit } from '@projectstorm/react-canvas-core';\n\nexport interface PortProps {\n\tport: PortModel;\n\tengine: DiagramEngine;\n\tclassName?;\n\tstyle?;\n}\n\nexport class PortWidget extends React.Component<React.PropsWithChildren<PortProps>> {\n\tref: React.RefObject<HTMLDivElement>;\n\tengineListenerHandle: ListenerHandle;\n\n\tconstructor(props: PortProps) {\n\t\tsuper(props);\n\t\tthis.ref = React.createRef();\n\t}\n\n\treport() {\n\t\tthis.props.port.updateCoords(this.props.engine.getPortCoords(this.props.port, this.ref.current));\n\t}\n\n\tcomponentWillUnmount(): void {\n\t\tthis.engineListenerHandle && this.engineListenerHandle.deregister();\n\t}\n\n\tcomponentDidUpdate(prevProps: Readonly<PortProps>, prevState, snapshot?: any): void {\n\t\tif (!this.props.port.reportedPosition) {\n\t\t\tthis.report();\n\t\t}\n\t}\n\n\tcomponentDidMount(): void {\n\t\tthis.engineListenerHandle = this.props.engine.registerListener({\n\t\t\tcanvasReady: () => {\n\t\t\t\tthis.report();\n\t\t\t}\n\t\t});\n\t\tif (this.props.engine.getCanvas()) {\n\t\t\tthis.report();\n\t\t}\n\t}\n\n\tgetExtraProps() {\n\t\tif (Toolkit.TESTING) {\n\t\t\tconst links = _keys(this.props.port.getNode().getPort(this.props.port.getName()).links).join(',');\n\t\t\treturn {\n\t\t\t\t'data-links': links\n\t\t\t};\n\t\t}\n\t\treturn {};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={this.props.style}\n\t\t\t\tref={this.ref}\n\t\t\t\tclassName={`port ${this.props.className || ''}`}\n\t\t\t\tdata-name={this.props.port.getName()}\n\t\t\t\tdata-nodeid={this.props.port.getNode().getID()}\n\t\t\t\t{...this.getExtraProps()}\n\t\t\t>\n\t\t\t\t{this.props.children}\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/index.ts",
    "content": "export * from './models/DiagramModel';\nexport * from './entities/label/LabelModel';\n\nexport * from './entities/link/LinkModel';\nexport * from './entities/link/PointModel';\nexport * from './entities/link/LinkWidget';\n\nexport * from './entities/link-layer/LinkLayerModel';\nexport * from './entities/link-layer/LinkLayerWidget';\nexport * from './entities/link-layer/LinkLayerFactory';\n\nexport * from './entities/node-layer/NodeLayerModel';\nexport * from './entities/node-layer/NodeLayerWidget';\nexport * from './entities/node-layer/NodeLayerFactory';\n\nexport * from './entities/node/NodeModel';\nexport * from './entities/node/NodeWidget';\nexport * from './entities/port/PortModel';\nexport * from './entities/port/PortWidget';\n\nexport * from './states/DefaultDiagramState';\nexport * from './states/DragDiagramItemsState';\nexport * from './states/DragNewLinkState';\n\nexport * from './DiagramEngine';\n"
  },
  {
    "path": "packages/react-diagrams-core/src/models/DiagramModel.ts",
    "content": "import _filter from 'lodash/filter';\nimport _flatMap from 'lodash/flatMap';\nimport _forEach from 'lodash/forEach';\nimport _some from 'lodash/some';\nimport _values from 'lodash/values';\nimport { LinkModel } from '../entities/link/LinkModel';\nimport { NodeModel } from '../entities/node/NodeModel';\nimport {\n\tBaseEntityEvent,\n\tBaseEntityListener,\n\tBaseModel,\n\tCanvasModel,\n\tCanvasModelGenerics,\n\tLayerModel,\n\tDeserializeEvent\n} from '@projectstorm/react-canvas-core';\nimport { NodeLayerModel } from '../entities/node-layer/NodeLayerModel';\nimport { LinkLayerModel } from '../entities/link-layer/LinkLayerModel';\n\nexport interface DiagramListener extends BaseEntityListener {\n\tnodesUpdated?(event: BaseEntityEvent & { node: NodeModel; isCreated: boolean }): void;\n\n\tlinksUpdated?(event: BaseEntityEvent & { link: LinkModel; isCreated: boolean }): void;\n}\n\nexport interface DiagramModelGenerics extends CanvasModelGenerics {\n\tLISTENER: DiagramListener;\n}\n\nexport class DiagramModel<G extends DiagramModelGenerics = DiagramModelGenerics> extends CanvasModel<G> {\n\tprotected activeNodeLayer: NodeLayerModel;\n\tprotected activeLinkLayer: LinkLayerModel;\n\n\tconstructor(options: G['OPTIONS'] = {}) {\n\t\tsuper(options);\n\t\tthis.addLayer(new LinkLayerModel());\n\t\tthis.addLayer(new NodeLayerModel());\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tthis.layers = [];\n\t\tsuper.deserialize(event);\n\t}\n\n\taddLayer(layer: LayerModel): void {\n\t\tsuper.addLayer(layer);\n\t\tif (layer instanceof NodeLayerModel) {\n\t\t\tthis.activeNodeLayer = layer;\n\t\t}\n\t\tif (layer instanceof LinkLayerModel) {\n\t\t\tthis.activeLinkLayer = layer;\n\t\t}\n\t}\n\n\tgetLinkLayers(): LinkLayerModel[] {\n\t\treturn _filter(this.layers, (layer) => {\n\t\t\treturn layer instanceof LinkLayerModel;\n\t\t}) as LinkLayerModel[];\n\t}\n\n\tgetNodeLayers(): NodeLayerModel[] {\n\t\treturn _filter(this.layers, (layer) => {\n\t\t\treturn layer instanceof NodeLayerModel;\n\t\t}) as NodeLayerModel[];\n\t}\n\n\tgetActiveNodeLayer(): NodeLayerModel {\n\t\tif (!this.activeNodeLayer) {\n\t\t\tconst layers = this.getNodeLayers();\n\t\t\tif (layers.length === 0) {\n\t\t\t\tthis.addLayer(new NodeLayerModel());\n\t\t\t} else {\n\t\t\t\tthis.activeNodeLayer = layers[0];\n\t\t\t}\n\t\t}\n\t\treturn this.activeNodeLayer;\n\t}\n\n\tgetActiveLinkLayer(): LinkLayerModel {\n\t\tif (!this.activeLinkLayer) {\n\t\t\tconst layers = this.getLinkLayers();\n\t\t\tif (layers.length === 0) {\n\t\t\t\tthis.addLayer(new LinkLayerModel());\n\t\t\t} else {\n\t\t\t\tthis.activeLinkLayer = layers[0];\n\t\t\t}\n\t\t}\n\t\treturn this.activeLinkLayer;\n\t}\n\n\tgetNode(node: string): NodeModel {\n\t\tfor (const layer of this.getNodeLayers()) {\n\t\t\tconst model = layer.getModel(node);\n\t\t\tif (model) {\n\t\t\t\treturn model;\n\t\t\t}\n\t\t}\n\t}\n\n\tgetLink(link: string): LinkModel {\n\t\tfor (const layer of this.getLinkLayers()) {\n\t\t\tconst model = layer.getModel(link);\n\t\t\tif (model) {\n\t\t\t\treturn model;\n\t\t\t}\n\t\t}\n\t}\n\n\taddAll(...models: BaseModel[]): BaseModel[] {\n\t\t_forEach(models, (model) => {\n\t\t\tif (model instanceof LinkModel) {\n\t\t\t\tthis.addLink(model);\n\t\t\t} else if (model instanceof NodeModel) {\n\t\t\t\tthis.addNode(model);\n\t\t\t}\n\t\t});\n\t\treturn models;\n\t}\n\n\taddLink(link: LinkModel): LinkModel {\n\t\tthis.getActiveLinkLayer().addModel(link);\n\t\tthis.fireEvent(\n\t\t\t{\n\t\t\t\tlink,\n\t\t\t\tisCreated: true\n\t\t\t},\n\t\t\t'linksUpdated'\n\t\t);\n\t\treturn link;\n\t}\n\n\taddNode(node: NodeModel): NodeModel {\n\t\tthis.getActiveNodeLayer().addModel(node);\n\t\tthis.fireEvent({ node, isCreated: true }, 'nodesUpdated');\n\t\treturn node;\n\t}\n\n\tremoveLink(link: LinkModel) {\n\t\tconst removed = _some(this.getLinkLayers(), (layer) => {\n\t\t\treturn layer.removeModel(link);\n\t\t});\n\t\tif (removed) {\n\t\t\tthis.fireEvent({ link, isCreated: false }, 'linksUpdated');\n\t\t}\n\t}\n\n\tremoveNode(node: NodeModel) {\n\t\tconst removed = _some(this.getNodeLayers(), (layer) => {\n\t\t\treturn layer.removeModel(node);\n\t\t});\n\t\tif (removed) {\n\t\t\tthis.fireEvent({ node, isCreated: false }, 'nodesUpdated');\n\t\t}\n\t}\n\n\tgetLinks(): LinkModel[] {\n\t\treturn _flatMap(this.getLinkLayers(), (layer) => {\n\t\t\treturn _values(layer.getModels());\n\t\t});\n\t}\n\n\tgetNodes(): NodeModel[] {\n\t\treturn _flatMap(this.getNodeLayers(), (layer) => {\n\t\t\treturn _values(layer.getModels());\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/states/DefaultDiagramState.ts",
    "content": "import { MouseEvent, TouchEvent } from 'react';\nimport {\n\tSelectingState,\n\tState,\n\tAction,\n\tInputType,\n\tActionEvent,\n\tDragCanvasState\n} from '@projectstorm/react-canvas-core';\nimport { PortModel } from '../entities/port/PortModel';\nimport { DragNewLinkState } from './DragNewLinkState';\nimport { DiagramEngine } from '../DiagramEngine';\nimport { DragDiagramItemsState } from './DragDiagramItemsState';\n\nexport class DefaultDiagramState extends State<DiagramEngine> {\n\tdragCanvas: DragCanvasState;\n\tdragNewLink: DragNewLinkState;\n\tdragItems: DragDiagramItemsState;\n\n\tconstructor() {\n\t\tsuper({\n\t\t\tname: 'default-diagrams'\n\t\t});\n\t\tthis.childStates = [new SelectingState()];\n\t\tthis.dragCanvas = new DragCanvasState();\n\t\tthis.dragNewLink = new DragNewLinkState();\n\t\tthis.dragItems = new DragDiagramItemsState();\n\n\t\t// determine what was clicked on\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst element = this.engine.getActionEventBus().getModelForEvent(event);\n\n\t\t\t\t\t// the canvas was clicked on, transition to the dragging canvas state\n\t\t\t\t\tif (!element) {\n\t\t\t\t\t\tthis.transitionWithEvent(this.dragCanvas, event);\n\t\t\t\t\t}\n\t\t\t\t\t// initiate dragging a new link\n\t\t\t\t\telse if (element instanceof PortModel) {\n\t\t\t\t\t\tthis.transitionWithEvent(this.dragNewLink, event);\n\t\t\t\t\t}\n\t\t\t\t\t// move the items (and potentially link points)\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.transitionWithEvent(this.dragItems, event);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\t// touch drags the canvas\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.TOUCH_START,\n\t\t\t\tfire: (event: ActionEvent<TouchEvent>) => {\n\t\t\t\t\tthis.transitionWithEvent(this.dragCanvas, event);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/states/DragDiagramItemsState.ts",
    "content": "import { Action, ActionEvent, InputType, MoveItemsState } from '@projectstorm/react-canvas-core';\nimport _forEach from 'lodash/forEach';\nimport { PointModel } from '../entities/link/PointModel';\nimport { DiagramEngine } from '../DiagramEngine';\nimport { PortModel } from '../entities/port/PortModel';\nimport { MouseEvent } from 'react';\nimport { LinkModel } from '../entities/link/LinkModel';\n\nexport class DragDiagramItemsState<E extends DiagramEngine = DiagramEngine> extends MoveItemsState<E> {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_UP,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst item = this.engine.getMouseElement(event.event);\n\t\t\t\t\tif (item instanceof PortModel) {\n\t\t\t\t\t\t_forEach(this.initialPositions, (position) => {\n\t\t\t\t\t\t\tif (position.item instanceof PointModel) {\n\t\t\t\t\t\t\t\tconst link = position.item.getParent() as LinkModel;\n\n\t\t\t\t\t\t\t\t// only care about the last links\n\t\t\t\t\t\t\t\tif (link.getLastPoint() !== position.item) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (link.getSourcePort().canLinkToPort(item)) {\n\t\t\t\t\t\t\t\t\tlink.setTargetPort(item);\n\t\t\t\t\t\t\t\t\titem.reportPosition();\n\t\t\t\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/src/states/DragNewLinkState.ts",
    "content": "import {\n\tAbstractDisplacementState,\n\tAbstractDisplacementStateEvent,\n\tAction,\n\tActionEvent,\n\tInputType\n} from '@projectstorm/react-canvas-core';\nimport { PortModel } from '../entities/port/PortModel';\nimport { MouseEvent } from 'react';\nimport { LinkModel } from '../entities/link/LinkModel';\nimport { DiagramEngine } from '../DiagramEngine';\n\nexport interface DragNewLinkStateOptions {\n\t/**\n\t * If enabled, the links will stay on the canvas if they dont connect to a port\n\t * when dragging finishes\n\t */\n\tallowLooseLinks?: boolean;\n\t/**\n\t * If enabled, then a link can still be drawn from the port even if it is locked\n\t */\n\tallowLinksFromLockedPorts?: boolean;\n}\n\nexport class DragNewLinkState<E extends DiagramEngine = DiagramEngine> extends AbstractDisplacementState<E> {\n\tport: PortModel;\n\tlink: LinkModel;\n\tconfig: DragNewLinkStateOptions;\n\n\tconstructor(options: DragNewLinkStateOptions = {}) {\n\t\tsuper({ name: 'drag-new-link' });\n\n\t\tthis.config = {\n\t\t\tallowLooseLinks: true,\n\t\t\tallowLinksFromLockedPorts: false,\n\t\t\t...options\n\t\t};\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_DOWN,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent, PortModel>) => {\n\t\t\t\t\tthis.port = this.engine.getMouseElement(event.event) as PortModel;\n\t\t\t\t\tif (!this.config.allowLinksFromLockedPorts && this.port.isLocked()) {\n\t\t\t\t\t\tthis.eject();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.link = this.port.createLinkModel();\n\n\t\t\t\t\t// if no link is given, just eject the state\n\t\t\t\t\tif (!this.link) {\n\t\t\t\t\t\tthis.eject();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.link.setSelected(true);\n\t\t\t\t\tthis.link.setSourcePort(this.port);\n\t\t\t\t\tthis.engine.getModel().addLink(this.link);\n\t\t\t\t\tthis.port.reportPosition();\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tthis.registerAction(\n\t\t\tnew Action({\n\t\t\t\ttype: InputType.MOUSE_UP,\n\t\t\t\tfire: (event: ActionEvent<MouseEvent>) => {\n\t\t\t\t\tconst model = this.engine.getMouseElement(event.event);\n\t\t\t\t\t// check to see if we connected to a new port\n\t\t\t\t\tif (model instanceof PortModel) {\n\t\t\t\t\t\tif (this.port.canLinkToPort(model)) {\n\t\t\t\t\t\t\tthis.link.setTargetPort(model);\n\t\t\t\t\t\t\tmodel.reportPosition();\n\t\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.link.remove();\n\t\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!this.config.allowLooseLinks) {\n\t\t\t\t\t\tthis.link.remove();\n\t\t\t\t\t\tthis.engine.repaintCanvas();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Calculates the link's far-end point position on mouse move.\n\t * In order to be as precise as possible the mouse initialXRelative & initialYRelative are taken into account as well\n\t * as the possible engine offset\n\t */\n\tfireMouseMoved(event: AbstractDisplacementStateEvent): any {\n\t\tconst portPos = this.port.getPosition();\n\t\tconst zoomLevelPercentage = this.engine.getModel().getZoomLevel() / 100;\n\t\tconst engineOffsetX = this.engine.getModel().getOffsetX() / zoomLevelPercentage;\n\t\tconst engineOffsetY = this.engine.getModel().getOffsetY() / zoomLevelPercentage;\n\t\tconst initialXRelative = this.initialXRelative / zoomLevelPercentage;\n\t\tconst initialYRelative = this.initialYRelative / zoomLevelPercentage;\n\t\tconst linkNextX = portPos.x - engineOffsetX + (initialXRelative - portPos.x) + event.virtualDisplacementX;\n\t\tconst linkNextY = portPos.y - engineOffsetY + (initialYRelative - portPos.y) + event.virtualDisplacementY;\n\n\t\tthis.link.getLastPoint().setPosition(linkNextX, linkNextY);\n\t\tthis.engine.repaintCanvas();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.base.json\",\n\t\"compilerOptions\": {\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"declarationDir\": \"dist/@types\",\n\t\t\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"\n\t},\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"../react-canvas-core\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"../geometry\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "packages/react-diagrams-core/webpack.config.js",
    "content": "const config = require('../../webpack.shared')(__dirname);\nmodule.exports = {\n\t...config,\n\toutput: {\n\t\t...config.output,\n\t\tlibrary: 'projectstorm/react-canvas-core'\n\t}\n};\n"
  },
  {
    "path": "packages/react-diagrams-defaults/.npmignore",
    "content": "*\n!dist/**/*\n!package.json\ndist/tsconfig.tsbuildinfo\n"
  },
  {
    "path": "packages/react-diagrams-defaults/CHANGELOG.md",
    "content": "# @projectstorm/react-diagrams-defaults\n\n## 7.1.3\n\n### Patch Changes\n\n- 20766f5: fix default link widget with react strict mode\n- 80285fe: refactor: update lodash imports to use individual functions\n- Updated dependencies [09ed60f]\n- Updated dependencies [80285fe]\n  - @projectstorm/react-canvas-core@7.0.3\n  - @projectstorm/react-diagrams-core@7.0.3\n  - @projectstorm/geometry@7.0.3\n\n## 7.1.2\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n- Updated dependencies [66c687a]\n  - @projectstorm/react-diagrams-core@7.0.2\n  - @projectstorm/react-canvas-core@7.0.2\n  - @projectstorm/geometry@7.0.2\n\n## 7.1.1\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/geometry@7.0.1\n  - @projectstorm/react-canvas-core@7.0.1\n  - @projectstorm/react-diagrams-core@7.0.1\n\n## 7.1.0\n\n### Minor Changes\n\n- e0d21f1: - [feature] new ability to refresh links in auto distribute system [PR 756](https://github.com/projectstorm/react-diagrams/pull/756)\n\n  - [fix] Default link now uses the correct method for creating a point allowing this to be overridden [PR 939](https://github.com/projectstorm/react-diagrams/pull/939)\n\n  Big thanks to @ToTheHit and @h0111in for your help on these, even though its very delayed on my part :)\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/react-diagrams-core@7.0.0\n  - @projectstorm/react-canvas-core@7.0.0\n  - @projectstorm/geometry@7.0.0\n"
  },
  {
    "path": "packages/react-diagrams-defaults/README.md",
    "content": "# Project STORM > React Diagrams > Defaults\n\nThis workspace houses the default models\n"
  },
  {
    "path": "packages/react-diagrams-defaults/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-diagrams-defaults\",\n\t\"version\": \"7.1.3\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"rimraf ./dist\",\n\t\t\"build\": \"../../node_modules/.bin/webpack\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.umd.js\",\n\t\"module\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"@emotion/react\": \"^11.14.0\",\n\t\t\"@emotion/styled\": \"^11.*\",\n\t\t\"@projectstorm/geometry\": \"workspace:*\",\n\t\t\"@projectstorm/react-canvas-core\": \"workspace:*\",\n\t\t\"@projectstorm/react-diagrams-core\": \"workspace:*\",\n\t\t\"lodash\": \"^4.17.21\",\n\t\t\"react\": \"^19.0.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/lodash\": \"^4.14.200\",\n\t\t\"@types/react\": \"^19.0.12\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/index.ts",
    "content": "export * from './label/DefaultLabelFactory';\nexport * from './label/DefaultLabelModel';\nexport * from './label/DefaultLabelWidget';\n\nexport * from './link/DefaultLinkFactory';\nexport * from './link/DefaultLinkModel';\nexport * from './link/DefaultLinkWidget';\nexport * from './link/DefaultLinkSegmentWidget';\nexport * from './link/DefaultLinkPointWidget';\n\nexport * from './node/DefaultNodeFactory';\nexport * from './node/DefaultNodeModel';\nexport * from './node/DefaultNodeWidget';\n\nexport * from './port/DefaultPortFactory';\nexport * from './port/DefaultPortLabelWidget';\nexport * from './port/DefaultPortModel';\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/label/DefaultLabelFactory.tsx",
    "content": "import * as React from 'react';\nimport { DefaultLabelModel } from './DefaultLabelModel';\nimport { DefaultLabelWidget } from './DefaultLabelWidget';\nimport { AbstractReactFactory } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { JSX } from 'react';\n\n/**\n * @author Dylan Vorster\n */\nexport class DefaultLabelFactory extends AbstractReactFactory<DefaultLabelModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('default');\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <DefaultLabelWidget model={event.model} />;\n\t}\n\n\tgenerateModel(event): DefaultLabelModel {\n\t\treturn new DefaultLabelModel();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/label/DefaultLabelModel.tsx",
    "content": "import { LabelModel, LabelModelGenerics, LabelModelOptions } from '@projectstorm/react-diagrams-core';\nimport { DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport interface DefaultLabelModelOptions extends LabelModelOptions {\n\tlabel?: string;\n}\n\nexport interface DefaultLabelModelGenerics extends LabelModelGenerics {\n\tOPTIONS: DefaultLabelModelOptions;\n}\n\nexport class DefaultLabelModel extends LabelModel<DefaultLabelModelGenerics> {\n\tconstructor(options: DefaultLabelModelOptions = {}) {\n\t\tsuper({\n\t\t\toffsetY: options.offsetY == null ? -23 : options.offsetY,\n\t\t\ttype: 'default',\n\t\t\t...options\n\t\t});\n\t}\n\n\tsetLabel(label: string) {\n\t\tthis.options.label = label;\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.label = event.data.label;\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tlabel: this.options.label\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/label/DefaultLabelWidget.tsx",
    "content": "import * as React from 'react';\nimport { DefaultLabelModel } from './DefaultLabelModel';\nimport styled from '@emotion/styled';\n\nexport interface DefaultLabelWidgetProps {\n\tmodel: DefaultLabelModel;\n}\n\nnamespace S {\n\texport const Label = styled.div`\n\t\tbackground: rgba(0, 0, 0, 0.8);\n\t\tborder-radius: 5px;\n\t\tcolor: white;\n\t\tfont-size: 12px;\n\t\tpadding: 4px 8px;\n\t\tfont-family: sans-serif;\n\t\tuser-select: none;\n\t`;\n}\n\nexport class DefaultLabelWidget extends React.Component<DefaultLabelWidgetProps> {\n\trender() {\n\t\treturn <S.Label>{this.props.model.getOptions().label}</S.Label>;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/link/DefaultLinkFactory.tsx",
    "content": "import * as React from 'react';\nimport { DefaultLinkModel } from './DefaultLinkModel';\nimport { DefaultLinkWidget } from './DefaultLinkWidget';\nimport styled from '@emotion/styled';\nimport { AbstractReactFactory } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { css, keyframes } from '@emotion/react';\nimport { JSX } from 'react';\n\nnamespace S {\n\texport const Keyframes = keyframes`\n\t\tfrom {\n\t\t\tstroke-dashoffset: 24;\n\t\t}\n\t\tto {\n\t\t\tstroke-dashoffset: 0;\n\t\t}\n\t`;\n\n\tconst selected = css`\n\t\tstroke-dasharray: 10, 2;\n\t\tanimation: ${Keyframes} 1s linear infinite;\n\t`;\n\n\texport const Path = styled.path<{ selected: boolean }>`\n\t\t${(p) => p.selected && selected};\n\t\tfill: none;\n\t\tpointer-events: auto;\n\t`;\n}\n\nexport class DefaultLinkFactory<Link extends DefaultLinkModel = DefaultLinkModel> extends AbstractReactFactory<\n\tLink,\n\tDiagramEngine\n> {\n\tconstructor(type = 'default') {\n\t\tsuper(type);\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <DefaultLinkWidget link={event.model} diagramEngine={this.engine} />;\n\t}\n\n\tgenerateModel(event): Link {\n\t\treturn new DefaultLinkModel() as Link;\n\t}\n\n\tgenerateLinkSegment(model: Link, selected: boolean, path: string) {\n\t\treturn (\n\t\t\t<S.Path\n\t\t\t\tselected={selected}\n\t\t\t\tstroke={selected ? model.getOptions().selectedColor : model.getOptions().color}\n\t\t\t\tstrokeWidth={model.getOptions().width}\n\t\t\t\td={path}\n\t\t\t/>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/link/DefaultLinkModel.ts",
    "content": "import {\n\tDiagramEngine,\n\tLabelModel,\n\tLinkModel,\n\tLinkModelGenerics,\n\tLinkModelListener,\n\tPortModel,\n\tPortModelAlignment\n} from '@projectstorm/react-diagrams-core';\nimport { DefaultLabelModel } from '../label/DefaultLabelModel';\nimport { BezierCurve } from '@projectstorm/geometry';\nimport { BaseEntityEvent, BaseModelOptions, DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport interface DefaultLinkModelListener extends LinkModelListener {\n\tcolorChanged?(event: BaseEntityEvent<DefaultLinkModel> & { color: null | string }): void;\n\n\twidthChanged?(event: BaseEntityEvent<DefaultLinkModel> & { width: 0 | number }): void;\n}\n\nexport interface DefaultLinkModelOptions extends BaseModelOptions {\n\twidth?: number;\n\tcolor?: string;\n\tselectedColor?: string;\n\tcurvyness?: number;\n\ttype?: string;\n\ttestName?: string;\n}\n\nexport interface DefaultLinkModelGenerics extends LinkModelGenerics {\n\tLISTENER: DefaultLinkModelListener;\n\tOPTIONS: DefaultLinkModelOptions;\n}\n\nexport class DefaultLinkModel extends LinkModel<DefaultLinkModelGenerics> {\n\tconstructor(options: DefaultLinkModelOptions = {}) {\n\t\tsuper({\n\t\t\ttype: 'default',\n\t\t\twidth: options.width || 3,\n\t\t\tcolor: options.color || 'gray',\n\t\t\tselectedColor: options.selectedColor || 'rgb(0,192,255)',\n\t\t\tcurvyness: 50,\n\t\t\t...options\n\t\t});\n\t}\n\n\tcalculateControlOffset(port: PortModel): [number, number] {\n\t\tif (port.getOptions().alignment === PortModelAlignment.RIGHT) {\n\t\t\treturn [this.options.curvyness, 0];\n\t\t} else if (port.getOptions().alignment === PortModelAlignment.LEFT) {\n\t\t\treturn [-this.options.curvyness, 0];\n\t\t} else if (port.getOptions().alignment === PortModelAlignment.TOP) {\n\t\t\treturn [0, -this.options.curvyness];\n\t\t}\n\t\treturn [0, this.options.curvyness];\n\t}\n\n\tgetSVGPath(): string {\n\t\tif (this.points.length == 2) {\n\t\t\tconst curve = new BezierCurve();\n\t\t\tcurve.setSource(this.getFirstPoint().getPosition());\n\t\t\tcurve.setTarget(this.getLastPoint().getPosition());\n\t\t\tcurve.setSourceControl(this.getFirstPoint().getPosition().clone());\n\t\t\tcurve.setTargetControl(this.getLastPoint().getPosition().clone());\n\n\t\t\tif (this.sourcePort) {\n\t\t\t\tcurve.getSourceControl().translate(...this.calculateControlOffset(this.getSourcePort()));\n\t\t\t}\n\n\t\t\tif (this.targetPort) {\n\t\t\t\tcurve.getTargetControl().translate(...this.calculateControlOffset(this.getTargetPort()));\n\t\t\t}\n\t\t\treturn curve.getSVGCurve();\n\t\t}\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\twidth: this.options.width,\n\t\t\tcolor: this.options.color,\n\t\t\tcurvyness: this.options.curvyness,\n\t\t\tselectedColor: this.options.selectedColor\n\t\t};\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.color = event.data.color;\n\t\tthis.options.width = event.data.width;\n\t\tthis.options.curvyness = event.data.curvyness;\n\t\tthis.options.selectedColor = event.data.selectedColor;\n\t}\n\n\taddLabel(label: LabelModel | string) {\n\t\tif (label instanceof LabelModel) {\n\t\t\treturn super.addLabel(label);\n\t\t}\n\t\tlet labelOb = new DefaultLabelModel();\n\t\tlabelOb.setLabel(label);\n\t\treturn super.addLabel(labelOb);\n\t}\n\n\tsetWidth(width: number) {\n\t\tthis.options.width = width;\n\t\tthis.fireEvent({ width }, 'widthChanged');\n\t}\n\n\tsetColor(color: string) {\n\t\tthis.options.color = color;\n\t\tthis.fireEvent({ color }, 'colorChanged');\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/link/DefaultLinkPointWidget.tsx",
    "content": "import * as React from 'react';\nimport { PointModel } from '@projectstorm/react-diagrams-core';\nimport styled from '@emotion/styled';\n\nexport interface DefaultLinkPointWidgetProps {\n\tpoint: PointModel;\n\tcolor?: string;\n\tcolorSelected: string;\n}\n\nexport interface DefaultLinkPointWidgetState {\n\tselected: boolean;\n}\n\nnamespace S {\n\texport const PointTop = styled.circle`\n\t\tpointer-events: all;\n\t`;\n}\n\nexport class DefaultLinkPointWidget extends React.Component<DefaultLinkPointWidgetProps, DefaultLinkPointWidgetState> {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\tselected: false\n\t\t};\n\t}\n\n\trender() {\n\t\tconst { point } = this.props;\n\t\treturn (\n\t\t\t<g>\n\t\t\t\t<circle\n\t\t\t\t\tcx={point.getPosition().x}\n\t\t\t\t\tcy={point.getPosition().y}\n\t\t\t\t\tr={5}\n\t\t\t\t\tfill={this.state.selected || this.props.point.isSelected() ? this.props.colorSelected : this.props.color}\n\t\t\t\t/>\n\t\t\t\t<S.PointTop\n\t\t\t\t\tclassName=\"point\"\n\t\t\t\t\tonMouseLeave={() => {\n\t\t\t\t\t\tthis.setState({ selected: false });\n\t\t\t\t\t}}\n\t\t\t\t\tonMouseEnter={() => {\n\t\t\t\t\t\tthis.setState({ selected: true });\n\t\t\t\t\t}}\n\t\t\t\t\tdata-id={point.getID()}\n\t\t\t\t\tdata-linkid={point.getLink().getID()}\n\t\t\t\t\tcx={point.getPosition().x}\n\t\t\t\t\tcy={point.getPosition().y}\n\t\t\t\t\tr={15}\n\t\t\t\t\topacity={0.0}\n\t\t\t\t/>\n\t\t\t</g>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/link/DefaultLinkSegmentWidget.tsx",
    "content": "import * as React from 'react';\nimport { DefaultLinkFactory } from './DefaultLinkFactory';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { DefaultLinkModel } from './DefaultLinkModel';\n\nexport interface DefaultLinkSegmentWidgetProps {\n\tpath: string;\n\tlink: DefaultLinkModel;\n\tselected: boolean;\n\tforwardRef: React.RefObject<SVGPathElement | null>;\n\tfactory: DefaultLinkFactory;\n\tdiagramEngine: DiagramEngine;\n\tonSelection: (selected: boolean) => any;\n\textras: object;\n}\n\nexport class DefaultLinkSegmentWidget extends React.Component<DefaultLinkSegmentWidgetProps> {\n\trender() {\n\t\tconst Bottom = React.cloneElement(\n\t\t\tthis.props.factory.generateLinkSegment(\n\t\t\t\tthis.props.link,\n\t\t\t\tthis.props.selected || this.props.link.isSelected(),\n\t\t\t\tthis.props.path\n\t\t\t),\n\t\t\t{\n\t\t\t\tref: this.props.forwardRef\n\t\t\t}\n\t\t);\n\n\t\tconst Top = React.cloneElement(Bottom, {\n\t\t\tstrokeLinecap: 'round',\n\t\t\tonMouseLeave: () => {\n\t\t\t\tthis.props.onSelection(false);\n\t\t\t},\n\t\t\tonMouseEnter: () => {\n\t\t\t\tthis.props.onSelection(true);\n\t\t\t},\n\t\t\t...this.props.extras,\n\t\t\tref: null,\n\t\t\t'data-linkid': this.props.link.getID(),\n\t\t\tstrokeOpacity: this.props.selected ? 0.1 : 0,\n\t\t\tstrokeWidth: 20,\n\t\t\tfill: 'none',\n\t\t\tonContextMenu: () => {\n\t\t\t\tif (!this.props.link.isLocked()) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.props.link.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn (\n\t\t\t<g>\n\t\t\t\t{Bottom}\n\t\t\t\t{Top}\n\t\t\t</g>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/link/DefaultLinkWidget.tsx",
    "content": "import { DiagramEngine, LinkWidget, PointModel } from '@projectstorm/react-diagrams-core';\nimport * as React from 'react';\nimport { JSX, MouseEvent, useEffect, useRef } from 'react';\nimport { DefaultLinkModel } from './DefaultLinkModel';\nimport { DefaultLinkPointWidget } from './DefaultLinkPointWidget';\nimport { DefaultLinkSegmentWidget } from './DefaultLinkSegmentWidget';\n\nexport interface DefaultLinkProps {\n\tlink: DefaultLinkModel;\n\tdiagramEngine: DiagramEngine;\n\tpointAdded?: (point: PointModel, event: MouseEvent) => any;\n\trenderPoints?: boolean;\n\tselected?: (event: MouseEvent) => any;\n}\n\nexport const DefaultLinkWidget: React.FC<DefaultLinkProps> = (props) => {\n\tconst [selected, setSelected] = React.useState(false);\n\tconst refPaths = useRef<React.RefObject<SVGPathElement>[]>([]);\n\n\tconst renderPoints = () => {\n\t\treturn props.renderPoints ?? true;\n\t};\n\n\tuseEffect(() => {\n\t\tprops.link.setRenderedPaths(refPaths.current.map((ref) => ref.current).filter(Boolean) as SVGPathElement[]);\n\t\treturn () => {\n\t\t\tprops.link.setRenderedPaths([]);\n\t\t};\n\t}, [props.link]);\n\n\tconst generateRef = () => {\n\t\tconst ref = React.createRef<SVGPathElement>();\n\t\trefPaths.current.push(ref);\n\t\treturn ref;\n\t};\n\n\tconst addPointToLink = (event: MouseEvent, index: number) => {\n\t\tif (\n\t\t\t!event.shiftKey &&\n\t\t\t!props.link.isLocked() &&\n\t\t\tprops.link.getPoints().length - 1 <= props.diagramEngine.getMaxNumberPointsPerLink()\n\t\t) {\n\t\t\tconst position = props.diagramEngine.getRelativeMousePoint(event);\n\t\t\tconst point = props.link.point(position.x, position.y, index);\n\t\t\tevent.persist();\n\t\t\tevent.stopPropagation();\n\t\t\tprops.diagramEngine.getActionEventBus().fireAction({\n\t\t\t\tevent,\n\t\t\t\tmodel: point\n\t\t\t});\n\t\t}\n\t};\n\n\tconst generatePoint = (point: PointModel): JSX.Element => {\n\t\treturn (\n\t\t\t<DefaultLinkPointWidget\n\t\t\t\tkey={point.getID()}\n\t\t\t\tpoint={point as any}\n\t\t\t\tcolorSelected={props.link.getOptions().selectedColor ?? ''}\n\t\t\t\tcolor={props.link.getOptions().color}\n\t\t\t/>\n\t\t);\n\t};\n\n\tconst generateLink = (path: string, extraProps: any, id: string | number): JSX.Element => {\n\t\treturn (\n\t\t\t<DefaultLinkSegmentWidget\n\t\t\t\tkey={`link-${id}`}\n\t\t\t\tpath={path}\n\t\t\t\tselected={selected}\n\t\t\t\tdiagramEngine={props.diagramEngine}\n\t\t\t\tfactory={props.diagramEngine.getFactoryForLink(props.link)}\n\t\t\t\tlink={props.link}\n\t\t\t\tforwardRef={generateRef()}\n\t\t\t\tonSelection={setSelected}\n\t\t\t\textras={extraProps}\n\t\t\t/>\n\t\t);\n\t};\n\n\tconst points = props.link.getPoints();\n\tconst paths = [];\n\trefPaths.current = []; // Reset the refPaths for the current render\n\n\tif (points.length === 2) {\n\t\tpaths.push(\n\t\t\tgenerateLink(\n\t\t\t\tprops.link.getSVGPath(),\n\t\t\t\t{\n\t\t\t\t\tonMouseDown: (event: MouseEvent) => {\n\t\t\t\t\t\tprops.selected?.(event);\n\t\t\t\t\t\taddPointToLink(event, 1);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t'0'\n\t\t\t)\n\t\t);\n\n\t\tif (props.link.getTargetPort() == null) {\n\t\t\tpaths.push(generatePoint(points[1]));\n\t\t}\n\t} else {\n\t\tfor (let j = 0; j < points.length - 1; j++) {\n\t\t\tpaths.push(\n\t\t\t\tgenerateLink(\n\t\t\t\t\tLinkWidget.generateLinePath(points[j], points[j + 1]),\n\t\t\t\t\t{\n\t\t\t\t\t\t'data-linkid': props.link.getID(),\n\t\t\t\t\t\t'data-point': j,\n\t\t\t\t\t\tonMouseDown: (event: MouseEvent) => {\n\t\t\t\t\t\t\tprops.selected?.(event);\n\t\t\t\t\t\t\taddPointToLink(event, j + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tj\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\tif (renderPoints()) {\n\t\t\tfor (let i = 1; i < points.length - 1; i++) {\n\t\t\t\tpaths.push(generatePoint(points[i]));\n\t\t\t}\n\n\t\t\tif (props.link.getTargetPort() == null) {\n\t\t\t\tpaths.push(generatePoint(points[points.length - 1]));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn <g data-default-link-test={props.link.getOptions().testName}>{paths}</g>;\n};\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/node/DefaultNodeFactory.tsx",
    "content": "import * as React from 'react';\nimport { DefaultNodeModel } from './DefaultNodeModel';\nimport { DefaultNodeWidget } from './DefaultNodeWidget';\nimport { AbstractReactFactory } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { JSX } from 'react';\n\nexport class DefaultNodeFactory extends AbstractReactFactory<DefaultNodeModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('default');\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <DefaultNodeWidget engine={this.engine} node={event.model} />;\n\t}\n\n\tgenerateModel(event): DefaultNodeModel {\n\t\treturn new DefaultNodeModel();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/node/DefaultNodeModel.ts",
    "content": "import _map from 'lodash/map';\nimport { NodeModel, NodeModelGenerics, PortModelAlignment } from '@projectstorm/react-diagrams-core';\nimport { DefaultPortModel } from '../port/DefaultPortModel';\nimport { BasePositionModelOptions, DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport interface DefaultNodeModelOptions extends BasePositionModelOptions {\n\tname?: string;\n\tcolor?: string;\n}\n\nexport interface DefaultNodeModelGenerics extends NodeModelGenerics {\n\tOPTIONS: DefaultNodeModelOptions;\n}\n\nexport class DefaultNodeModel extends NodeModel<DefaultNodeModelGenerics> {\n\tprotected portsIn: DefaultPortModel[];\n\tprotected portsOut: DefaultPortModel[];\n\n\tconstructor(name: string, color: string);\n\tconstructor(options?: DefaultNodeModelOptions);\n\tconstructor(options: any = {}, color?: string) {\n\t\tif (typeof options === 'string') {\n\t\t\toptions = {\n\t\t\t\tname: options,\n\t\t\t\tcolor: color\n\t\t\t};\n\t\t}\n\t\tsuper({\n\t\t\ttype: 'default',\n\t\t\tname: 'Untitled',\n\t\t\tcolor: 'rgb(0,192,255)',\n\t\t\t...options\n\t\t});\n\t\tthis.portsOut = [];\n\t\tthis.portsIn = [];\n\t}\n\n\tdoClone(lookupTable: {}, clone: any): void {\n\t\tclone.portsIn = [];\n\t\tclone.portsOut = [];\n\t\tsuper.doClone(lookupTable, clone);\n\t}\n\n\tremovePort(port: DefaultPortModel): void {\n\t\tsuper.removePort(port);\n\t\tif (port.getOptions().in) {\n\t\t\tthis.portsIn.splice(this.portsIn.indexOf(port), 1);\n\t\t} else {\n\t\t\tthis.portsOut.splice(this.portsOut.indexOf(port), 1);\n\t\t}\n\t}\n\n\taddPort<T extends DefaultPortModel>(port: T): T {\n\t\tsuper.addPort(port);\n\t\tif (port.getOptions().in) {\n\t\t\tif (this.portsIn.indexOf(port) === -1) {\n\t\t\t\tthis.portsIn.push(port);\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.portsOut.indexOf(port) === -1) {\n\t\t\t\tthis.portsOut.push(port);\n\t\t\t}\n\t\t}\n\t\treturn port;\n\t}\n\n\taddInPort(label: string, after = true): DefaultPortModel {\n\t\tconst p = new DefaultPortModel({\n\t\t\tin: true,\n\t\t\tname: label,\n\t\t\tlabel: label,\n\t\t\talignment: PortModelAlignment.LEFT\n\t\t});\n\t\tif (!after) {\n\t\t\tthis.portsIn.splice(0, 0, p);\n\t\t}\n\t\treturn this.addPort(p);\n\t}\n\n\taddOutPort(label: string, after = true): DefaultPortModel {\n\t\tconst p = new DefaultPortModel({\n\t\t\tin: false,\n\t\t\tname: label,\n\t\t\tlabel: label,\n\t\t\talignment: PortModelAlignment.RIGHT\n\t\t});\n\t\tif (!after) {\n\t\t\tthis.portsOut.splice(0, 0, p);\n\t\t}\n\t\treturn this.addPort(p);\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.name = event.data.name;\n\t\tthis.options.color = event.data.color;\n\t\tthis.portsIn = _map(event.data.portsInOrder, (id) => {\n\t\t\treturn this.getPortFromID(id);\n\t\t}) as DefaultPortModel[];\n\t\tthis.portsOut = _map(event.data.portsOutOrder, (id) => {\n\t\t\treturn this.getPortFromID(id);\n\t\t}) as DefaultPortModel[];\n\t}\n\n\tserialize(): any {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tname: this.options.name,\n\t\t\tcolor: this.options.color,\n\t\t\tportsInOrder: _map(this.portsIn, (port) => {\n\t\t\t\treturn port.getID();\n\t\t\t}),\n\t\t\tportsOutOrder: _map(this.portsOut, (port) => {\n\t\t\t\treturn port.getID();\n\t\t\t})\n\t\t};\n\t}\n\n\tgetInPorts(): DefaultPortModel[] {\n\t\treturn this.portsIn;\n\t}\n\n\tgetOutPorts(): DefaultPortModel[] {\n\t\treturn this.portsOut;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/node/DefaultNodeWidget.tsx",
    "content": "import * as React from 'react';\nimport _map from 'lodash/map';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { DefaultNodeModel } from './DefaultNodeModel';\nimport { DefaultPortLabel } from '../port/DefaultPortLabelWidget';\nimport styled from '@emotion/styled';\n\nnamespace S {\n\texport const Node = styled.div<{ background: string; selected: boolean }>`\n\t\tbackground-color: ${(p) => p.background};\n\t\tborder-radius: 5px;\n\t\tfont-family: sans-serif;\n\t\tcolor: white;\n\t\tborder: solid 2px black;\n\t\toverflow: visible;\n\t\tfont-size: 11px;\n\t\tborder: solid 2px ${(p) => (p.selected ? 'rgb(0,192,255)' : 'black')};\n\t`;\n\n\texport const Title = styled.div`\n\t\tbackground: rgba(0, 0, 0, 0.3);\n\t\tdisplay: flex;\n\t\twhite-space: nowrap;\n\t\tjustify-items: center;\n\t`;\n\n\texport const TitleName = styled.div`\n\t\tflex-grow: 1;\n\t\tpadding: 5px 5px;\n\t`;\n\n\texport const Ports = styled.div`\n\t\tdisplay: flex;\n\t\tbackground-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.2));\n\t`;\n\n\texport const PortsContainer = styled.div`\n\t\tflex-grow: 1;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\n\t\t&:first-of-type {\n\t\t\tmargin-right: 10px;\n\t\t}\n\n\t\t&:only-child {\n\t\t\tmargin-right: 0px;\n\t\t}\n\t`;\n}\n\nexport interface DefaultNodeProps {\n\tnode: DefaultNodeModel;\n\tengine: DiagramEngine;\n}\n\n/**\n * Default node that models the DefaultNodeModel. It creates two columns\n * for both all the input ports on the left, and the output ports on the right.\n */\nexport class DefaultNodeWidget extends React.Component<DefaultNodeProps> {\n\tgeneratePort = (port) => {\n\t\treturn <DefaultPortLabel engine={this.props.engine} port={port} key={port.getID()} />;\n\t};\n\n\trender() {\n\t\treturn (\n\t\t\t<S.Node\n\t\t\t\tdata-default-node-name={this.props.node.getOptions().name}\n\t\t\t\tselected={this.props.node.isSelected()}\n\t\t\t\tbackground={this.props.node.getOptions().color}\n\t\t\t>\n\t\t\t\t<S.Title>\n\t\t\t\t\t<S.TitleName>{this.props.node.getOptions().name}</S.TitleName>\n\t\t\t\t</S.Title>\n\t\t\t\t<S.Ports>\n\t\t\t\t\t<S.PortsContainer>{_map(this.props.node.getInPorts(), this.generatePort)}</S.PortsContainer>\n\t\t\t\t\t<S.PortsContainer>{_map(this.props.node.getOutPorts(), this.generatePort)}</S.PortsContainer>\n\t\t\t\t</S.Ports>\n\t\t\t</S.Node>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/port/DefaultPortFactory.tsx",
    "content": "import { DefaultPortModel } from './DefaultPortModel';\nimport { AbstractModelFactory } from '@projectstorm/react-canvas-core';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\n\nexport class DefaultPortFactory extends AbstractModelFactory<DefaultPortModel, DiagramEngine> {\n\tconstructor() {\n\t\tsuper('default');\n\t}\n\n\tgenerateModel(): DefaultPortModel {\n\t\treturn new DefaultPortModel({\n\t\t\tname: 'unknown'\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/port/DefaultPortLabelWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine, PortWidget } from '@projectstorm/react-diagrams-core';\nimport { DefaultPortModel } from './DefaultPortModel';\nimport styled from '@emotion/styled';\n\nexport interface DefaultPortLabelProps {\n\tport: DefaultPortModel;\n\tengine: DiagramEngine;\n}\n\nnamespace S {\n\texport const PortLabel = styled.div`\n\t\tdisplay: flex;\n\t\tmargin-top: 1px;\n\t\talign-items: center;\n\t`;\n\n\texport const Label = styled.div`\n\t\tpadding: 0 5px;\n\t\tflex-grow: 1;\n\t`;\n\n\texport const Port = styled.div`\n\t\twidth: 15px;\n\t\theight: 15px;\n\t\tbackground: rgba(255, 255, 255, 0.1);\n\n\t\t&:hover {\n\t\t\tbackground: rgb(192, 255, 0);\n\t\t}\n\t`;\n}\n\nexport class DefaultPortLabel extends React.Component<DefaultPortLabelProps> {\n\trender() {\n\t\tconst port = (\n\t\t\t<PortWidget engine={this.props.engine} port={this.props.port}>\n\t\t\t\t<S.Port />\n\t\t\t</PortWidget>\n\t\t);\n\t\tconst label = <S.Label>{this.props.port.getOptions().label}</S.Label>;\n\n\t\treturn (\n\t\t\t<S.PortLabel>\n\t\t\t\t{this.props.port.getOptions().in ? port : label}\n\t\t\t\t{this.props.port.getOptions().in ? label : port}\n\t\t\t</S.PortLabel>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/src/port/DefaultPortModel.ts",
    "content": "import {\n\tLinkModel,\n\tPortModel,\n\tPortModelAlignment,\n\tPortModelGenerics,\n\tPortModelOptions\n} from '@projectstorm/react-diagrams-core';\nimport { DefaultLinkModel } from '../link/DefaultLinkModel';\nimport { AbstractModelFactory, DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport interface DefaultPortModelOptions extends PortModelOptions {\n\tlabel?: string;\n\tin?: boolean;\n\ttype?: string;\n}\n\nexport interface DefaultPortModelGenerics extends PortModelGenerics {\n\tOPTIONS: DefaultPortModelOptions;\n}\n\nexport class DefaultPortModel extends PortModel<DefaultPortModelGenerics> {\n\tconstructor(isIn: boolean, name?: string, label?: string);\n\tconstructor(options: DefaultPortModelOptions);\n\tconstructor(options: DefaultPortModelOptions | boolean, name?: string, label?: string) {\n\t\tif (!!name) {\n\t\t\toptions = {\n\t\t\t\tin: !!options,\n\t\t\t\tname: name,\n\t\t\t\tlabel: label\n\t\t\t};\n\t\t}\n\t\toptions = options as DefaultPortModelOptions;\n\t\tsuper({\n\t\t\tlabel: options.label || options.name,\n\t\t\talignment: options.in ? PortModelAlignment.LEFT : PortModelAlignment.RIGHT,\n\t\t\ttype: 'default',\n\t\t\t...options\n\t\t});\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.options.in = event.data.in;\n\t\tthis.options.label = event.data.label;\n\t}\n\n\tserialize() {\n\t\treturn {\n\t\t\t...super.serialize(),\n\t\t\tin: this.options.in,\n\t\t\tlabel: this.options.label\n\t\t};\n\t}\n\n\tlink<T extends LinkModel>(port: PortModel, factory?: AbstractModelFactory<T>): T {\n\t\tlet link = this.createLinkModel(factory);\n\t\tlink.setSourcePort(this);\n\t\tlink.setTargetPort(port);\n\t\treturn link as T;\n\t}\n\n\tcanLinkToPort(port: PortModel): boolean {\n\t\tif (port instanceof DefaultPortModel) {\n\t\t\treturn this.options.in !== port.getOptions().in;\n\t\t}\n\t\treturn true;\n\t}\n\n\tcreateLinkModel(factory?: AbstractModelFactory<LinkModel>): LinkModel {\n\t\tlet link = super.createLinkModel();\n\t\tif (!link && factory) {\n\t\t\treturn factory.generateModel({});\n\t\t}\n\t\treturn link || new DefaultLinkModel();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.base.json\",\n\t\"compilerOptions\": {\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"declarationDir\": \"dist/@types\",\n\t\t\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"\n\t},\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"../react-diagrams-core\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "packages/react-diagrams-defaults/webpack.config.js",
    "content": "const config = require('../../webpack.shared')(__dirname);\nmodule.exports = {\n\t...config,\n\toutput: {\n\t\t...config.output,\n\t\tlibrary: 'projectstorm/react-diagrams-defaults'\n\t}\n};\n"
  },
  {
    "path": "packages/react-diagrams-routing/.npmignore",
    "content": "*\n!dist/**/*\n!package.json\ndist/tsconfig.tsbuildinfo"
  },
  {
    "path": "packages/react-diagrams-routing/CHANGELOG.md",
    "content": "# @projectstorm/react-diagrams-routing\n\n## 7.1.3\n\n### Patch Changes\n\n- 80285fe: refactor: update lodash imports to use individual functions\n- Updated dependencies [09ed60f]\n- Updated dependencies [20766f5]\n- Updated dependencies [80285fe]\n  - @projectstorm/react-canvas-core@7.0.3\n  - @projectstorm/react-diagrams-core@7.0.3\n  - @projectstorm/react-diagrams-defaults@7.1.3\n  - @projectstorm/geometry@7.0.3\n\n## 7.1.2\n\n### Patch Changes\n\n- 66c687a: Upgrade all dependencies and fix Storybook after upgrade\n- Updated dependencies [66c687a]\n  - @projectstorm/react-diagrams-defaults@7.1.2\n  - @projectstorm/react-diagrams-core@7.0.2\n  - @projectstorm/react-canvas-core@7.0.2\n  - @projectstorm/geometry@7.0.2\n\n## 7.1.1\n\n### Patch Changes\n\n- b8a4cbd: Inline sources in sourcemap\n- Updated dependencies [b8a4cbd]\n  - @projectstorm/geometry@7.0.1\n  - @projectstorm/react-canvas-core@7.0.1\n  - @projectstorm/react-diagrams-core@7.0.1\n  - @projectstorm/react-diagrams-defaults@7.1.1\n\n## 7.1.0\n\n### Minor Changes\n\n- e0d21f1: - [feature] new ability to refresh links in auto distribute system [PR 756](https://github.com/projectstorm/react-diagrams/pull/756)\n\n  - [fix] Default link now uses the correct method for creating a point allowing this to be overridden [PR 939](https://github.com/projectstorm/react-diagrams/pull/939)\n\n  Big thanks to @ToTheHit and @h0111in for your help on these, even though its very delayed on my part :)\n\n### Patch Changes\n\n- Updated dependencies [e0d21f1]\n  - @projectstorm/react-diagrams-defaults@7.1.0\n\n## 7.0.0\n\n### Major Changes\n\n- b051697: - [internal] moves to `Pnpm` (instead of yarn -\\_-)\n  - [internal]moves to `Changesets` for releases\n  - [internal]removes `Lerna`\n  - [internal] upgrades all dependencies\n  - [internal] switches to workspace protocol syntax (Changesets will bake in the correct version when a publish occurs)\n  - [internal] Changesets will open a release PR which can wrap up several changes in 1 go\n  - [internal] Changesets will run the storybook deploy automatically upon merging the release PR\n  - [internal] removes a lot of the stuff from the root package.json\n  - [internal] cleans up the build and clean commands\n  - [internal] remove E2E tests, they are a nightmare to maintain and the ROI is far too low\n  - [fix] Wrong type name for react-canvas model listener\n  - [fix] export more stuff form the main react-diagrams package\n  - [fix] circular deps with Rectangle and Polygon (turns out this was a problem but only with UMD builds, sorry @everyone who I doubted, but this is also why I could never reproduce the issue)\n  - [breaking change] compile both ES6 and UMD\n  - [breaking change] moves dependencies back to each package. (After years of working on libraries, I've come to actually hate peer dependencies, and this is easily solved with build systems / package managers).\n  - [breaking change] static methods on `Polygon` and `Rectangle` moved to standalone methods\n  - [breaking change] static construction methods to rather deal with different Rectangle constructor overloads (I now consider this bad design)\n  - [breaking change] introduce `Bounds` as a simpler point-array type to deal with boundary computation instead\n\n### Patch Changes\n\n- Updated dependencies [b051697]\n  - @projectstorm/react-diagrams-defaults@7.0.0\n  - @projectstorm/react-diagrams-core@7.0.0\n  - @projectstorm/react-canvas-core@7.0.0\n  - @projectstorm/geometry@7.0.0\n"
  },
  {
    "path": "packages/react-diagrams-routing/README.md",
    "content": "# Project STORM > React Diagrams > Dagre\n\nThis package adds dagre integration for laying out nodes and links\n"
  },
  {
    "path": "packages/react-diagrams-routing/jest.config.js",
    "content": "const path = require('path');\nmodule.exports = {\n\ttransform: {\n\t\t'^.+\\\\.tsx?$': 'ts-jest'\n\t},\n\troots: [path.join(__dirname, 'tests')],\n\ttestMatch: ['**/*.test.{ts,tsx}']\n};\n"
  },
  {
    "path": "packages/react-diagrams-routing/package.json",
    "content": "{\n\t\"name\": \"@projectstorm/react-diagrams-routing\",\n\t\"version\": \"7.1.3\",\n\t\"author\": \"dylanvorster\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/projectstorm/react-diagrams.git\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"rimraf ./dist\",\n\t\t\"build\": \"../../node_modules/.bin/webpack\",\n\t\t\"test\": \"../../node_modules/.bin/jest\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"keywords\": [\n\t\t\"web\",\n\t\t\"diagram\",\n\t\t\"diagrams\",\n\t\t\"react\",\n\t\t\"typescript\",\n\t\t\"flowchart\",\n\t\t\"simple\",\n\t\t\"links\",\n\t\t\"nodes\"\n\t],\n\t\"main\": \"./dist/index.umd.js\",\n\t\"module\": \"./dist/index.js\",\n\t\"typings\": \"./dist/@types/index\",\n\t\"dependencies\": {\n\t\t\"@projectstorm/geometry\": \"workspace:*\",\n\t\t\"@projectstorm/react-canvas-core\": \"workspace:*\",\n\t\t\"@projectstorm/react-diagrams-core\": \"workspace:*\",\n\t\t\"@projectstorm/react-diagrams-defaults\": \"workspace:*\",\n\t\t\"dagre\": \"^0.8.5\",\n\t\t\"lodash\": \"^4.17.21\",\n\t\t\"pathfinding\": \"^0.4.18\",\n\t\t\"paths-js\": \"^0.4.11\",\n\t\t\"react\": \"^19.0.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/dagre\": \"^0.7.50\",\n\t\t\"@types/lodash\": \"^4.14.200\",\n\t\t\"@types/react\": \"^19.0.12\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/dagre/DagreEngine.ts",
    "content": "import { DiagramModel, PointModel } from '@projectstorm/react-diagrams-core';\nimport * as dagre from 'dagre';\nimport { GraphLabel } from 'dagre';\nimport _every from 'lodash/every';\nimport _findIndex from 'lodash/findIndex';\nimport _forEach from 'lodash/forEach';\nimport _map from 'lodash/map';\nimport _range from 'lodash/range';\nimport _sortBy from 'lodash/sortBy';\nimport { Point } from '@projectstorm/geometry';\n\nexport interface DagreEngineOptions {\n\tgraph?: GraphLabel;\n\t/**\n\t * Will also re-layout links\n\t */\n\tincludeLinks?: boolean;\n\tnodeMargin?: number;\n}\n\nexport class DagreEngine {\n\toptions: DagreEngineOptions;\n\n\tconstructor(options: DagreEngineOptions = {}) {\n\t\tthis.options = options;\n\t}\n\n\tredistribute(model: DiagramModel) {\n\t\t// Create a new directed graph\n\t\tvar g = new dagre.graphlib.Graph({\n\t\t\tmultigraph: true,\n\t\t\tcompound: true\n\t\t});\n\t\tg.setGraph(this.options.graph || {});\n\t\tg.setDefaultEdgeLabel(function () {\n\t\t\treturn {};\n\t\t});\n\n\t\t// set nodes\n\t\t_forEach(model.getNodes(), (node) => {\n\t\t\tg.setNode(node.getID(), { width: node.width, height: node.height });\n\t\t});\n\n\t\t_forEach(model.getLinks(), (link) => {\n\t\t\t// set edges\n\t\t\tif (link.getSourcePort() && link.getTargetPort()) {\n\t\t\t\tg.setEdge({\n\t\t\t\t\tv: link.getSourcePort().getNode().getID(),\n\t\t\t\t\tw: link.getTargetPort().getNode().getID(),\n\t\t\t\t\tname: link.getID()\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// layout the graph\n\t\tdagre.layout(g);\n\n\t\tg.nodes().forEach((v) => {\n\t\t\tconst node = g.node(v);\n\t\t\tmodel.getNode(v).setPosition(node.x - node.width / 2, node.y - node.height / 2);\n\t\t});\n\n\t\t// also include links?\n\t\tif (this.options.includeLinks) {\n\t\t\tg.edges().forEach((e) => {\n\t\t\t\tconst edge = g.edge(e);\n\t\t\t\tconst link = model.getLink(e.name);\n\n\t\t\t\tconst points = [link.getFirstPoint()];\n\t\t\t\tfor (let i = 1; i < edge.points.length - 1; i++) {\n\t\t\t\t\tpoints.push(new PointModel({ link: link, position: new Point(edge.points[i].x, edge.points[i].y) }));\n\t\t\t\t}\n\t\t\t\tlink.setPoints(points.concat(link.getLastPoint()));\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * TODO cleanup this method into smaller methods\n\t */\n\tpublic refreshLinks(diagram: DiagramModel) {\n\t\tconst { nodeMargin } = this.options;\n\t\tconst nodes = diagram.getNodes();\n\t\tconst links = diagram.getLinks();\n\t\tlet maxChunkRowIndex = -1;\n\t\t// build the chunk matrix\n\t\tconst chunks: { [id: number]: { [id: number]: boolean } } = {}; // true: occupied, false: blank\n\t\tconst NodeXColumnIndexDictionary: { [id: number]: number } = {};\n\t\tlet verticalLines: number[] = [];\n\t\t_forEach(nodes, (node) => {\n\t\t\t// find vertical lines. vertical lines go through maximum number of nodes located under each other.\n\t\t\tconst nodeColumnCenter = node.getX() + node.width / 2;\n\t\t\tif (\n\t\t\t\t_every(verticalLines, (vLine) => {\n\t\t\t\t\treturn Math.abs(nodeColumnCenter - vLine) > nodeMargin;\n\t\t\t\t})\n\t\t\t) {\n\t\t\t\tverticalLines.push(nodeColumnCenter);\n\t\t\t}\n\t\t});\n\n\t\t// sort chunk columns\n\t\tverticalLines = verticalLines.sort((a, b) => a - b);\n\t\t_forEach(verticalLines, (line, index) => {\n\t\t\tchunks[index] = {};\n\t\t\tchunks[index + 0.5] = {};\n\t\t});\n\n\t\t// set occupied chunks\n\t\t_forEach(nodes, (node) => {\n\t\t\tconst nodeColumnCenter = node.getX() + node.width / 2;\n\t\t\tconst startChunkIndex = Math.floor(node.getY() / nodeMargin);\n\t\t\tconst endChunkIndex = Math.floor((node.getY() + node.height) / nodeMargin);\n\t\t\t// find max ChunkRowIndex\n\t\t\tif (endChunkIndex > maxChunkRowIndex) maxChunkRowIndex = endChunkIndex;\n\t\t\tconst nodeColumnIndex = _findIndex(verticalLines, (vLine) => {\n\t\t\t\treturn Math.abs(nodeColumnCenter - vLine) <= nodeMargin;\n\t\t\t});\n\t\t\t_forEach(_range(startChunkIndex, endChunkIndex + 1), (chunkIndex) => {\n\t\t\t\tchunks[nodeColumnIndex][chunkIndex] = true;\n\t\t\t});\n\t\t\tNodeXColumnIndexDictionary[node.getX()] = nodeColumnIndex;\n\t\t});\n\n\t\t// sort links based on their distances\n\t\tconst edges = _map(links, (link) => {\n\t\t\tif (link.getSourcePort() && link.getTargetPort()) {\n\t\t\t\tconst source = link.getSourcePort().getNode();\n\t\t\t\tconst target = link.getTargetPort().getNode();\n\t\t\t\tconst sourceIndex = NodeXColumnIndexDictionary[source.getX()];\n\t\t\t\tconst targetIndex = NodeXColumnIndexDictionary[target.getX()];\n\n\t\t\t\treturn sourceIndex > targetIndex\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tlink,\n\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\tsourceY: source.getY() + source.height / 2,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\ttargetIndex,\n\t\t\t\t\t\t\ttargetY: target.getY() + source.height / 2,\n\t\t\t\t\t\t\ttarget\n\t\t\t\t\t  }\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tlink,\n\t\t\t\t\t\t\tsourceIndex: targetIndex,\n\t\t\t\t\t\t\tsourceY: target.getY() + target.height / 2,\n\t\t\t\t\t\t\tsource: target,\n\t\t\t\t\t\t\ttargetIndex: sourceIndex,\n\t\t\t\t\t\t\ttargetY: source.getY() + source.height / 2,\n\t\t\t\t\t\t\ttarget: source\n\t\t\t\t\t  };\n\t\t\t}\n\t\t});\n\t\tconst sortedEdges = _sortBy(edges, (link) => {\n\t\t\treturn Math.abs(link.targetIndex - link.sourceIndex);\n\t\t});\n\n\t\t// set link points\n\t\tif (this.options.includeLinks) {\n\t\t\t_forEach(sortedEdges, (edge) => {\n\t\t\t\tconst link = diagram.getLink(edge.link.getID());\n\t\t\t\t// re-draw\n\t\t\t\tif (Math.abs(edge.sourceIndex - edge.targetIndex) > 1) {\n\t\t\t\t\t// get the length of link in column\n\t\t\t\t\tconst columns = _range(edge.sourceIndex - 1, edge.targetIndex);\n\n\t\t\t\t\tconst chunkIndex = Math.floor(edge.sourceY / nodeMargin);\n\t\t\t\t\tconst targetChunkIndex = Math.floor(edge.targetY / nodeMargin);\n\n\t\t\t\t\t// check upper paths\n\t\t\t\t\tlet northCost = 1;\n\t\t\t\t\tlet aboveRowIndex = chunkIndex;\n\t\t\t\t\tfor (; aboveRowIndex >= 0; aboveRowIndex--, northCost++) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t_every(columns, (columnIndex) => {\n\t\t\t\t\t\t\t\treturn !(\n\t\t\t\t\t\t\t\t\tchunks[columnIndex][aboveRowIndex] ||\n\t\t\t\t\t\t\t\t\tchunks[columnIndex + 0.5][aboveRowIndex] ||\n\t\t\t\t\t\t\t\t\tchunks[columnIndex - 0.5][aboveRowIndex]\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// check lower paths\n\t\t\t\t\tlet southCost = 0;\n\t\t\t\t\tlet belowRowIndex = chunkIndex;\n\t\t\t\t\tfor (; belowRowIndex <= maxChunkRowIndex; belowRowIndex++, southCost++) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t_every(columns, (columnIndex) => {\n\t\t\t\t\t\t\t\treturn !(\n\t\t\t\t\t\t\t\t\tchunks[columnIndex][belowRowIndex] ||\n\t\t\t\t\t\t\t\t\tchunks[columnIndex + 0.5][belowRowIndex] ||\n\t\t\t\t\t\t\t\t\tchunks[columnIndex - 0.5][belowRowIndex]\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// pick the cheapest path\n\t\t\t\t\tconst pathRowIndex =\n\t\t\t\t\t\tsouthCost + (belowRowIndex - targetChunkIndex) < northCost + (targetChunkIndex - aboveRowIndex)\n\t\t\t\t\t\t\t? belowRowIndex + 1\n\t\t\t\t\t\t\t: aboveRowIndex - 1;\n\n\t\t\t\t\t// Finally update the link points\n\t\t\t\t\tconst points = [link.getFirstPoint()];\n\t\t\t\t\tpoints.push(\n\t\t\t\t\t\tnew PointModel({\n\t\t\t\t\t\t\tlink: link,\n\t\t\t\t\t\t\tposition: new Point(\n\t\t\t\t\t\t\t\t(verticalLines[columns[0]] + verticalLines[columns[0] + 1]) / 2,\n\t\t\t\t\t\t\t\t(pathRowIndex + 0.5) * nodeMargin\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\n\t\t\t\t\t_forEach(columns, (column) => {\n\t\t\t\t\t\tpoints.push(\n\t\t\t\t\t\t\tnew PointModel({\n\t\t\t\t\t\t\t\tlink: link,\n\t\t\t\t\t\t\t\tposition: new Point(verticalLines[column], (pathRowIndex + 0.5) * nodeMargin)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t\tpoints.push(\n\t\t\t\t\t\t\tnew PointModel({\n\t\t\t\t\t\t\t\tlink: link,\n\t\t\t\t\t\t\t\tposition: new Point(\n\t\t\t\t\t\t\t\t\t(verticalLines[column] + verticalLines[column - 1]) / 2,\n\t\t\t\t\t\t\t\t\t(pathRowIndex + 0.5) * nodeMargin\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t\tchunks[column][pathRowIndex] = true;\n\t\t\t\t\t\tchunks[column][pathRowIndex + 1] = true;\n\t\t\t\t\t\tchunks[column + 0.5][pathRowIndex] = true;\n\t\t\t\t\t\tchunks[column + 0.5][pathRowIndex + 1] = true;\n\t\t\t\t\t});\n\t\t\t\t\tlink.setPoints(points.concat(link.getLastPoint()));\n\t\t\t\t} else {\n\t\t\t\t\t// refresh\n\t\t\t\t\tlink.setPoints([link.getFirstPoint(), link.getLastPoint()]);\n\t\t\t\t\tconst columnIndex = (edge.sourceIndex + edge.targetIndex) / 2;\n\t\t\t\t\tif (!chunks[columnIndex]) {\n\t\t\t\t\t\tchunks[columnIndex] = {};\n\t\t\t\t\t}\n\t\t\t\t\tconst rowIndex = Math.floor((edge.sourceY + edge.targetY) / 2 / nodeMargin);\n\t\t\t\t\tchunks[columnIndex][rowIndex] = true;\n\t\t\t\t\tchunks[columnIndex][rowIndex + 1] = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/engine/PathFinding.ts",
    "content": "import * as PF from 'pathfinding';\nimport { PathFindingLinkFactory } from '../link/PathFindingLinkFactory';\nimport { PointModel } from '@projectstorm/react-diagrams-core';\n\n/*\nit can be very expensive to calculate routes when every single pixel on the canvas\nis individually represented. Using the factor below, we combine values in order\nto achieve the best trade-off between accuracy and performance.\n*/\n\nconst pathFinderInstance = new PF.JumpPointFinder({\n\theuristic: PF.Heuristic.manhattan,\n\tdiagonalMovement: PF.DiagonalMovement.Never\n});\n\nexport class PathFinding {\n\tinstance: any;\n\tfactory: PathFindingLinkFactory;\n\n\tconstructor(factory: PathFindingLinkFactory) {\n\t\tthis.instance = pathFinderInstance;\n\t\tthis.factory = factory;\n\t}\n\n\t/**\n\t * Taking as argument a fully unblocked walking matrix, this method\n\t * finds a direct path from point A to B.\n\t */\n\tcalculateDirectPath(from: PointModel, to: PointModel): number[][] {\n\t\tconst matrix = this.factory.getCanvasMatrix();\n\t\tconst grid = new PF.Grid(matrix);\n\n\t\treturn pathFinderInstance.findPath(\n\t\t\tthis.factory.translateRoutingX(Math.floor(from.getX() / this.factory.ROUTING_SCALING_FACTOR)),\n\t\t\tthis.factory.translateRoutingY(Math.floor(from.getY() / this.factory.ROUTING_SCALING_FACTOR)),\n\t\t\tthis.factory.translateRoutingX(Math.floor(to.getX() / this.factory.ROUTING_SCALING_FACTOR)),\n\t\t\tthis.factory.translateRoutingY(Math.floor(to.getY() / this.factory.ROUTING_SCALING_FACTOR)),\n\t\t\tgrid\n\t\t);\n\t}\n\n\t/**\n\t * Using @link{#calculateDirectPath}'s result as input, we here\n\t * determine the first walkable point found in the matrix that includes\n\t * blocked paths.\n\t */\n\tcalculateLinkStartEndCoords(\n\t\tmatrix: number[][],\n\t\tpath: number[][]\n\t): {\n\t\tstart: {\n\t\t\tx: number;\n\t\t\ty: number;\n\t\t};\n\t\tend: {\n\t\t\tx: number;\n\t\t\ty: number;\n\t\t};\n\t\tpathToStart: number[][];\n\t\tpathToEnd: number[][];\n\t} {\n\t\tconst startIndex = path.findIndex((point) => {\n\t\t\tif (matrix[point[1]]) return matrix[point[1]][point[0]] === 0;\n\t\t\telse return false;\n\t\t});\n\t\tconst endIndex =\n\t\t\tpath.length -\n\t\t\t1 -\n\t\t\tpath\n\t\t\t\t.slice()\n\t\t\t\t.reverse()\n\t\t\t\t.findIndex((point) => {\n\t\t\t\t\tif (matrix[point[1]]) return matrix[point[1]][point[0]] === 0;\n\t\t\t\t\telse return false;\n\t\t\t\t});\n\n\t\t// are we trying to create a path exclusively through blocked areas?\n\t\t// if so, let's fallback to the linear routing\n\t\tif (startIndex === -1 || endIndex === -1) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst pathToStart = path.slice(0, startIndex);\n\t\tconst pathToEnd = path.slice(endIndex);\n\n\t\treturn {\n\t\t\tstart: {\n\t\t\t\tx: path[startIndex][0],\n\t\t\t\ty: path[startIndex][1]\n\t\t\t},\n\t\t\tend: {\n\t\t\t\tx: path[endIndex][0],\n\t\t\t\ty: path[endIndex][1]\n\t\t\t},\n\t\t\tpathToStart,\n\t\t\tpathToEnd\n\t\t};\n\t}\n\n\t/**\n\t * Puts everything together: merges the paths from/to the centre of the ports,\n\t * with the path calculated around other elements.\n\t */\n\tcalculateDynamicPath(\n\t\troutingMatrix: number[][],\n\t\tstart: {\n\t\t\tx: number;\n\t\t\ty: number;\n\t\t},\n\t\tend: {\n\t\t\tx: number;\n\t\t\ty: number;\n\t\t},\n\t\tpathToStart: number[][],\n\t\tpathToEnd: number[][]\n\t) {\n\t\t// generate the path based on the matrix with obstacles\n\t\tconst grid = new PF.Grid(routingMatrix);\n\t\tconst dynamicPath = pathFinderInstance.findPath(start.x, start.y, end.x, end.y, grid);\n\n\t\t// aggregate everything to have the calculated path ready for rendering\n\t\tconst pathCoords = pathToStart\n\t\t\t.concat(dynamicPath, pathToEnd)\n\t\t\t.map((coords) => [\n\t\t\t\tthis.factory.translateRoutingX(coords[0], true),\n\t\t\t\tthis.factory.translateRoutingY(coords[1], true)\n\t\t\t]);\n\t\treturn PF.Util.compressPath(pathCoords);\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/index.ts",
    "content": "export * from './link/PathFindingLinkFactory';\nexport * from './link/PathFindingLinkModel';\nexport * from './link/PathFindingLinkWidget';\nexport * from './link/RightAngleLinkWidget';\nexport * from './link/RightAngleLinkFactory';\nexport * from './link/RightAngleLinkModel';\n\nexport * from './engine/PathFinding';\nexport * from './dagre/DagreEngine';\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/link/PathFindingLinkFactory.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { PathFindingLinkModel } from './PathFindingLinkModel';\nimport { PathFindingLinkWidget } from './PathFindingLinkWidget';\nimport _cloneDeep from 'lodash/cloneDeep';\nimport _concat from 'lodash/concat';\nimport _defer from 'lodash/defer';\nimport _flatMap from 'lodash/flatMap';\nimport _get from 'lodash/get';\nimport _minBy from 'lodash/minBy';\nimport _maxBy from 'lodash/maxBy';\nimport _range from 'lodash/range';\nimport _reduce from 'lodash/reduce';\nimport _values from 'lodash/values';\nimport * as Path from 'paths-js/path';\nimport { DefaultLinkFactory } from '@projectstorm/react-diagrams-defaults';\nimport {\n\tAbstractDisplacementState,\n\tAbstractFactory,\n\tAction,\n\tFactoryBank,\n\tInputType,\n\tListenerHandle\n} from '@projectstorm/react-canvas-core';\nimport { JSX } from 'react';\n\nexport class PathFindingLinkFactory extends DefaultLinkFactory<PathFindingLinkModel> {\n\tROUTING_SCALING_FACTOR: number = 5;\n\n\t// calculated only when smart routing is active\n\tcanvasMatrix: number[][] = [];\n\troutingMatrix: number[][] = [];\n\n\t// used when at least one element has negative coordinates\n\thAdjustmentFactor: number = 0;\n\tvAdjustmentFactor: number = 0;\n\n\tstatic NAME = 'pathfinding';\n\tlistener: ListenerHandle;\n\n\tconstructor() {\n\t\tsuper(PathFindingLinkFactory.NAME);\n\t}\n\n\tsetDiagramEngine(engine: DiagramEngine): void {\n\t\tsuper.setDiagramEngine(engine);\n\n\t\t// listen for drag changes\n\t\tengine.getStateMachine().registerListener({\n\t\t\tstateChanged: (event) => {\n\t\t\t\tif (event.newState instanceof AbstractDisplacementState) {\n\t\t\t\t\tconst deRegister = engine.getActionEventBus().registerAction(\n\t\t\t\t\t\tnew Action<DiagramEngine>({\n\t\t\t\t\t\t\ttype: InputType.MOUSE_UP,\n\t\t\t\t\t\t\tfire: () => {\n\t\t\t\t\t\t\t\tthis.calculateRoutingMatrix();\n\t\t\t\t\t\t\t\tengine.repaintCanvas();\n\t\t\t\t\t\t\t\tdeRegister();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tthis.listener = engine.registerListener({\n\t\t\tcanvasReady: () => {\n\t\t\t\t_defer(() => {\n\t\t\t\t\tthis.calculateRoutingMatrix();\n\t\t\t\t\tengine.repaintCanvas();\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\tsetFactoryBank(bank: FactoryBank<AbstractFactory>): void {\n\t\tsuper.setFactoryBank(bank);\n\t\tif (!bank && this.listener) {\n\t\t\tthis.listener.deregister();\n\t\t}\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <PathFindingLinkWidget diagramEngine={this.engine} link={event.model} factory={this} />;\n\t}\n\n\tgenerateModel(event): PathFindingLinkModel {\n\t\treturn new PathFindingLinkModel();\n\t}\n\n\t/**\n\t * A representation of the canvas in the following format:\n\t *\n\t * +-----------------+\n\t * | 0 0 0 0 0 0 0 0 |\n\t * | 0 0 0 0 0 0 0 0 |\n\t * | 0 0 0 0 0 0 0 0 |\n\t * | 0 0 0 0 0 0 0 0 |\n\t * | 0 0 0 0 0 0 0 0 |\n\t * +-----------------+\n\t *\n\t * In which all walkable points are marked by zeros.\n\t * It uses @link{#ROUTING_SCALING_FACTOR} to reduce the matrix dimensions and improve performance.\n\t */\n\tgetCanvasMatrix(): number[][] {\n\t\tif (this.canvasMatrix.length === 0) {\n\t\t\tthis.calculateCanvasMatrix();\n\t\t}\n\n\t\treturn this.canvasMatrix;\n\t}\n\tcalculateCanvasMatrix() {\n\t\tconst {\n\t\t\twidth: canvasWidth,\n\t\t\thAdjustmentFactor,\n\t\t\theight: canvasHeight,\n\t\t\tvAdjustmentFactor\n\t\t} = this.calculateMatrixDimensions();\n\n\t\tthis.hAdjustmentFactor = hAdjustmentFactor;\n\t\tthis.vAdjustmentFactor = vAdjustmentFactor;\n\n\t\tconst matrixWidth = Math.ceil(canvasWidth / this.ROUTING_SCALING_FACTOR);\n\t\tconst matrixHeight = Math.ceil(canvasHeight / this.ROUTING_SCALING_FACTOR);\n\n\t\tthis.canvasMatrix = _range(0, matrixHeight).map(() => {\n\t\t\treturn new Array(matrixWidth).fill(0);\n\t\t});\n\t}\n\n\t/**\n\t * A representation of the canvas in the following format:\n\t *\n\t * +-----------------+\n\t * | 0 0 1 1 0 0 0 0 |\n\t * | 0 0 1 1 0 0 1 1 |\n\t * | 0 0 0 0 0 0 1 1 |\n\t * | 1 1 0 0 0 0 0 0 |\n\t * | 1 1 0 0 0 0 0 0 |\n\t * +-----------------+\n\t *\n\t * In which all points blocked by a node (and its ports) are\n\t * marked as 1; points were there is nothing (ie, free) receive 0.\n\t */\n\tgetRoutingMatrix(): number[][] {\n\t\tif (this.routingMatrix.length === 0) {\n\t\t\tthis.calculateRoutingMatrix();\n\t\t}\n\n\t\treturn this.routingMatrix;\n\t}\n\tcalculateRoutingMatrix(): void {\n\t\tconst matrix = _cloneDeep(this.getCanvasMatrix());\n\n\t\t// nodes need to be marked as blocked points\n\t\tthis.markNodes(matrix);\n\t\t// same thing for ports\n\t\tthis.markPorts(matrix);\n\n\t\tthis.routingMatrix = matrix;\n\t}\n\n\t/**\n\t * The routing matrix does not have negative indexes, but elements could be negatively positioned.\n\t * We use the functions below to translate back and forth between these coordinates, relying on the\n\t * calculated values of hAdjustmentFactor and vAdjustmentFactor.\n\t */\n\ttranslateRoutingX(x: number, reverse: boolean = false) {\n\t\treturn x + this.hAdjustmentFactor * (reverse ? -1 : 1);\n\t}\n\ttranslateRoutingY(y: number, reverse: boolean = false) {\n\t\treturn y + this.vAdjustmentFactor * (reverse ? -1 : 1);\n\t}\n\n\t/**\n\t * Despite being a long method, we simply iterate over all three collections (nodes, ports and points)\n\t * to find the highest X and Y dimensions, so we can build the matrix large enough to contain all elements.\n\t */\n\tcalculateMatrixDimensions = (): {\n\t\twidth: number;\n\t\thAdjustmentFactor: number;\n\t\theight: number;\n\t\tvAdjustmentFactor: number;\n\t} => {\n\t\tconst allNodesCoords = _values(this.engine.getModel().getNodes()).map((item) => ({\n\t\t\tx: item.getX(),\n\t\t\twidth: item.width,\n\t\t\ty: item.getY(),\n\t\t\theight: item.height\n\t\t}));\n\n\t\tconst allLinks = _values(this.engine.getModel().getLinks());\n\t\tconst allPortsCoords = _flatMap(allLinks.map((link) => [link.getSourcePort(), link.getTargetPort()]))\n\t\t\t.filter((port) => port !== null)\n\t\t\t.map((item) => ({\n\t\t\t\tx: item.getX(),\n\t\t\t\twidth: item.width,\n\t\t\t\ty: item.getY(),\n\t\t\t\theight: item.height\n\t\t\t}));\n\t\tconst allPointsCoords = _flatMap(allLinks.map((link) => link.getPoints())).map((item) => ({\n\t\t\t// points don't have width/height, so let's just use 0\n\t\t\tx: item.getX(),\n\t\t\twidth: 0,\n\t\t\ty: item.getY(),\n\t\t\theight: 0\n\t\t}));\n\n\t\tconst sumProps = (object, props) => _reduce(props, (acc, prop) => acc + _get(object, prop, 0), 0);\n\n\t\tconst canvas = this.engine.getCanvas() as HTMLDivElement;\n\t\tconst concatedCoords = _concat(allNodesCoords, allPortsCoords, allPointsCoords);\n\t\tconst minX =\n\t\t\tMath.floor(Math.min(_get(_minBy(concatedCoords, 'x'), 'x', 0), 0) / this.ROUTING_SCALING_FACTOR) *\n\t\t\tthis.ROUTING_SCALING_FACTOR;\n\t\tconst maxXElement = _maxBy(concatedCoords, (item) => sumProps(item, ['x', 'width']));\n\t\tconst maxX = Math.max(sumProps(maxXElement, ['x', 'width']), canvas.offsetWidth);\n\t\tconst minYCoords = _minBy(concatedCoords, 'y');\n\t\tconst minY =\n\t\t\tMath.floor(Math.min(_get(minYCoords, 'y', 0), 0) / this.ROUTING_SCALING_FACTOR) * this.ROUTING_SCALING_FACTOR;\n\t\tconst maxYElement = _maxBy(concatedCoords, (item) => sumProps(item, ['y', 'height']));\n\t\tconst maxY = Math.max(sumProps(maxYElement, ['y', 'height']), canvas.offsetHeight);\n\n\t\treturn {\n\t\t\twidth: Math.ceil(Math.abs(minX) + maxX),\n\t\t\thAdjustmentFactor: Math.abs(minX) / this.ROUTING_SCALING_FACTOR + 1,\n\t\t\theight: Math.ceil(Math.abs(minY) + maxY),\n\t\t\tvAdjustmentFactor: Math.abs(minY) / this.ROUTING_SCALING_FACTOR + 1\n\t\t};\n\t};\n\n\t/**\n\t * Updates (by reference) where nodes will be drawn on the matrix passed in.\n\t */\n\tmarkNodes = (matrix: number[][]): void => {\n\t\t_values(this.engine.getModel().getNodes()).forEach((node) => {\n\t\t\tconst startX = Math.floor(node.getX() / this.ROUTING_SCALING_FACTOR);\n\t\t\tconst endX = Math.ceil((node.getX() + node.width) / this.ROUTING_SCALING_FACTOR);\n\t\t\tconst startY = Math.floor(node.getY() / this.ROUTING_SCALING_FACTOR);\n\t\t\tconst endY = Math.ceil((node.getY() + node.height) / this.ROUTING_SCALING_FACTOR);\n\n\t\t\tfor (let x = startX - 1; x <= endX + 1; x++) {\n\t\t\t\tfor (let y = startY - 1; y < endY + 1; y++) {\n\t\t\t\t\tthis.markMatrixPoint(matrix, this.translateRoutingX(x), this.translateRoutingY(y));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\t/**\n\t * Updates (by reference) where ports will be drawn on the matrix passed in.\n\t */\n\tmarkPorts = (matrix: number[][]): void => {\n\t\tconst allElements = _flatMap(\n\t\t\t_values(this.engine.getModel().getLinks()).map((link) => [].concat(link.getSourcePort(), link.getTargetPort()))\n\t\t);\n\t\tallElements\n\t\t\t.filter((port) => port !== null)\n\t\t\t.forEach((port) => {\n\t\t\t\tconst startX = Math.floor(port.x / this.ROUTING_SCALING_FACTOR);\n\t\t\t\tconst endX = Math.ceil((port.x + port.width) / this.ROUTING_SCALING_FACTOR);\n\t\t\t\tconst startY = Math.floor(port.y / this.ROUTING_SCALING_FACTOR);\n\t\t\t\tconst endY = Math.ceil((port.y + port.height) / this.ROUTING_SCALING_FACTOR);\n\n\t\t\t\tfor (let x = startX - 1; x <= endX + 1; x++) {\n\t\t\t\t\tfor (let y = startY - 1; y < endY + 1; y++) {\n\t\t\t\t\t\tthis.markMatrixPoint(matrix, this.translateRoutingX(x), this.translateRoutingY(y));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t};\n\n\tmarkMatrixPoint = (matrix: number[][], x: number, y: number) => {\n\t\tif (matrix[y] !== undefined && matrix[y][x] !== undefined) {\n\t\t\tmatrix[y][x] = 1;\n\t\t}\n\t};\n\n\tgenerateDynamicPath(pathCoords: number[][]) {\n\t\tlet path = Path();\n\t\tpath = path.moveto(pathCoords[0][0] * this.ROUTING_SCALING_FACTOR, pathCoords[0][1] * this.ROUTING_SCALING_FACTOR);\n\t\tpathCoords.slice(1).forEach((coords) => {\n\t\t\tpath = path.lineto(coords[0] * this.ROUTING_SCALING_FACTOR, coords[1] * this.ROUTING_SCALING_FACTOR);\n\t\t});\n\t\treturn path.print();\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/link/PathFindingLinkModel.ts",
    "content": "import { PathFindingLinkFactory } from './PathFindingLinkFactory';\nimport { DefaultLinkModel, DefaultLinkModelOptions } from '@projectstorm/react-diagrams-defaults';\n\nexport class PathFindingLinkModel extends DefaultLinkModel {\n\tconstructor(options: DefaultLinkModelOptions = {}) {\n\t\tsuper({\n\t\t\ttype: PathFindingLinkFactory.NAME,\n\t\t\t...options\n\t\t});\n\t}\n\n\tperformanceTune() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/link/PathFindingLinkWidget.tsx",
    "content": "import * as React from 'react';\nimport _first from 'lodash/first';\nimport _last from 'lodash/last';\nimport { DiagramEngine } from '@projectstorm/react-diagrams-core';\nimport { PathFinding } from '../engine/PathFinding';\nimport { PathFindingLinkFactory } from './PathFindingLinkFactory';\nimport { PathFindingLinkModel } from './PathFindingLinkModel';\nimport { DefaultLinkSegmentWidget } from '@projectstorm/react-diagrams-defaults';\nimport { JSX } from 'react';\n\nexport interface PathFindingLinkWidgetProps {\n\tcolor?: string;\n\twidth?: number;\n\tsmooth?: boolean;\n\tlink: PathFindingLinkModel;\n\tdiagramEngine: DiagramEngine;\n\tfactory: PathFindingLinkFactory;\n}\n\nexport interface PathFindingLinkWidgetState {\n\tselected: boolean;\n}\n\nexport class PathFindingLinkWidget extends React.Component<PathFindingLinkWidgetProps, PathFindingLinkWidgetState> {\n\trefPaths: React.RefObject<SVGPathElement>[];\n\tpathFinding: PathFinding;\n\n\tconstructor(props: PathFindingLinkWidgetProps) {\n\t\tsuper(props);\n\t\tthis.refPaths = [];\n\t\tthis.state = {\n\t\t\tselected: false\n\t\t};\n\t\tthis.pathFinding = new PathFinding(this.props.factory);\n\t}\n\n\tcomponentDidUpdate(): void {\n\t\tthis.props.link.setRenderedPaths(\n\t\t\tthis.refPaths.map((ref) => {\n\t\t\t\treturn ref.current;\n\t\t\t})\n\t\t);\n\t}\n\n\tcomponentDidMount(): void {\n\t\tthis.props.link.setRenderedPaths(\n\t\t\tthis.refPaths.map((ref) => {\n\t\t\t\treturn ref.current;\n\t\t\t})\n\t\t);\n\t}\n\n\tcomponentWillUnmount(): void {\n\t\tthis.props.link.setRenderedPaths([]);\n\t}\n\n\tgenerateLink(path: string, id: string | number): JSX.Element {\n\t\tconst ref = React.createRef<SVGPathElement>();\n\t\tthis.refPaths.push(ref);\n\t\treturn (\n\t\t\t<DefaultLinkSegmentWidget\n\t\t\t\tkey={`link-${id}`}\n\t\t\t\tpath={path}\n\t\t\t\tselected={this.state.selected}\n\t\t\t\tdiagramEngine={this.props.diagramEngine}\n\t\t\t\tfactory={this.props.diagramEngine.getFactoryForLink(this.props.link)}\n\t\t\t\tlink={this.props.link}\n\t\t\t\tforwardRef={ref}\n\t\t\t\tonSelection={(selected) => {\n\t\t\t\t\tthis.setState({ selected: selected });\n\t\t\t\t}}\n\t\t\t\textras={{}}\n\t\t\t/>\n\t\t);\n\t}\n\n\trender() {\n\t\tthis.refPaths = [];\n\t\t//ensure id is present for all points on the path\n\t\tvar points = this.props.link.getPoints();\n\t\tvar paths = [];\n\n\t\t// first step: calculate a direct path between the points being linked\n\t\tconst directPathCoords = this.pathFinding.calculateDirectPath(_first(points), _last(points));\n\n\t\tconst routingMatrix = this.props.factory.getRoutingMatrix();\n\t\t// now we need to extract, from the routing matrix, the very first walkable points\n\t\t// so they can be used as origin and destination of the link to be created\n\t\tconst smartLink = this.pathFinding.calculateLinkStartEndCoords(routingMatrix, directPathCoords);\n\t\tif (smartLink) {\n\t\t\tconst { start, end, pathToStart, pathToEnd } = smartLink;\n\n\t\t\t// second step: calculate a path avoiding hitting other elements\n\t\t\tconst simplifiedPath = this.pathFinding.calculateDynamicPath(routingMatrix, start, end, pathToStart, pathToEnd);\n\n\t\t\tpaths.push(\n\t\t\t\t//smooth: boolean, extraProps: any, id: string | number, firstPoint: PointModel, lastPoint: PointModel\n\t\t\t\tthis.generateLink(this.props.factory.generateDynamicPath(simplifiedPath), '0')\n\t\t\t);\n\t\t}\n\t\treturn <>{paths}</>;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/link/RightAngleLinkFactory.tsx",
    "content": "import * as React from 'react';\nimport { RightAngleLinkWidget } from './RightAngleLinkWidget';\nimport { DefaultLinkFactory } from '@projectstorm/react-diagrams-defaults';\nimport { RightAngleLinkModel } from './RightAngleLinkModel';\nimport { JSX } from 'react';\n\n/**\n * @author Daniel Lazar\n */\nexport class RightAngleLinkFactory extends DefaultLinkFactory<RightAngleLinkModel> {\n\tstatic NAME = 'rightAngle';\n\n\tconstructor() {\n\t\tsuper(RightAngleLinkFactory.NAME);\n\t}\n\n\tgenerateModel(event): RightAngleLinkModel {\n\t\treturn new RightAngleLinkModel();\n\t}\n\n\tgenerateReactWidget(event): JSX.Element {\n\t\treturn <RightAngleLinkWidget diagramEngine={this.engine} link={event.model} factory={this} />;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/link/RightAngleLinkModel.ts",
    "content": "import { DefaultLinkModel, DefaultLinkModelOptions } from '@projectstorm/react-diagrams-defaults';\nimport { RightAngleLinkFactory } from './RightAngleLinkFactory';\nimport { PointModel } from '@projectstorm/react-diagrams-core';\nimport { DeserializeEvent } from '@projectstorm/react-canvas-core';\n\nexport class RightAngleLinkModel extends DefaultLinkModel {\n\tlastHoverIndexOfPath: number;\n\tprivate _lastPathXdirection: boolean;\n\tprivate _firstPathXdirection: boolean;\n\tconstructor(options: DefaultLinkModelOptions = {}) {\n\t\tsuper({\n\t\t\ttype: RightAngleLinkFactory.NAME,\n\t\t\t...options\n\t\t});\n\t\tthis.lastHoverIndexOfPath = 0;\n\t\tthis._lastPathXdirection = false;\n\t\tthis._firstPathXdirection = false;\n\t}\n\n\tsetFirstAndLastPathsDirection() {\n\t\tlet points = this.getPoints();\n\t\tfor (let i = 1; i < points.length; i += points.length - 2) {\n\t\t\tlet dx = Math.abs(points[i].getX() - points[i - 1].getX());\n\t\t\tlet dy = Math.abs(points[i].getY() - points[i - 1].getY());\n\t\t\tif (i - 1 === 0) {\n\t\t\t\tthis._firstPathXdirection = dx > dy;\n\t\t\t} else {\n\t\t\t\tthis._lastPathXdirection = dx > dy;\n\t\t\t}\n\t\t}\n\t}\n\n\t// @ts-ignore\n\taddPoint<P extends PointModel>(pointModel: P, index: number = 1): P {\n\t\t// @ts-ignore\n\t\tsuper.addPoint(pointModel, index);\n\t\tthis.setFirstAndLastPathsDirection();\n\t\treturn pointModel;\n\t}\n\n\tdeserialize(event: DeserializeEvent<this>) {\n\t\tsuper.deserialize(event);\n\t\tthis.setFirstAndLastPathsDirection();\n\t}\n\n\tsetManuallyFirstAndLastPathsDirection(first, last) {\n\t\tthis._firstPathXdirection = first;\n\t\tthis._lastPathXdirection = last;\n\t}\n\n\tgetLastPathXdirection(): boolean {\n\t\treturn this._lastPathXdirection;\n\t}\n\tgetFirstPathXdirection(): boolean {\n\t\treturn this._firstPathXdirection;\n\t}\n\n\tsetWidth(width: number) {\n\t\tthis.options.width = width;\n\t\tthis.fireEvent({ width }, 'widthChanged');\n\t}\n\n\tsetColor(color: string) {\n\t\tthis.options.color = color;\n\t\tthis.fireEvent({ color }, 'colorChanged');\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/src/link/RightAngleLinkWidget.tsx",
    "content": "import * as React from 'react';\nimport { DiagramEngine, LinkWidget, PointModel } from '@projectstorm/react-diagrams-core';\nimport { RightAngleLinkFactory } from './RightAngleLinkFactory';\nimport { DefaultLinkModel, DefaultLinkSegmentWidget } from '@projectstorm/react-diagrams-defaults';\nimport { Point } from '@projectstorm/geometry';\nimport { JSX, MouseEvent } from 'react';\nimport { RightAngleLinkModel } from './RightAngleLinkModel';\n\nexport interface RightAngleLinkProps {\n\tcolor?: string;\n\twidth?: number;\n\tsmooth?: boolean;\n\tlink: RightAngleLinkModel;\n\tdiagramEngine: DiagramEngine;\n\tfactory: RightAngleLinkFactory;\n}\n\nexport interface RightAngleLinkState {\n\tselected: boolean;\n\tcanDrag: boolean;\n}\n\nexport class RightAngleLinkWidget extends React.Component<RightAngleLinkProps, RightAngleLinkState> {\n\tpublic static defaultProps: RightAngleLinkProps = {\n\t\tcolor: 'red',\n\t\twidth: 3,\n\t\tlink: null,\n\t\tsmooth: false,\n\t\tdiagramEngine: null,\n\t\tfactory: null\n\t};\n\n\trefPaths: React.RefObject<SVGPathElement>[];\n\n\t// DOM references to the label and paths (if label is given), used to calculate dynamic positioning\n\trefLabels: { [id: string]: HTMLElement };\n\tdragging_index: number;\n\n\tconstructor(props: RightAngleLinkProps) {\n\t\tsuper(props);\n\n\t\tthis.refPaths = [];\n\t\tthis.state = {\n\t\t\tselected: false,\n\t\t\tcanDrag: false\n\t\t};\n\n\t\tthis.dragging_index = 0;\n\t}\n\n\tcomponentDidUpdate(): void {\n\t\tthis.props.link.setRenderedPaths(\n\t\t\tthis.refPaths.map((ref) => {\n\t\t\t\treturn ref.current;\n\t\t\t})\n\t\t);\n\t}\n\n\tcomponentDidMount(): void {\n\t\tthis.props.link.setRenderedPaths(\n\t\t\tthis.refPaths.map((ref) => {\n\t\t\t\treturn ref.current;\n\t\t\t})\n\t\t);\n\t}\n\n\tcomponentWillUnmount(): void {\n\t\tthis.props.link.setRenderedPaths([]);\n\t}\n\n\tgenerateLink(path: string, extraProps: any, id: string | number): JSX.Element {\n\t\tconst ref = React.createRef<SVGPathElement>();\n\t\tthis.refPaths.push(ref);\n\t\treturn (\n\t\t\t<DefaultLinkSegmentWidget\n\t\t\t\tkey={`link-${id}`}\n\t\t\t\tpath={path}\n\t\t\t\tselected={this.state.selected}\n\t\t\t\tdiagramEngine={this.props.diagramEngine}\n\t\t\t\tfactory={this.props.diagramEngine.getFactoryForLink(this.props.link)}\n\t\t\t\tlink={this.props.link}\n\t\t\t\tforwardRef={ref}\n\t\t\t\tonSelection={(selected) => {\n\t\t\t\t\tthis.setState({ selected: selected });\n\t\t\t\t}}\n\t\t\t\textras={extraProps}\n\t\t\t/>\n\t\t);\n\t}\n\n\tcalculatePositions(points: PointModel[], event: MouseEvent, index: number, coordinate: string) {\n\t\t// If path is first or last add another point to keep node port on its position\n\t\tif (index === 0) {\n\t\t\tlet point = new PointModel({\n\t\t\t\tlink: this.props.link,\n\t\t\t\tposition: new Point(points[index].getX(), points[index].getY())\n\t\t\t});\n\t\t\tthis.props.link.addPoint(point, index);\n\t\t\tthis.dragging_index++;\n\t\t\treturn;\n\t\t} else if (index === points.length - 2) {\n\t\t\tlet point = new PointModel({\n\t\t\t\tlink: this.props.link,\n\t\t\t\tposition: new Point(points[index + 1].getX(), points[index + 1].getY())\n\t\t\t});\n\t\t\tthis.props.link.addPoint(point, index + 1);\n\t\t\treturn;\n\t\t}\n\n\t\t// Merge two points if it is not close to node port and close to each other\n\t\tif (index - 2 > 0) {\n\t\t\tlet _points = {\n\t\t\t\t[index - 2]: points[index - 2].getPosition(),\n\t\t\t\t[index + 1]: points[index + 1].getPosition(),\n\t\t\t\t[index - 1]: points[index - 1].getPosition()\n\t\t\t};\n\t\t\tif (Math.abs(_points[index - 1][coordinate] - _points[index + 1][coordinate]) < 5) {\n\t\t\t\t_points[index - 2][coordinate] = this.props.diagramEngine.getRelativeMousePoint(event)[coordinate];\n\t\t\t\t_points[index + 1][coordinate] = this.props.diagramEngine.getRelativeMousePoint(event)[coordinate];\n\t\t\t\tpoints[index - 2].setPosition(_points[index - 2]);\n\t\t\t\tpoints[index + 1].setPosition(_points[index + 1]);\n\t\t\t\tpoints[index - 1].remove();\n\t\t\t\tpoints[index - 1].remove();\n\t\t\t\tthis.dragging_index--;\n\t\t\t\tthis.dragging_index--;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Merge two points if it is not close to node port\n\t\tif (index + 2 < points.length - 2) {\n\t\t\tlet _points = {\n\t\t\t\t[index + 3]: points[index + 3].getPosition(),\n\t\t\t\t[index + 2]: points[index + 2].getPosition(),\n\t\t\t\t[index + 1]: points[index + 1].getPosition(),\n\t\t\t\t[index]: points[index].getPosition()\n\t\t\t};\n\t\t\tif (Math.abs(_points[index + 1][coordinate] - _points[index + 2][coordinate]) < 5) {\n\t\t\t\t_points[index][coordinate] = this.props.diagramEngine.getRelativeMousePoint(event)[coordinate];\n\t\t\t\t_points[index + 3][coordinate] = this.props.diagramEngine.getRelativeMousePoint(event)[coordinate];\n\t\t\t\tpoints[index].setPosition(_points[index]);\n\t\t\t\tpoints[index + 3].setPosition(_points[index + 3]);\n\t\t\t\tpoints[index + 1].remove();\n\t\t\t\tpoints[index + 1].remove();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// If no condition above handled then just update path points position\n\t\tlet _points = {\n\t\t\t[index]: points[index].getPosition(),\n\t\t\t[index + 1]: points[index + 1].getPosition()\n\t\t};\n\t\t_points[index][coordinate] = this.props.diagramEngine.getRelativeMousePoint(event)[coordinate];\n\t\t_points[index + 1][coordinate] = this.props.diagramEngine.getRelativeMousePoint(event)[coordinate];\n\t\tpoints[index].setPosition(_points[index]);\n\t\tpoints[index + 1].setPosition(_points[index + 1]);\n\t}\n\n\tdraggingEvent(event: MouseEvent, index: number) {\n\t\tlet points = this.props.link.getPoints();\n\t\t// get moving difference. Index + 1 will work because links indexes has\n\t\t// length = points.lenght - 1\n\t\tlet dx = Math.abs(points[index].getX() - points[index + 1].getX());\n\t\tlet dy = Math.abs(points[index].getY() - points[index + 1].getY());\n\n\t\t// moving with y direction\n\t\tif (dx === 0) {\n\t\t\tthis.calculatePositions(points, event, index, 'x');\n\t\t} else if (dy === 0) {\n\t\t\tthis.calculatePositions(points, event, index, 'y');\n\t\t}\n\t\tthis.props.link.setFirstAndLastPathsDirection();\n\t}\n\n\thandleMove = function (event: MouseEvent) {\n\t\tthis.draggingEvent(event, this.dragging_index);\n\t}.bind(this);\n\n\thandleUp = function (event: MouseEvent) {\n\t\t// Unregister handlers to avoid multiple event handlers for other links\n\t\tthis.setState({ canDrag: false, selected: false });\n\t\twindow.removeEventListener('mousemove', this.handleMove);\n\t\twindow.removeEventListener('mouseup', this.handleUp);\n\t}.bind(this);\n\n\trender() {\n\t\t//ensure id is present for all points on the path\n\t\tlet points = this.props.link.getPoints();\n\t\tlet paths = [];\n\t\tthis.refPaths = [];\n\n\t\t// Get points based on link orientation\n\t\tlet pointLeft = points[0];\n\t\tlet pointRight = points[points.length - 1];\n\t\tlet hadToSwitch = false;\n\t\tif (pointLeft.getX() > pointRight.getX()) {\n\t\t\tpointLeft = points[points.length - 1];\n\t\t\tpointRight = points[0];\n\t\t\thadToSwitch = true;\n\t\t}\n\t\tlet dy = Math.abs(points[0].getY() - points[points.length - 1].getY());\n\n\t\t// When new link add one middle point to get everywhere 90° angle\n\t\tif (this.props.link.getTargetPort() === null && points.length === 2) {\n\t\t\t[...Array(2)].forEach((item) => {\n\t\t\t\tthis.props.link.addPoint(\n\t\t\t\t\tnew PointModel({\n\t\t\t\t\t\tlink: this.props.link,\n\t\t\t\t\t\tposition: new Point(pointLeft.getX(), pointRight.getY())\n\t\t\t\t\t}),\n\t\t\t\t\t1\n\t\t\t\t);\n\t\t\t});\n\t\t\tthis.props.link.setManuallyFirstAndLastPathsDirection(true, true);\n\t\t}\n\t\t// When new link is moving and not connected to target port move with middle point\n\t\t// TODO: @DanielLazarLDAPPS This will be better to update in DragNewLinkState\n\t\t//  in function fireMouseMoved to avoid calling this unexpectedly e.g. after Deserialize\n\t\telse if (this.props.link.getTargetPort() === null && this.props.link.getSourcePort() !== null) {\n\t\t\tpoints[1].setPosition(\n\t\t\t\tpointRight.getX() + (pointLeft.getX() - pointRight.getX()) / 2,\n\t\t\t\t!hadToSwitch ? pointLeft.getY() : pointRight.getY()\n\t\t\t);\n\t\t\tpoints[2].setPosition(\n\t\t\t\tpointRight.getX() + (pointLeft.getX() - pointRight.getX()) / 2,\n\t\t\t\t!hadToSwitch ? pointRight.getY() : pointLeft.getY()\n\t\t\t);\n\t\t}\n\t\t// Render was called but link is not moved but user.\n\t\t// Node is moved and in this case fix coordinates to get 90° angle.\n\t\t// For loop just for first and last path\n\t\telse if (!this.state.canDrag && points.length > 2) {\n\t\t\t// Those points and its position only will be moved\n\t\t\tfor (let i = 1; i < points.length; i += points.length - 2) {\n\t\t\t\tif (i - 1 === 0) {\n\t\t\t\t\tif (this.props.link.getFirstPathXdirection()) {\n\t\t\t\t\t\tpoints[i].setPosition(points[i].getX(), points[i - 1].getY());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpoints[i].setPosition(points[i - 1].getX(), points[i].getY());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (this.props.link.getLastPathXdirection()) {\n\t\t\t\t\t\tpoints[i - 1].setPosition(points[i - 1].getX(), points[i].getY());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpoints[i - 1].setPosition(points[i].getX(), points[i - 1].getY());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If there is existing link which has two points add one\n\t\t// NOTE: It doesn't matter if check is for dy or dx\n\t\tif (points.length === 2 && dy !== 0 && !this.state.canDrag) {\n\t\t\tthis.props.link.addPoint(\n\t\t\t\tnew PointModel({\n\t\t\t\t\tlink: this.props.link,\n\t\t\t\t\tposition: new Point(pointLeft.getX(), pointRight.getY())\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tfor (let j = 0; j < points.length - 1; j++) {\n\t\t\tpaths.push(\n\t\t\t\tthis.generateLink(\n\t\t\t\t\tLinkWidget.generateLinePath(points[j], points[j + 1]),\n\t\t\t\t\t{\n\t\t\t\t\t\t'data-linkid': this.props.link.getID(),\n\t\t\t\t\t\t'data-point': j,\n\t\t\t\t\t\tonMouseDown: (event: MouseEvent) => {\n\t\t\t\t\t\t\tif (event.button === 0) {\n\t\t\t\t\t\t\t\tthis.setState({ canDrag: true });\n\t\t\t\t\t\t\t\tthis.dragging_index = j;\n\t\t\t\t\t\t\t\t// Register mouse move event to track mouse position\n\t\t\t\t\t\t\t\t// On mouse up these events are unregistered check \"this.handleUp\"\n\t\t\t\t\t\t\t\twindow.addEventListener('mousemove', this.handleMove);\n\t\t\t\t\t\t\t\twindow.addEventListener('mouseup', this.handleUp);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonMouseEnter: (event: MouseEvent) => {\n\t\t\t\t\t\t\tthis.setState({ selected: true });\n\t\t\t\t\t\t\tthis.props.link.lastHoverIndexOfPath = j;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tj\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn <g data-default-link-test={this.props.link.getOptions().testName}>{paths}</g>;\n\t}\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/tests/PathFinding.test.tsx",
    "content": "import { PathFinding } from '../src/engine/PathFinding';\n\ndescribe('calculating start and end points', function () {\n\tlet pathFinding: PathFinding = new PathFinding(null);\n\n\tbeforeEach(() => {\n\t\tpathFinding = new PathFinding(null);\n\t});\n\n\ttest('return correct object for valid walkable input', () => {\n\t\tconst matrix = [\n\t\t\t[0, 0, 0, 0, 1, 1],\n\t\t\t[0, 0, 0, 0, 1, 1],\n\t\t\t[0, 0, 0, 0, 0, 0],\n\t\t\t[0, 0, 0, 0, 0, 0],\n\t\t\t[1, 1, 0, 0, 0, 0],\n\t\t\t[1, 1, 0, 0, 0, 0]\n\t\t];\n\t\tconst path = [\n\t\t\t[0, 5],\n\t\t\t[1, 4],\n\t\t\t[2, 3],\n\t\t\t[3, 2],\n\t\t\t[4, 1],\n\t\t\t[5, 0]\n\t\t];\n\n\t\tconst result = pathFinding.calculateLinkStartEndCoords(matrix, path);\n\n\t\texpect(result.start).toEqual({\n\t\t\tx: 2,\n\t\t\ty: 3\n\t\t});\n\t\texpect(result.end).toEqual({\n\t\t\tx: 3,\n\t\t\ty: 2\n\t\t});\n\t\texpect(result.pathToStart).toEqual([\n\t\t\t[0, 5],\n\t\t\t[1, 4]\n\t\t]);\n\t\texpect(result.pathToEnd).toEqual([\n\t\t\t[3, 2],\n\t\t\t[4, 1],\n\t\t\t[5, 0]\n\t\t]);\n\t});\n\n\ttest('undefined is returned when no walkable path exists', () => {\n\t\tconst matrix = [\n\t\t\t[0, 0, 1, 1],\n\t\t\t[0, 0, 1, 1],\n\t\t\t[1, 1, 0, 0],\n\t\t\t[1, 1, 0, 0]\n\t\t];\n\t\tconst path = [\n\t\t\t[0, 3],\n\t\t\t[1, 2],\n\t\t\t[2, 1],\n\t\t\t[3, 0]\n\t\t];\n\n\t\tconst result = pathFinding.calculateLinkStartEndCoords(matrix, path);\n\n\t\texpect(result).toBeUndefined();\n\t});\n});\n"
  },
  {
    "path": "packages/react-diagrams-routing/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.base.json\",\n\t\"compilerOptions\": {\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"outDir\": \"dist\",\n\t\t\"rootDir\": \"src\",\n\t\t\"declarationDir\": \"dist/@types\",\n\t\t\"tsBuildInfoFile\": \"dist/tsconfig.tsbuildinfo\"\n\t},\n\t\"include\": [\"./src\"],\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"../geometry\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"../react-canvas-core\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"../react-diagrams-defaults\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "packages/react-diagrams-routing/webpack.config.js",
    "content": "const config = require('../../webpack.shared')(__dirname);\nmodule.exports = {\n\t...config,\n\toutput: {\n\t\t...config.output,\n\t\tlibrary: 'projectstorm/react-diagrams-routing'\n\t}\n};\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/*'\n  - 'diagrams-demo-gallery'\n  - 'diagrams-demo-project'"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n\t\"compileOnSave\": false,\n\t\"compilerOptions\": {\n\t\t\"declaration\": true,\n\t\t\"composite\": true,\n\t\t\"incremental\": true,\n\t\t\"strictNullChecks\": false,\n\t\t\"sourceMap\": true,\n\t\t\"inlineSources\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"jsx\": \"react\",\n\t\t\"target\": \"ES6\",\n\t\t\"moduleResolution\": \"Node\",\n\t\t\"module\": \"es6\",\n\t\t\"strict\": false,\n\t\t\"lib\": [\n\t\t\t\"DOM\",\n\t\t\t\"ES6\"\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n\t\"files\": [],\n\t\"references\": [\n\t\t{\n\t\t\t\"path\": \"./packages/geometry\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"./packages/react-canvas-core\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"./packages/react-diagrams\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"./packages/react-diagrams-core\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"./packages/react-diagrams-defaults\"\n\t\t},\n\t\t{\n\t\t\t\"path\": \"./packages/react-diagrams-routing\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "webpack.shared.js",
    "content": "const production = process.env.NODE_ENV === 'production';\nconst TerserPlugin = require('terser-webpack-plugin');\nconst nodeExternals = require('webpack-node-externals');\nconst path = require('path');\n\nmodule.exports = (directory) => {\n\treturn {\n\t\tentry: path.join(directory, './dist/index.js'),\n\t\toutput: {\n\t\t\tfilename: 'index.umd.js',\n\t\t\tpath: path.join(directory, 'dist'),\n\t\t\tlibraryTarget: 'umd'\n\t\t},\n\t\texternals: [\n\t\t\tnodeExternals({ modulesDir: path.join(directory, 'node_modules') }),\n\t\t\tnodeExternals({ modulesDir: path.join(__dirname, 'node_modules') })\n\t\t],\n\t\tmodule: {\n\t\t\trules: [\n\t\t\t\t{\n\t\t\t\t\tenforce: 'pre',\n\t\t\t\t\ttest: /\\.js$/,\n\t\t\t\t\tloader: 'source-map-loader'\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresolve: {\n\t\t\textensions: ['.tsx', '.ts', '.js']\n\t\t},\n\t\tdevtool: production ? 'source-map' : 'cheap-module-source-map',\n\t\tmode: production ? 'production' : 'development',\n\t\toptimization: {\n\t\t\tminimizer: [new TerserPlugin()]\n\t\t}\n\t};\n};\n"
  }
]