├── .browserslistrc ├── .eslintignore ├── .eslintrc.js ├── .github ├── dependabot.yml └── workflows │ └── run-tests.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── babel.config.js ├── docs ├── .vuepress │ ├── config.yml │ └── public │ │ ├── favicon.ico │ │ ├── logo.png │ │ ├── screenshot-eddy.png │ │ └── screenshot.png ├── api │ ├── events.md │ ├── index.md │ ├── props.md │ └── slots.md ├── guide │ ├── index.md │ └── installation.md └── index.md ├── jest.config.js ├── package.json ├── postcss.config.js ├── public └── index.html ├── src ├── App.vue ├── ExampleNode.vue ├── VueDag.vue ├── __tests__ │ ├── App.spec.ts │ └── __snapshots__ │ │ └── App.spec.ts.snap ├── components │ ├── DAGContainer │ │ ├── DAGContainer.vue │ │ ├── __tests__ │ │ │ ├── DAGContainer.spec.ts │ │ │ └── __snapshots__ │ │ │ │ └── DAGContainer.spec.ts.snap │ │ └── index.ts │ ├── DAGEdge │ │ ├── DAGEdge.vue │ │ ├── __tests__ │ │ │ ├── DAGEdge.ts │ │ │ └── __snapshots__ │ │ │ │ └── DAGEdge.ts.snap │ │ └── index.ts │ └── DAGNode │ │ ├── DAGNode.vue │ │ ├── __tests__ │ │ ├── DAGNode.ts │ │ └── __snapshots__ │ │ │ └── DAGNode.ts.snap │ │ └── index.ts ├── index.ts ├── main.ts ├── scss │ └── vue-dag.scss └── shims-vue.d.ts ├── tsconfig.json ├── types └── index.d.ts └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | last 1 version 2 | > 1% 3 | maintained node versions 4 | not dead -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | index.html -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: ['plugin:vue/recommended', '@vue/prettier', '@vue/typescript'], 7 | rules: { 8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 10 | 'prettier/prettier': [ 11 | 'error', 12 | { 13 | printWidth: 100, 14 | singleQuote: true, 15 | trailingComma: 'all', 16 | htmlWhitespaceSensitivity: 'ignore', 17 | }, 18 | ], 19 | }, 20 | parserOptions: { 21 | parser: '@typescript-eslint/parser', 22 | }, 23 | overrides: [ 24 | { 25 | files: ['**/__tests__/*.{j,t}s?(x)'], 26 | env: { 27 | jest: true, 28 | }, 29 | }, 30 | ], 31 | }; 32 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: core-js 11 | versions: 12 | - 3.10.2 13 | - 3.11.0 14 | - 3.9.0 15 | - dependency-name: typescript 16 | versions: 17 | - 4.1.3 18 | - 4.1.4 19 | - 4.1.5 20 | - 4.2.2 21 | - 4.2.4 22 | - dependency-name: eslint-plugin-vue 23 | versions: 24 | - 7.5.0 25 | - 7.6.0 26 | - 7.7.0 27 | - dependency-name: sass-loader 28 | versions: 29 | - 11.0.0 30 | - 11.0.1 31 | - dependency-name: "@vue/cli-plugin-babel" 32 | versions: 33 | - 4.5.11 34 | - dependency-name: ts-jest 35 | versions: 36 | - 26.5.0 37 | - 26.5.1 38 | - 26.5.2 39 | - dependency-name: vuepress 40 | versions: 41 | - 1.8.1 42 | - 1.8.2 43 | - dependency-name: "@vue/test-utils" 44 | versions: 45 | - 1.1.2 46 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: run-tests 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [8.x, 10.x, 12.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: Install dependencies 21 | run: | 22 | npm install 23 | env: 24 | CI: true 25 | - name: Run Jest unit tests 26 | run: | 27 | npm run test:unit 28 | env: 29 | CI: true 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | # Docs build 24 | docs/.vuepress/dist 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alexandru-Ionut Imbrea 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🏗Vue DAG Builder 2 | 3 | > Data-driven directed acyclic graph (DAG) visual builder for Vue.js 4 | 5 | [![GitHub Actions](https://github.com/aleximb/vue-dag/workflows/run-tests/badge.svg)](https://github.com/aleximb/vue-dag/actions) [![Netlify Status](https://api.netlify.com/api/v1/badges/377debe3-712c-40c8-a4a8-2909fff31db4/deploy-status)](https://app.netlify.com/sites/vue-dag/deploys) 6 | [![npm](https://img.shields.io/npm/v/vue-dag.svg) ![npm](https://img.shields.io/npm/dm/vue-dag.svg)](https://www.npmjs.com/package/vue-dag) 7 | [![vue2](https://img.shields.io/badge/vue-2+-brightgreen.svg)](https://vuejs.org/) 8 | ![GitHub](https://img.shields.io/github/license/aleximb/vue-dag.svg) 9 | 10 | ## Examples 11 | 12 | [vue-dag-example.netlify.app](https://vue-dag-example.netlify.app/) 13 | 14 | ![Screenshot](docs/.vuepress/public/screenshot.png) 15 | 16 | [eddy-analytics.org](https://eddy-analytics.org) 17 | 18 | ![Screenshot Eddy](docs/.vuepress/public/screenshot-eddy.png) 19 | 20 | 21 | ## Installation 22 | 23 | ```bash 24 | npm install --save vue-dag 25 | ``` 26 | or 27 | ```bash 28 | yarn add vue-dag 29 | ``` 30 | 31 | Import and register the component 32 | ```js 33 | import VueDag from 'vue-dag'; 34 | ``` 35 | 36 | ```js 37 | components: { 38 | VueDag 39 | } 40 | ``` 41 | 42 | Use it in templates 43 | ```html 44 | 45 | ``` 46 | 47 | The component does not include any CSS. You'll need to import it separately: 48 | ```js 49 | import 'vue-dag/dist/vue-dag.css'; 50 | ``` 51 | 52 | Alternatively, you can import the SCSS version and overrite variables and styles 53 | ```scss 54 | @import 'vue-dag/src/scss/vue-dag.scss'; 55 | ``` 56 | 57 | Full documentation: [https://vue-dag.netlify.com/](https://vue-dag.netlify.com/) 58 | 59 | 60 | 61 | ## Project development setup 62 | 63 | 64 | ### Installs dependencies 65 | ``` 66 | yarn install 67 | ``` 68 | 69 | ### Compiles and hot-reloads for development 70 | ``` 71 | yarn run serve 72 | ``` 73 | 74 | ### Lints and fixes files 75 | ``` 76 | yarn run lint 77 | ``` 78 | 79 | ### Runs unit tests 80 | ``` 81 | yarn run test:unit 82 | ``` 83 | 84 | ### Builds as library 85 | ``` 86 | yarn run build:library 87 | ``` 88 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/app'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/.vuepress/config.yml: -------------------------------------------------------------------------------- 1 | title: 'Vue DAG' 2 | base: '/' 3 | serviceWorker: true 4 | themeConfig: 5 | repo: 'AlexImb/vue-dag' 6 | docsDir: 'docs' 7 | editLinks: true 8 | serviceWorker: 9 | updatePopup: true 10 | nav: 11 | - text: Home 12 | link: '/' 13 | - text: Guide 14 | link: '/guide/installation' 15 | - text: API 16 | link: '/api/' 17 | - text: Demo 18 | link: 'https://vue-dag-example.netlify.app' 19 | sidebarDepth: 2, 20 | sidebar: 21 | - '/guide/': 22 | title: 'Guide' 23 | collapsable: false 24 | children: 25 | - 26 | - 'guide/installation' 27 | - 'Installation' 28 | - '/api/': 29 | title: 'API' 30 | collapsable: false 31 | children: 32 | - 33 | - 'api/props' 34 | - 'Props' 35 | - 36 | - 'api/events' 37 | - 'Events' 38 | - 39 | - 'api/slots' 40 | - 'Slots' 41 | 42 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexImb/vue-dag/42ae5a47bab6ca15287a40c2af87fd8f08be8dc6/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexImb/vue-dag/42ae5a47bab6ca15287a40c2af87fd8f08be8dc6/docs/.vuepress/public/logo.png -------------------------------------------------------------------------------- /docs/.vuepress/public/screenshot-eddy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexImb/vue-dag/42ae5a47bab6ca15287a40c2af87fd8f08be8dc6/docs/.vuepress/public/screenshot-eddy.png -------------------------------------------------------------------------------- /docs/.vuepress/public/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexImb/vue-dag/42ae5a47bab6ca15287a40c2af87fd8f08be8dc6/docs/.vuepress/public/screenshot.png -------------------------------------------------------------------------------- /docs/api/events.md: -------------------------------------------------------------------------------- 1 | # Events -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | # API -------------------------------------------------------------------------------- /docs/api/props.md: -------------------------------------------------------------------------------- 1 | # Props -------------------------------------------------------------------------------- /docs/api/slots.md: -------------------------------------------------------------------------------- 1 | # Slots -------------------------------------------------------------------------------- /docs/guide/index.md: -------------------------------------------------------------------------------- 1 | # Guide -------------------------------------------------------------------------------- /docs/guide/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ```bash 4 | npm install --save vue-dag 5 | ``` 6 | or 7 | ```bash 8 | yarn add vue-dag 9 | ``` 10 | 11 | Import and register the component 12 | ```js 13 | import VueDag from 'vue-dag'; 14 | ``` 15 | 16 | ```js 17 | components: { 18 | VueDag 19 | } 20 | ``` 21 | 22 | Use it in templates 23 | ```html 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | description: '🏗Directed acyclic graph (DAG) builder for Vue.js' 4 | heroImage: /logo.png 5 | actionText: Get Started → 6 | actionLink: /guide/installation 7 | features: 8 | - title: Data-driven 9 | details: Specify the model of the DAG as JSON and keep it in sync all the time. 10 | - title: Customizable 11 | details: Use custom style rules and slots content for complete customization. 12 | - title: Event-based 13 | details: React to (custom-)events emitted from components or triggered by interactions. 14 | footer: MIT Licensed - Created by Alex Imbrea (@AlexImb) 15 | --- -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue', 'ts', 'tsx'], 3 | transform: { 4 | '^.+\\.vue$': 'vue-jest', 5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', 6 | '^.+\\.tsx?$': 'ts-jest', 7 | }, 8 | transformIgnorePatterns: ['/node_modules/'], 9 | moduleNameMapper: { 10 | '^@/(.*)$': '/src/$1', 11 | }, 12 | snapshotSerializers: ['jest-serializer-vue'], 13 | testMatch: ['**/__tests__/*.(js|jsx|ts|tsx)'], 14 | testURL: 'http://localhost/', 15 | watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'], 16 | globals: { 17 | 'ts-jest': { 18 | babelConfig: true, 19 | }, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-dag", 3 | "version": "0.1.8", 4 | "description": "Directed acyclic graph (DAG) builder for Vue.js", 5 | "main": "dist/vue-dag.umd.js", 6 | "module": "dist/vue-dag.esm.js", 7 | "unpkg": "dist/vue-dag.min.js", 8 | "typings": "types/index.d.ts", 9 | "scripts": { 10 | "serve": "vue-cli-service serve", 11 | "build": "vue-cli-service build --dest demo", 12 | "build:library": "vue-cli-service build --target lib --name vue-dag ./src/index.ts", 13 | "lint": "vue-cli-service lint", 14 | "test:unit": "vue-cli-service test:unit", 15 | "docs:dev": "vuepress dev docs", 16 | "docs:build": "vuepress build docs" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/AlexImb/vue-dag.git" 21 | }, 22 | "keywords": [ 23 | "vue", 24 | "dag", 25 | "builder" 26 | ], 27 | "author": "Alex Imbrea ", 28 | "bugs": { 29 | "url": "https://github.com/AlexImb/vue-dag/issues" 30 | }, 31 | "homepage": "https://github.com/AlexImb/vue-dag", 32 | "license": "MIT", 33 | "devDependencies": { 34 | "@types/jest": "^26.0.10", 35 | "@vue/cli-plugin-babel": "^4.5.12", 36 | "@vue/cli-plugin-eslint": "^4.3.1", 37 | "@vue/cli-plugin-typescript": "^4.4.1", 38 | "@vue/cli-plugin-unit-jest": "^4.5.4", 39 | "@vue/cli-service": "^4.5.6", 40 | "@vue/eslint-config-prettier": "^6.0.0", 41 | "@vue/eslint-config-typescript": "^4.0.0", 42 | "@vue/test-utils": "1.2.0", 43 | "babel-core": "7.0.0-bridge.0", 44 | "babel-eslint": "^10.0.1", 45 | "core-js": "^3.8.3", 46 | "eslint": "^6.8.0", 47 | "eslint-plugin-prettier": "^3.1.0", 48 | "eslint-plugin-vue": "^7.8.0", 49 | "node-sass": "^6.0.0", 50 | "prettier": "^2.1.1", 51 | "sass-loader": "^10.1.1", 52 | "ts-jest": "^26.3.0", 53 | "typescript": "3.9.7", 54 | "vue": "^2.6.10", 55 | "vue-class-component": "^7.0.2", 56 | "vue-property-decorator": "^9.0.0", 57 | "vue-template-compiler": "^2.6.10", 58 | "vuepress": "^1.1.0" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-dag | Dev 9 | 10 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 60 | 61 | 68 | -------------------------------------------------------------------------------- /src/ExampleNode.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /src/VueDag.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 259 | 260 | 263 | -------------------------------------------------------------------------------- /src/__tests__/App.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, Wrapper } from '@vue/test-utils'; 2 | import App from '@/App.vue'; 3 | 4 | let wrapper: Wrapper; 5 | 6 | describe('App', () => { 7 | beforeEach(() => { 8 | wrapper = shallowMount(App); 9 | }); 10 | 11 | it('renders correctly', () => { 12 | expect(wrapper.html()).toMatchSnapshot(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/App.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`App renders correctly 1`] = ` 4 |
5 |
6 |

Vue DAG Demo

7 |
8 |
9 | 10 |
11 |
12 |
13 |
14 | `; 15 | -------------------------------------------------------------------------------- /src/components/DAGContainer/DAGContainer.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /src/components/DAGContainer/__tests__/DAGContainer.spec.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, Wrapper } from '@vue/test-utils'; 2 | import { DAGNode } from '@/components/DAGNode'; 3 | 4 | let wrapper: Wrapper; 5 | 6 | describe('DAGContainer', () => { 7 | beforeEach(() => { 8 | wrapper = shallowMount(DAGNode); 9 | }); 10 | 11 | it('renders correctly', () => { 12 | expect(wrapper.html()).toMatchSnapshot(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/DAGContainer/__tests__/__snapshots__/DAGContainer.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`DAGContainer renders correctly 1`] = ` 4 |
5 | 6 | 7 | 8 | 9 |
Empty node
10 |
11 | `; 12 | -------------------------------------------------------------------------------- /src/components/DAGContainer/index.ts: -------------------------------------------------------------------------------- 1 | import DAGContainer from './DAGContainer.vue'; 2 | 3 | export { DAGContainer }; 4 | -------------------------------------------------------------------------------- /src/components/DAGEdge/DAGEdge.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 84 | -------------------------------------------------------------------------------- /src/components/DAGEdge/__tests__/DAGEdge.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, Wrapper } from '@vue/test-utils'; 2 | import { DAGEdge } from '@/components/DAGEdge'; 3 | 4 | let wrapper: Wrapper; 5 | 6 | describe('DAGEdge', () => { 7 | beforeEach(() => { 8 | wrapper = shallowMount(DAGEdge); 9 | }); 10 | 11 | it('renders correctly', () => { 12 | expect(wrapper.html()).toMatchSnapshot(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/DAGEdge/__tests__/__snapshots__/DAGEdge.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`DAGEdge renders correctly 1`] = ` 4 | 5 | 6 | 7 | 8 | `; 9 | -------------------------------------------------------------------------------- /src/components/DAGEdge/index.ts: -------------------------------------------------------------------------------- 1 | import DAGEdge from './DAGEdge.vue'; 2 | 3 | export { DAGEdge }; 4 | -------------------------------------------------------------------------------- /src/components/DAGNode/DAGNode.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 35 | -------------------------------------------------------------------------------- /src/components/DAGNode/__tests__/DAGNode.ts: -------------------------------------------------------------------------------- 1 | import { shallowMount, Wrapper } from '@vue/test-utils'; 2 | import { DAGNode } from '@/components/DAGNode'; 3 | 4 | let wrapper: Wrapper; 5 | 6 | describe('DAGNode', () => { 7 | beforeEach(() => { 8 | wrapper = shallowMount(DAGNode); 9 | }); 10 | 11 | it('renders correctly', () => { 12 | expect(wrapper.html()).toMatchSnapshot(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/components/DAGNode/__tests__/__snapshots__/DAGNode.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`DAGNode renders correctly 1`] = ` 4 |
5 | 6 | 7 | 8 | 9 |
Empty node
10 |
11 | `; 12 | -------------------------------------------------------------------------------- /src/components/DAGNode/index.ts: -------------------------------------------------------------------------------- 1 | import DAGNode from './DAGNode.vue'; 2 | 3 | export { DAGNode }; 4 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import VueDag from './VueDag.vue'; 2 | export default VueDag; 3 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | 4 | Vue.config.productionTip = false; 5 | 6 | new Vue({ 7 | render: (h) => h(App), 8 | }).$mount('#app'); 9 | -------------------------------------------------------------------------------- /src/scss/vue-dag.scss: -------------------------------------------------------------------------------- 1 | $vd-accent-color: #12c2e9 !default; 2 | $vd-bg-color: #fbfbfb !default; 3 | 4 | $vd-dot-color: #bbb !default; 5 | $vd-dot-size: 2px !default; 6 | $vd-dot-space: 22px !default; 7 | 8 | $vd-node-bg-color: white !default; 9 | $vd-node-box-shadow-color: #ccc !default; 10 | $vd-node-box-shadow: 0 0 4px 0 $vd-node-box-shadow-color !default; 11 | 12 | 13 | .vd__container { 14 | background: linear-gradient(90deg, $vd-bg-color ($vd-dot-space - $vd-dot-size), transparent 1%) center, linear-gradient($vd-bg-color ($vd-dot-space - $vd-dot-size), transparent 1%) center, $vd-dot-color; 15 | background-size: $vd-dot-space $vd-dot-space; 16 | 17 | margin: 0; 18 | position: relative; 19 | overflow: hidden; 20 | height: 100%; 21 | } 22 | 23 | .vd__node { 24 | width: 15rem; 25 | height: 5rem; 26 | background: $vd-node-bg-color; 27 | box-shadow: $vd-node-box-shadow; 28 | 29 | cursor: move; 30 | position: absolute; 31 | transform-origin: top left; 32 | 33 | .vd__node__link { 34 | width: .5rem; 35 | height: .5rem; 36 | position: absolute; 37 | border: .1rem solid $vd-accent-color; 38 | border-radius: 50%; 39 | cursor: pointer; 40 | visibility: hidden; 41 | 42 | &:hover { 43 | background: $vd-accent-color; 44 | } 45 | 46 | &--top { 47 | top: -.4rem; 48 | left: 7.25rem; 49 | } 50 | &--right { 51 | right: -.4rem; 52 | top: 2.25rem; 53 | } 54 | &--bottom { 55 | bottom: -.4rem; 56 | left: 7.25rem; 57 | } 58 | &--left { 59 | left: -.4rem; 60 | top: 2.25rem; 61 | } 62 | } 63 | 64 | &:hover { 65 | .vd__node__link { 66 | visibility: visible; 67 | } 68 | } 69 | 70 | .vd__node__default-content { 71 | text-align: center; 72 | padding-top: 2rem; 73 | } 74 | } -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue'; 3 | export default Vue; 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "noImplicitAny": true, 7 | "removeComments": true, 8 | "jsx": "preserve", 9 | "importHelpers": true, 10 | "moduleResolution": "node", 11 | "experimentalDecorators": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "sourceMap": true, 15 | "baseUrl": ".", 16 | "types": [ 17 | "webpack-env", 18 | "jest" 19 | ], 20 | "paths": { 21 | "@/*": [ 22 | "src/*" 23 | ] 24 | }, 25 | "lib": [ 26 | "esnext", 27 | "dom", 28 | "dom.iterable", 29 | "scripthost" 30 | ] 31 | }, 32 | "include": [ 33 | "src/**/*.ts", 34 | "src/**/*.tsx", 35 | "src/**/*.vue", 36 | "tests/**/*.ts", 37 | "tests/**/*.tsx" 38 | ], 39 | "exclude": [ 40 | "node_modules" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | declare interface GraphConfig { 2 | scale?: number; 3 | height?: string; 4 | width?: string; 5 | } 6 | 7 | declare interface GraphNode { 8 | id: number; 9 | content?: string; 10 | component?: Object; 11 | props?: Object; 12 | x?: number; 13 | y?: number; 14 | } 15 | 16 | declare type GraphLinkPosition = 'top' | 'right' | 'bottom' | 'left'; 17 | 18 | declare interface GraphEdge { 19 | id: number; 20 | content?: string; 21 | from: number; 22 | to: number; 23 | fromLink?: GraphLinkPosition; 24 | toLink?: GraphLinkPosition; 25 | edgeColor?: string; 26 | arrowColor?: string; 27 | } 28 | 29 | declare interface GraphData { 30 | config: GraphConfig; 31 | nodes: GraphNode[]; 32 | edges: GraphEdge[]; 33 | } 34 | 35 | export { GraphData, GraphConfig, GraphEdge, GraphNode, GraphLinkPosition }; 36 | --------------------------------------------------------------------------------