From e6bef4a9f19b28f87277766b08fe3d7b5362412a Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Thu, 28 Jul 2022 00:09:56 +0200 Subject: [PATCH] docs: use vitepress --- docs2/.gitignore | 2 + docs2/components/Repl.vue | 110 +++ docs2/components/examples/basic/App.vue | 84 ++ docs2/components/examples/basic/index.ts | 3 + .../examples/basic/initial-elements.js | 25 + docs2/components/examples/basic/style.css | 30 + .../examples/connectionline/App.vue | 24 + .../connectionline/CustomConnectionLine.vue | 33 + .../examples/connectionline/index.ts | 2 + docs2/components/examples/custom-node/App.vue | 117 +++ .../examples/custom-node/CustomNode.vue | 59 ++ .../components/examples/custom-node/index.ts | 4 + .../examples/custom-node/presets.js | 23 + .../components/examples/custom-node/style.css | 73 ++ docs2/components/examples/dnd/App.vue | 45 + docs2/components/examples/dnd/Sidebar.vue | 19 + docs2/components/examples/dnd/index.ts | 3 + docs2/components/examples/dnd/style.css | 51 ++ docs2/components/examples/edges/App.vue | 74 ++ .../components/examples/edges/CustomEdge.vue | 100 +++ .../components/examples/edges/CustomEdge2.vue | 97 +++ .../examples/edges/CustomEdgeLabel.vue | 12 + docs2/components/examples/edges/index.ts | 5 + docs2/components/examples/edges/style.css | 10 + docs2/components/examples/empty/App.vue | 31 + docs2/components/examples/empty/index.ts | 1 + docs2/components/examples/hidden/App.vue | 41 + docs2/components/examples/hidden/index.ts | 1 + docs2/components/examples/horizontal/App.vue | 27 + docs2/components/examples/horizontal/index.ts | 2 + .../examples/horizontal/initial-elements.js | 38 + docs2/components/examples/index.ts | 100 +++ docs2/components/examples/interaction/App.vue | 20 + .../interaction/InteractionControls.vue | 110 +++ .../components/examples/interaction/index.ts | 3 + .../components/examples/interaction/style.css | 22 + docs2/components/examples/multi/App.vue | 10 + docs2/components/examples/multi/Flow.vue | 36 + docs2/components/examples/multi/index.ts | 3 + docs2/components/examples/multi/style.css | 18 + docs2/components/examples/nested/App.vue | 93 ++ docs2/components/examples/nested/index.ts | 1 + .../examples/pinia/PiniaExample.vue | 23 + .../components/examples/save-restore/App.vue | 13 + .../examples/save-restore/Controls.vue | 40 + .../components/examples/save-restore/index.ts | 3 + .../examples/save-restore/style.css | 25 + docs2/components/examples/stress/App.vue | 42 + docs2/components/examples/stress/index.ts | 3 + docs2/components/examples/stress/style.css | 4 + docs2/components/examples/stress/utils.js | 40 + docs2/components/examples/teleport/App.vue | 46 + .../components/examples/teleport/Sidebar.vue | 10 + .../examples/teleport/TeleportableNode.vue | 40 + docs2/components/examples/teleport/index.ts | 5 + docs2/components/examples/teleport/style.css | 125 +++ .../examples/teleport/useTransition.js | 107 +++ docs2/components/examples/update-edge/App.vue | 47 + .../components/examples/update-edge/index.ts | 1 + docs2/components/examples/update-node/App.vue | 48 + .../components/examples/update-node/index.ts | 2 + .../components/examples/update-node/style.css | 30 + docs2/components/examples/validation/App.vue | 47 + .../examples/validation/CustomInput.vue | 21 + .../examples/validation/CustomNode.vue | 25 + docs2/components/examples/validation/index.ts | 4 + .../components/examples/validation/style.css | 31 + docs2/components/home/Acknowledgement.vue | 27 + docs2/components/home/Banner.vue | 31 + docs2/components/home/Features.vue | 56 ++ docs2/components/home/Home.vue | 83 ++ docs2/components/home/edges/Custom.vue | 57 ++ docs2/components/home/flows/Additional.vue | 112 +++ docs2/components/home/flows/Basic.vue | 143 +++ docs2/components/home/flows/Intro.vue | 451 ++++++++++ docs2/components/home/flows/Nested.vue | 85 ++ docs2/components/home/flows/RGB.vue | 114 +++ docs2/components/home/flows/confetti.ts | 69 ++ docs2/components/home/nodes/Input.vue | 46 + docs2/components/home/nodes/Output.vue | 21 + docs2/package.json | 37 + docs2/src/.vitepress/auto-imports.d.ts | 248 ++++++ docs2/src/.vitepress/components.d.ts | 13 + docs2/src/.vitepress/config.ts | 154 ++++ docs2/src/.vitepress/copy-plugin.ts | 21 + docs2/src/.vitepress/head.ts | 132 +++ docs2/src/.vitepress/theme/index.ts | 12 + .../src/.vitepress/theme/layouts/default.vue | 83 ++ docs2/src/.vitepress/windi.config.ts | 73 ++ docs2/src/assets/index.css | 111 +++ docs2/src/assets/polygon-scatter.svg | 1 + docs2/src/examples/dnd.md | 24 + docs2/src/examples/edges/connection-line.md | 19 + docs2/src/examples/edges/index.md | 17 + docs2/src/examples/edges/updatable-edge.md | 22 + docs2/src/examples/edges/validation.md | 39 + docs2/src/examples/empty.md | 17 + docs2/src/examples/floating-edges.md | 25 + docs2/src/examples/hidden.md | 24 + docs2/src/examples/horizontal.md | 19 + docs2/src/examples/index.md | 19 + docs2/src/examples/interaction.md | 18 + docs2/src/examples/multi.md | 18 + docs2/src/examples/nodes/index.md | 19 + docs2/src/examples/nodes/nesting.md | 20 + docs2/src/examples/nodes/update-node.md | 22 + docs2/src/examples/pinia.md | 15 + docs2/src/examples/save.md | 25 + docs2/src/examples/stress.md | 18 + docs2/src/examples/teleport.md | 16 + docs2/src/guide/components/background.md | 29 + docs2/src/guide/components/control-button.md | 26 + docs2/src/guide/components/controls.md | 59 ++ docs2/src/guide/components/minimap-node.md | 42 + docs2/src/guide/components/minimap.md | 30 + docs2/src/guide/composables.md | 125 +++ docs2/src/guide/edge.md | 423 +++++++++ docs2/src/guide/getting-started.md | 100 +++ docs2/src/guide/index.md | 40 + docs2/src/guide/node.md | 460 ++++++++++ docs2/src/guide/theming.md | 153 ++++ docs2/src/guide/utils/edge.md | 62 ++ docs2/src/guide/utils/graph.md | 179 ++++ docs2/src/guide/utils/instance.md | 165 ++++ docs2/src/guide/vue-flow/config.md | 824 ++++++++++++++++++ docs2/src/guide/vue-flow/slots.md | 42 + docs2/src/guide/vue-flow/state.md | 157 ++++ docs2/src/index.md | 20 + .../favicons/android-chrome-192x192.png | Bin 0 -> 5725 bytes .../favicons/android-chrome-512x512.png | Bin 0 -> 17490 bytes .../src/public/favicons/apple-touch-icon.png | Bin 0 -> 5132 bytes docs2/src/public/favicons/favicon-16x16.png | Bin 0 -> 375 bytes docs2/src/public/favicons/favicon-32x32.png | Bin 0 -> 744 bytes docs2/src/public/favicons/favicon.ico | Bin 0 -> 15406 bytes docs2/src/public/favicons/site.webmanifest | 21 + docs2/tsconfig.json | 23 + docs2/tsconfig.node.json | 8 + docs2/typedoc.json | 13 + pnpm-lock.yaml | 244 ++++++ pnpm-workspace.yaml | 1 + 140 files changed, 8166 insertions(+) create mode 100644 docs2/.gitignore create mode 100644 docs2/components/Repl.vue create mode 100644 docs2/components/examples/basic/App.vue create mode 100644 docs2/components/examples/basic/index.ts create mode 100644 docs2/components/examples/basic/initial-elements.js create mode 100644 docs2/components/examples/basic/style.css create mode 100644 docs2/components/examples/connectionline/App.vue create mode 100644 docs2/components/examples/connectionline/CustomConnectionLine.vue create mode 100644 docs2/components/examples/connectionline/index.ts create mode 100644 docs2/components/examples/custom-node/App.vue create mode 100644 docs2/components/examples/custom-node/CustomNode.vue create mode 100644 docs2/components/examples/custom-node/index.ts create mode 100644 docs2/components/examples/custom-node/presets.js create mode 100644 docs2/components/examples/custom-node/style.css create mode 100644 docs2/components/examples/dnd/App.vue create mode 100644 docs2/components/examples/dnd/Sidebar.vue create mode 100644 docs2/components/examples/dnd/index.ts create mode 100644 docs2/components/examples/dnd/style.css create mode 100644 docs2/components/examples/edges/App.vue create mode 100644 docs2/components/examples/edges/CustomEdge.vue create mode 100644 docs2/components/examples/edges/CustomEdge2.vue create mode 100644 docs2/components/examples/edges/CustomEdgeLabel.vue create mode 100644 docs2/components/examples/edges/index.ts create mode 100644 docs2/components/examples/edges/style.css create mode 100644 docs2/components/examples/empty/App.vue create mode 100644 docs2/components/examples/empty/index.ts create mode 100644 docs2/components/examples/hidden/App.vue create mode 100644 docs2/components/examples/hidden/index.ts create mode 100644 docs2/components/examples/horizontal/App.vue create mode 100644 docs2/components/examples/horizontal/index.ts create mode 100644 docs2/components/examples/horizontal/initial-elements.js create mode 100644 docs2/components/examples/index.ts create mode 100644 docs2/components/examples/interaction/App.vue create mode 100644 docs2/components/examples/interaction/InteractionControls.vue create mode 100644 docs2/components/examples/interaction/index.ts create mode 100644 docs2/components/examples/interaction/style.css create mode 100644 docs2/components/examples/multi/App.vue create mode 100644 docs2/components/examples/multi/Flow.vue create mode 100644 docs2/components/examples/multi/index.ts create mode 100644 docs2/components/examples/multi/style.css create mode 100644 docs2/components/examples/nested/App.vue create mode 100644 docs2/components/examples/nested/index.ts create mode 100644 docs2/components/examples/pinia/PiniaExample.vue create mode 100644 docs2/components/examples/save-restore/App.vue create mode 100644 docs2/components/examples/save-restore/Controls.vue create mode 100644 docs2/components/examples/save-restore/index.ts create mode 100644 docs2/components/examples/save-restore/style.css create mode 100644 docs2/components/examples/stress/App.vue create mode 100644 docs2/components/examples/stress/index.ts create mode 100644 docs2/components/examples/stress/style.css create mode 100644 docs2/components/examples/stress/utils.js create mode 100644 docs2/components/examples/teleport/App.vue create mode 100644 docs2/components/examples/teleport/Sidebar.vue create mode 100644 docs2/components/examples/teleport/TeleportableNode.vue create mode 100644 docs2/components/examples/teleport/index.ts create mode 100644 docs2/components/examples/teleport/style.css create mode 100644 docs2/components/examples/teleport/useTransition.js create mode 100644 docs2/components/examples/update-edge/App.vue create mode 100644 docs2/components/examples/update-edge/index.ts create mode 100644 docs2/components/examples/update-node/App.vue create mode 100644 docs2/components/examples/update-node/index.ts create mode 100644 docs2/components/examples/update-node/style.css create mode 100644 docs2/components/examples/validation/App.vue create mode 100644 docs2/components/examples/validation/CustomInput.vue create mode 100644 docs2/components/examples/validation/CustomNode.vue create mode 100644 docs2/components/examples/validation/index.ts create mode 100644 docs2/components/examples/validation/style.css create mode 100644 docs2/components/home/Acknowledgement.vue create mode 100644 docs2/components/home/Banner.vue create mode 100644 docs2/components/home/Features.vue create mode 100644 docs2/components/home/Home.vue create mode 100644 docs2/components/home/edges/Custom.vue create mode 100644 docs2/components/home/flows/Additional.vue create mode 100644 docs2/components/home/flows/Basic.vue create mode 100644 docs2/components/home/flows/Intro.vue create mode 100644 docs2/components/home/flows/Nested.vue create mode 100644 docs2/components/home/flows/RGB.vue create mode 100644 docs2/components/home/flows/confetti.ts create mode 100644 docs2/components/home/nodes/Input.vue create mode 100644 docs2/components/home/nodes/Output.vue create mode 100644 docs2/package.json create mode 100644 docs2/src/.vitepress/auto-imports.d.ts create mode 100644 docs2/src/.vitepress/components.d.ts create mode 100644 docs2/src/.vitepress/config.ts create mode 100644 docs2/src/.vitepress/copy-plugin.ts create mode 100644 docs2/src/.vitepress/head.ts create mode 100644 docs2/src/.vitepress/theme/index.ts create mode 100644 docs2/src/.vitepress/theme/layouts/default.vue create mode 100644 docs2/src/.vitepress/windi.config.ts create mode 100644 docs2/src/assets/index.css create mode 100644 docs2/src/assets/polygon-scatter.svg create mode 100644 docs2/src/examples/dnd.md create mode 100644 docs2/src/examples/edges/connection-line.md create mode 100644 docs2/src/examples/edges/index.md create mode 100644 docs2/src/examples/edges/updatable-edge.md create mode 100644 docs2/src/examples/edges/validation.md create mode 100644 docs2/src/examples/empty.md create mode 100644 docs2/src/examples/floating-edges.md create mode 100644 docs2/src/examples/hidden.md create mode 100644 docs2/src/examples/horizontal.md create mode 100644 docs2/src/examples/index.md create mode 100644 docs2/src/examples/interaction.md create mode 100644 docs2/src/examples/multi.md create mode 100644 docs2/src/examples/nodes/index.md create mode 100644 docs2/src/examples/nodes/nesting.md create mode 100644 docs2/src/examples/nodes/update-node.md create mode 100644 docs2/src/examples/pinia.md create mode 100644 docs2/src/examples/save.md create mode 100644 docs2/src/examples/stress.md create mode 100644 docs2/src/examples/teleport.md create mode 100644 docs2/src/guide/components/background.md create mode 100644 docs2/src/guide/components/control-button.md create mode 100644 docs2/src/guide/components/controls.md create mode 100644 docs2/src/guide/components/minimap-node.md create mode 100644 docs2/src/guide/components/minimap.md create mode 100644 docs2/src/guide/composables.md create mode 100644 docs2/src/guide/edge.md create mode 100644 docs2/src/guide/getting-started.md create mode 100644 docs2/src/guide/index.md create mode 100644 docs2/src/guide/node.md create mode 100644 docs2/src/guide/theming.md create mode 100644 docs2/src/guide/utils/edge.md create mode 100644 docs2/src/guide/utils/graph.md create mode 100644 docs2/src/guide/utils/instance.md create mode 100644 docs2/src/guide/vue-flow/config.md create mode 100644 docs2/src/guide/vue-flow/slots.md create mode 100644 docs2/src/guide/vue-flow/state.md create mode 100644 docs2/src/index.md create mode 100644 docs2/src/public/favicons/android-chrome-192x192.png create mode 100644 docs2/src/public/favicons/android-chrome-512x512.png create mode 100644 docs2/src/public/favicons/apple-touch-icon.png create mode 100644 docs2/src/public/favicons/favicon-16x16.png create mode 100644 docs2/src/public/favicons/favicon-32x32.png create mode 100644 docs2/src/public/favicons/favicon.ico create mode 100644 docs2/src/public/favicons/site.webmanifest create mode 100644 docs2/tsconfig.json create mode 100644 docs2/tsconfig.node.json create mode 100644 docs2/typedoc.json diff --git a/docs2/.gitignore b/docs2/.gitignore new file mode 100644 index 00000000..34a44fc0 --- /dev/null +++ b/docs2/.gitignore @@ -0,0 +1,2 @@ +.data.json +.temp diff --git a/docs2/components/Repl.vue b/docs2/components/Repl.vue new file mode 100644 index 00000000..98708f4e --- /dev/null +++ b/docs2/components/Repl.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/docs2/components/examples/basic/App.vue b/docs2/components/examples/basic/App.vue new file mode 100644 index 00000000..31c05328 --- /dev/null +++ b/docs2/components/examples/basic/App.vue @@ -0,0 +1,84 @@ + + + diff --git a/docs2/components/examples/basic/index.ts b/docs2/components/examples/basic/index.ts new file mode 100644 index 00000000..05bd1883 --- /dev/null +++ b/docs2/components/examples/basic/index.ts @@ -0,0 +1,3 @@ +export { default as BasicApp } from './App.vue?raw' +export { default as BasicElements } from './initial-elements.js?raw' +export { default as BasicCSS } from './style.css' diff --git a/docs2/components/examples/basic/initial-elements.js b/docs2/components/examples/basic/initial-elements.js new file mode 100644 index 00000000..68f5e14d --- /dev/null +++ b/docs2/components/examples/basic/initial-elements.js @@ -0,0 +1,25 @@ +import { MarkerType } from '@braks/vue-flow' + +/** + * You can pass elements together as a v-model value + * or split them up into nodes and edges and pass them to the `nodes` and `edges` props of Vue Flow (or useVueFlow composable) + */ +export const initialElements = [ + { id: '1', type: 'input', label: 'Node 1', position: { x: 250, y: 5 }, class: 'light' }, + { id: '2', type: 'output', label: 'Node 2', position: { x: 100, y: 100 }, class: 'light' }, + { id: '3', label: 'Node 3', position: { x: 400, y: 100 }, class: 'light' }, + { id: '4', label: 'Node 4', position: { x: 150, y: 200 }, class: 'light' }, + { id: '5', type: 'output', label: 'Node 5', position: { x: 300, y: 300 }, class: 'light' }, + { id: 'e1-2', source: '1', target: '2', animated: true }, + { id: 'e1-3', label: 'edge with arrowhead', source: '1', target: '3', markerEnd: MarkerType.Arrow }, + { + id: 'e4-5', + type: 'step', + label: 'step-edge', + source: '4', + target: '5', + style: { stroke: 'orange' }, + labelBgStyle: { fill: 'orange' }, + }, + { id: 'e3-4', type: 'smoothstep', label: 'smoothstep-edge', source: '3', target: '4' }, +] diff --git a/docs2/components/examples/basic/style.css b/docs2/components/examples/basic/style.css new file mode 100644 index 00000000..425bc525 --- /dev/null +++ b/docs2/components/examples/basic/style.css @@ -0,0 +1,30 @@ +.basicflow .vue-flow__node.dark { + background: #1C1C1C; + color: #FFFFFB; +} + +.basicflow .controls { + position: absolute; + left: 10px; + top: 10px; + z-index: 4; + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 8px; +} + +.basicflow .controls button { + padding: 5px; + border-radius: 5px; + font-weight: 500; + -webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); + box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); + cursor: pointer; +} + +.basicflow .controls button:hover { + opacity: 0.8; + transform: scale(105%); + transition: 250ms all ease; +} diff --git a/docs2/components/examples/connectionline/App.vue b/docs2/components/examples/connectionline/App.vue new file mode 100644 index 00000000..4bda5dff --- /dev/null +++ b/docs2/components/examples/connectionline/App.vue @@ -0,0 +1,24 @@ + + + diff --git a/docs2/components/examples/connectionline/CustomConnectionLine.vue b/docs2/components/examples/connectionline/CustomConnectionLine.vue new file mode 100644 index 00000000..64759b84 --- /dev/null +++ b/docs2/components/examples/connectionline/CustomConnectionLine.vue @@ -0,0 +1,33 @@ + + + diff --git a/docs2/components/examples/connectionline/index.ts b/docs2/components/examples/connectionline/index.ts new file mode 100644 index 00000000..e93b98df --- /dev/null +++ b/docs2/components/examples/connectionline/index.ts @@ -0,0 +1,2 @@ +export { default as CustomConnectionLineApp } from './App.vue?raw' +export { default as CustomConnectionLine } from './CustomConnectionLine.vue?raw' diff --git a/docs2/components/examples/custom-node/App.vue b/docs2/components/examples/custom-node/App.vue new file mode 100644 index 00000000..5008404b --- /dev/null +++ b/docs2/components/examples/custom-node/App.vue @@ -0,0 +1,117 @@ + + + diff --git a/docs2/components/examples/custom-node/CustomNode.vue b/docs2/components/examples/custom-node/CustomNode.vue new file mode 100644 index 00000000..ecfff975 --- /dev/null +++ b/docs2/components/examples/custom-node/CustomNode.vue @@ -0,0 +1,59 @@ + + + diff --git a/docs2/components/examples/custom-node/index.ts b/docs2/components/examples/custom-node/index.ts new file mode 100644 index 00000000..cebea17a --- /dev/null +++ b/docs2/components/examples/custom-node/index.ts @@ -0,0 +1,4 @@ +export { default as CustomNodeApp } from './App.vue?raw' +export { default as CustomNode } from './CustomNode.vue?raw' +export { default as CustomNodeCSS } from './style.css' +export { default as ColorPresets } from './presets.js?raw' diff --git a/docs2/components/examples/custom-node/presets.js b/docs2/components/examples/custom-node/presets.js new file mode 100644 index 00000000..8933583c --- /dev/null +++ b/docs2/components/examples/custom-node/presets.js @@ -0,0 +1,23 @@ +export const presets = { + sumi: '#1C1C1C', + gofun: '#FFFFFB', + byakuroku: '#A8D8B9', + mizu: '#81C7D4', + asagi: '#33A6B8', + ukon: '#EFBB24', + mushikuri: '#D9CD90', + hiwa: '#BEC23F', + ichigo: '#B5495B', + kurenai: '#CB1B45', + syojyohi: '#E83015', + konjyo: '#113285', + fuji: '#8B81C3', + ayame: '#6F3381', + torinoko: '#DAC9A6', + kurotsurubami: '#0B1013', + ohni: '#F05E1C', + kokikuchinashi: '#FB9966', + beniukon: '#E98B2A', + sakura: '#FEDFE1', + toki: '#EEA9A9', +} diff --git a/docs2/components/examples/custom-node/style.css b/docs2/components/examples/custom-node/style.css new file mode 100644 index 00000000..789d54b2 --- /dev/null +++ b/docs2/components/examples/custom-node/style.css @@ -0,0 +1,73 @@ +.customnodeflow .vue-flow__node-custom { + border: 1px solid #777; + padding: 10px; + border-radius: 10px; + background: whitesmoke; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + gap: 10px; + max-width: 250px; +} + +.customnodeflow button { + padding: 5px; + width: 25px; + height: 25px; + border-radius: 25px; + -webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); + box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); + cursor: pointer; +} + +.customnodeflow button:hover { + opacity: 0.9; + transform: scale(105%); + transition: 250ms all ease; +} + +.animated-bg-gradient { + background: linear-gradient(122deg, #6f3381, #81c7d4, #fedfe1, #fffffb); + background-size: 800% 800%; + + -webkit-animation: gradient 4s ease infinite; + -moz-animation: gradient 4s ease infinite; + animation: gradient 4s ease infinite; +} + +@-webkit-keyframes gradient { + 0% { + background-position: 0% 22% + } + 50% { + background-position: 100% 79% + } + 100% { + background-position: 0% 22% + } +} + +@-moz-keyframes gradient { + 0% { + background-position: 0% 22% + } + 50% { + background-position: 100% 79% + } + 100% { + background-position: 0% 22% + } +} + +@keyframes gradient { + 0% { + background-position: 0% 22% + } + 50% { + background-position: 100% 79% + } + 100% { + background-position: 0% 22% + } +} diff --git a/docs2/components/examples/dnd/App.vue b/docs2/components/examples/dnd/App.vue new file mode 100644 index 00000000..aa93fa9b --- /dev/null +++ b/docs2/components/examples/dnd/App.vue @@ -0,0 +1,45 @@ + + + diff --git a/docs2/components/examples/dnd/Sidebar.vue b/docs2/components/examples/dnd/Sidebar.vue new file mode 100644 index 00000000..7a42607b --- /dev/null +++ b/docs2/components/examples/dnd/Sidebar.vue @@ -0,0 +1,19 @@ + + + diff --git a/docs2/components/examples/dnd/index.ts b/docs2/components/examples/dnd/index.ts new file mode 100644 index 00000000..a8c16c1a --- /dev/null +++ b/docs2/components/examples/dnd/index.ts @@ -0,0 +1,3 @@ +export { default as DndApp } from './App.vue?raw' +export { default as DndSidebar } from './Sidebar.vue?raw' +export { default as DndCSS } from './style.css' diff --git a/docs2/components/examples/dnd/style.css b/docs2/components/examples/dnd/style.css new file mode 100644 index 00000000..d6560044 --- /dev/null +++ b/docs2/components/examples/dnd/style.css @@ -0,0 +1,51 @@ +.dndflow { + flex-direction: column; + display: flex; + height: 100%; +} + +.dndflow aside { + color: white; + font-weight: 700; + border-right: 1px solid #eee; + padding: 15px 10px; + font-size: 12px; + background: rgba(16, 185, 129, 0.75); + -webkit-box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3); + box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3); +} + +.dndflow aside .nodes > * { + margin-bottom: 10px; + cursor: grab; + font-weight: 500; + -webkit-box-shadow: 5px 5px 10px 2px rgba(0,0,0,0.25); + box-shadow: 5px 5px 10px 2px rgba(0,0,0,0.25); +} + +.dndflow aside .description { + margin-bottom: 10px; +} + +.dndflow .vue-flow-wrapper { + flex-grow: 1; + height: 100%; +} + +@media screen and (min-width: 640px) { + .dndflow { + flex-direction: row; + } + + .dndflow aside { + min-width: 25%; + } +} + +@media screen and (max-width: 639px) { + .dndflow aside .nodes { + display: flex; + flex-direction: row; + gap: 5px; + } +} diff --git a/docs2/components/examples/edges/App.vue b/docs2/components/examples/edges/App.vue new file mode 100644 index 00000000..9829eeb5 --- /dev/null +++ b/docs2/components/examples/edges/App.vue @@ -0,0 +1,74 @@ + + + diff --git a/docs2/components/examples/edges/CustomEdge.vue b/docs2/components/examples/edges/CustomEdge.vue new file mode 100644 index 00000000..52fe1385 --- /dev/null +++ b/docs2/components/examples/edges/CustomEdge.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/docs2/components/examples/edges/CustomEdge2.vue b/docs2/components/examples/edges/CustomEdge2.vue new file mode 100644 index 00000000..b4fff2ba --- /dev/null +++ b/docs2/components/examples/edges/CustomEdge2.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/docs2/components/examples/edges/CustomEdgeLabel.vue b/docs2/components/examples/edges/CustomEdgeLabel.vue new file mode 100644 index 00000000..19d19e75 --- /dev/null +++ b/docs2/components/examples/edges/CustomEdgeLabel.vue @@ -0,0 +1,12 @@ + + + diff --git a/docs2/components/examples/edges/index.ts b/docs2/components/examples/edges/index.ts new file mode 100644 index 00000000..5d38a75c --- /dev/null +++ b/docs2/components/examples/edges/index.ts @@ -0,0 +1,5 @@ +export { default as EdgesApp } from './App.vue?raw' +export { default as CustomEdge } from './CustomEdge.vue?raw' +export { default as CustomEdge2 } from './CustomEdge2.vue?raw' +export { default as CustomEdgeLabel } from './CustomEdgeLabel.vue?raw' +export { default as EdgeCSS } from './style.css' diff --git a/docs2/components/examples/edges/style.css b/docs2/components/examples/edges/style.css new file mode 100644 index 00000000..34182d43 --- /dev/null +++ b/docs2/components/examples/edges/style.css @@ -0,0 +1,10 @@ +.edgebutton { + border-radius: 999px; + cursor: pointer; +} + +.edgebutton:hover { + transform: scale(110%); + transition: all ease 500ms; + box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.5), 0 0 0 4px #10b981; +} diff --git a/docs2/components/examples/empty/App.vue b/docs2/components/examples/empty/App.vue new file mode 100644 index 00000000..bf823312 --- /dev/null +++ b/docs2/components/examples/empty/App.vue @@ -0,0 +1,31 @@ + + + diff --git a/docs2/components/examples/empty/index.ts b/docs2/components/examples/empty/index.ts new file mode 100644 index 00000000..74eb2379 --- /dev/null +++ b/docs2/components/examples/empty/index.ts @@ -0,0 +1 @@ +export { default as EmptyApp } from './App.vue?raw' diff --git a/docs2/components/examples/hidden/App.vue b/docs2/components/examples/hidden/App.vue new file mode 100644 index 00000000..87811329 --- /dev/null +++ b/docs2/components/examples/hidden/App.vue @@ -0,0 +1,41 @@ + + + diff --git a/docs2/components/examples/hidden/index.ts b/docs2/components/examples/hidden/index.ts new file mode 100644 index 00000000..b6a6a585 --- /dev/null +++ b/docs2/components/examples/hidden/index.ts @@ -0,0 +1 @@ +export { default as HiddenApp } from './App.vue?raw' diff --git a/docs2/components/examples/horizontal/App.vue b/docs2/components/examples/horizontal/App.vue new file mode 100644 index 00000000..8eebf67f --- /dev/null +++ b/docs2/components/examples/horizontal/App.vue @@ -0,0 +1,27 @@ + + + diff --git a/docs2/components/examples/horizontal/index.ts b/docs2/components/examples/horizontal/index.ts new file mode 100644 index 00000000..a40f7c4c --- /dev/null +++ b/docs2/components/examples/horizontal/index.ts @@ -0,0 +1,2 @@ +export { default as HorizontalApp } from './App.vue?raw' +export { default as HorizontalElements } from './initial-elements.js?raw' diff --git a/docs2/components/examples/horizontal/initial-elements.js b/docs2/components/examples/horizontal/initial-elements.js new file mode 100644 index 00000000..174e97b4 --- /dev/null +++ b/docs2/components/examples/horizontal/initial-elements.js @@ -0,0 +1,38 @@ +import { MarkerType, Position } from '@braks/vue-flow' + +export const initialElements = [ + { + id: '1', + type: 'input', + label: 'Node 1', + position: { x: 0, y: 50 }, + sourcePosition: Position.Right, + }, + { + id: '2', + type: 'output', + label: 'Node 2', + position: { x: 250, y: 0 }, + targetPosition: Position.Left, + }, + { id: '3', label: 'Node 3', position: { x: 250, y: 100 }, sourcePosition: Position.Right, targetPosition: Position.Left }, + { id: '4', label: 'Node 4', position: { x: 500, y: 150 }, sourcePosition: Position.Right, targetPosition: Position.Left }, + { + id: '5', + type: 'output', + label: 'Node 5', + position: { x: 750, y: 50 }, + sourcePosition: Position.Right, + targetPosition: Position.Left, + }, + { id: 'e1-2', source: '1', target: '2', animated: true }, + { id: 'e1-3', source: '1', target: '3', markerEnd: MarkerType.Arrow }, + { + id: 'e4-5', + source: '4', + target: '5', + style: { stroke: 'orange' }, + labelBgStyle: { fill: 'orange' }, + }, + { id: 'e3-4', source: '3', target: '4' }, +] diff --git a/docs2/components/examples/index.ts b/docs2/components/examples/index.ts new file mode 100644 index 00000000..6d92740d --- /dev/null +++ b/docs2/components/examples/index.ts @@ -0,0 +1,100 @@ +import { BasicApp, BasicCSS, BasicElements } from './basic' +import { ColorPresets, CustomNode, CustomNodeApp, CustomNodeCSS } from './custom-node' +import { CustomConnectionLine, CustomConnectionLineApp } from './connectionline' +import { CustomEdge, CustomEdge2, CustomEdgeLabel, EdgeCSS, EdgesApp } from './edges' +import { NestedApp } from './nested' +import { StressApp, StressCSS, StressUtils } from './stress' +import { UpdateEdgeApp } from './update-edge' +import { UpdateNodeApp, UpdateNodeCSS } from './update-node' +import { ValidationApp, ValidationCSS, ValidationCustomInput, ValidationCustomNode } from './validation' +import { SaveRestoreApp, SaveRestoreCSS, SaveRestoreControls } from './save-restore' +import { DndApp, DndCSS, DndSidebar } from './dnd' +import { EmptyApp } from './empty' +import { HiddenApp } from './hidden' +import { InteractionApp, InteractionCSS, InteractionControls } from './interaction' +import { MultiApp, MultiCSS, MultiFlow } from './multi' +import { HorizontalApp, HorizontalElements } from './horizontal' +import { TeleportApp, TeleportCSS, TeleportSidebar, TeleportableNode, TeleportableUseTransition } from './teleport' + +export const exampleImports = { + basic: { + 'App.vue': BasicApp, + 'initial-elements.js': BasicElements, + 'style.css': BasicCSS, + }, + customNode: { + 'App.vue': CustomNodeApp, + 'CustomNode.vue': CustomNode, + 'style.css': CustomNodeCSS, + 'presets.js': ColorPresets, + }, + connectionline: { + 'App.vue': CustomConnectionLineApp, + 'CustomConnectionLine.vue': CustomConnectionLine, + }, + edges: { + 'App.vue': EdgesApp, + 'CustomEdge.vue': CustomEdge, + 'CustomEdge2.vue': CustomEdge2, + 'CustomEdgeLabel.vue': CustomEdgeLabel, + 'style.css': EdgeCSS, + }, + nested: { + 'App.vue': NestedApp, + }, + stress: { + 'App.vue': StressApp, + 'utils.js': StressUtils, + 'style.css': StressCSS, + }, + updateEdge: { + 'App.vue': UpdateEdgeApp, + }, + updateNode: { + 'App.vue': UpdateNodeApp, + 'style.css': UpdateNodeCSS, + }, + validation: { + 'App.vue': ValidationApp, + 'CustomInput.vue': ValidationCustomInput, + 'CustomNode.vue': ValidationCustomNode, + 'style.css': ValidationCSS, + }, + saveRestore: { + 'App.vue': SaveRestoreApp, + 'Controls.vue': SaveRestoreControls, + 'style.css': SaveRestoreCSS, + }, + dnd: { + 'App.vue': DndApp, + 'Sidebar.vue': DndSidebar, + 'style.css': DndCSS, + }, + empty: { + 'App.vue': EmptyApp, + }, + hidden: { + 'App.vue': HiddenApp, + }, + interaction: { + 'App.vue': InteractionApp, + 'InteractionControls.vue': InteractionControls, + 'style.css': InteractionCSS, + }, + multi: { + 'App.vue': MultiApp, + 'Flow.vue': MultiFlow, + 'style.css': MultiCSS, + }, + horizontal: { + 'App.vue': HorizontalApp, + 'initial-elements.js': HorizontalElements, + }, + teleport: { + 'App.vue': TeleportApp, + 'Sidebar.vue': TeleportSidebar, + 'TeleportableNode.vue': TeleportableNode, + 'useTransition.js': TeleportableUseTransition, + 'style.css': TeleportCSS, + }, +} diff --git a/docs2/components/examples/interaction/App.vue b/docs2/components/examples/interaction/App.vue new file mode 100644 index 00000000..c8fca777 --- /dev/null +++ b/docs2/components/examples/interaction/App.vue @@ -0,0 +1,20 @@ + + + diff --git a/docs2/components/examples/interaction/InteractionControls.vue b/docs2/components/examples/interaction/InteractionControls.vue new file mode 100644 index 00000000..942f4d00 --- /dev/null +++ b/docs2/components/examples/interaction/InteractionControls.vue @@ -0,0 +1,110 @@ + + + diff --git a/docs2/components/examples/interaction/index.ts b/docs2/components/examples/interaction/index.ts new file mode 100644 index 00000000..84792f94 --- /dev/null +++ b/docs2/components/examples/interaction/index.ts @@ -0,0 +1,3 @@ +export { default as InteractionApp } from './App.vue?raw' +export { default as InteractionControls } from './InteractionControls.vue?raw' +export { default as InteractionCSS } from './style.css' diff --git a/docs2/components/examples/interaction/style.css b/docs2/components/examples/interaction/style.css new file mode 100644 index 00000000..b979c3c7 --- /dev/null +++ b/docs2/components/examples/interaction/style.css @@ -0,0 +1,22 @@ +.interactionflow .controls { + position: absolute; + left: 0; + top: 0; + z-index: 4; + font-size: 11px; + background-color: lightgray; + border-bottom-right-radius: 10px; + padding: 12px; +} + +.interactionflow .controls .label { + display: flex; + justify-content: space-between; + align-items: center; + gap: 5px; + cursor: pointer; +} + +.interactionflow .controls .label input { + cursor: pointer; +} diff --git a/docs2/components/examples/multi/App.vue b/docs2/components/examples/multi/App.vue new file mode 100644 index 00000000..2f9b72a7 --- /dev/null +++ b/docs2/components/examples/multi/App.vue @@ -0,0 +1,10 @@ + + + diff --git a/docs2/components/examples/multi/Flow.vue b/docs2/components/examples/multi/Flow.vue new file mode 100644 index 00000000..18058d87 --- /dev/null +++ b/docs2/components/examples/multi/Flow.vue @@ -0,0 +1,36 @@ + + + diff --git a/docs2/components/examples/multi/index.ts b/docs2/components/examples/multi/index.ts new file mode 100644 index 00000000..d6731a00 --- /dev/null +++ b/docs2/components/examples/multi/index.ts @@ -0,0 +1,3 @@ +export { default as MultiApp } from './App.vue?raw' +export { default as MultiFlow } from './Flow.vue?raw' +export { default as MultiCSS } from './style.css' diff --git a/docs2/components/examples/multi/style.css b/docs2/components/examples/multi/style.css new file mode 100644 index 00000000..92c483fd --- /dev/null +++ b/docs2/components/examples/multi/style.css @@ -0,0 +1,18 @@ +.vue-flow__node.dark { + background: #000000; + color: #ffffff; +} + +.multiflows { + display: flex; + height: 100%; +} + +.multiflows .vue-flow { + width: 100%; + height: 100%; +} + +.multiflows .vue-flow:first-child { + border-right: 2px solid #333; +} diff --git a/docs2/components/examples/nested/App.vue b/docs2/components/examples/nested/App.vue new file mode 100644 index 00000000..f328341e --- /dev/null +++ b/docs2/components/examples/nested/App.vue @@ -0,0 +1,93 @@ + + + diff --git a/docs2/components/examples/nested/index.ts b/docs2/components/examples/nested/index.ts new file mode 100644 index 00000000..7aef51bc --- /dev/null +++ b/docs2/components/examples/nested/index.ts @@ -0,0 +1 @@ +export { default as NestedApp } from './App.vue?raw' diff --git a/docs2/components/examples/pinia/PiniaExample.vue b/docs2/components/examples/pinia/PiniaExample.vue new file mode 100644 index 00000000..bcc3333f --- /dev/null +++ b/docs2/components/examples/pinia/PiniaExample.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/docs2/components/examples/save-restore/App.vue b/docs2/components/examples/save-restore/App.vue new file mode 100644 index 00000000..55d9d552 --- /dev/null +++ b/docs2/components/examples/save-restore/App.vue @@ -0,0 +1,13 @@ + + + diff --git a/docs2/components/examples/save-restore/Controls.vue b/docs2/components/examples/save-restore/Controls.vue new file mode 100644 index 00000000..dc6d84b2 --- /dev/null +++ b/docs2/components/examples/save-restore/Controls.vue @@ -0,0 +1,40 @@ + + + diff --git a/docs2/components/examples/save-restore/index.ts b/docs2/components/examples/save-restore/index.ts new file mode 100644 index 00000000..d6faf819 --- /dev/null +++ b/docs2/components/examples/save-restore/index.ts @@ -0,0 +1,3 @@ +export { default as SaveRestoreApp } from './App.vue?raw' +export { default as SaveRestoreControls } from './Controls.vue?raw' +export { default as SaveRestoreCSS } from './style.css' diff --git a/docs2/components/examples/save-restore/style.css b/docs2/components/examples/save-restore/style.css new file mode 100644 index 00000000..ab1c9790 --- /dev/null +++ b/docs2/components/examples/save-restore/style.css @@ -0,0 +1,25 @@ +.save__controls { + position: absolute; + left: 10px; + top: 10px; + z-index: 4; + font-size: 12px; +} + +.save__controls button { + margin-left: 5px; + padding: 5px; + border-radius: 5px; + font-weight: 700; + text-transform: uppercase; + color: white; + -webkit-box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3); + box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.3); + cursor: pointer; +} + +.save__controls button:hover { + opacity: 0.8; + transform: scale(105%); + transition: 250ms all ease-in-out; +} diff --git a/docs2/components/examples/stress/App.vue b/docs2/components/examples/stress/App.vue new file mode 100644 index 00000000..931fea0d --- /dev/null +++ b/docs2/components/examples/stress/App.vue @@ -0,0 +1,42 @@ + + + diff --git a/docs2/components/examples/stress/index.ts b/docs2/components/examples/stress/index.ts new file mode 100644 index 00000000..2b70f3e0 --- /dev/null +++ b/docs2/components/examples/stress/index.ts @@ -0,0 +1,3 @@ +export { default as StressApp } from './App.vue?raw' +export { default as StressUtils } from './utils.js?raw' +export { default as StressCSS } from './style.css' diff --git a/docs2/components/examples/stress/style.css b/docs2/components/examples/stress/style.css new file mode 100644 index 00000000..f835f6ea --- /dev/null +++ b/docs2/components/examples/stress/style.css @@ -0,0 +1,4 @@ +.vue-flow__node.dark { + background: #000000; + color: #ffffff; +} diff --git a/docs2/components/examples/stress/utils.js b/docs2/components/examples/stress/utils.js new file mode 100644 index 00000000..60a7869b --- /dev/null +++ b/docs2/components/examples/stress/utils.js @@ -0,0 +1,40 @@ +export function getElements(xElements = 10, yElements = 10) { + const initialNodes = [] + const initialEdges = [] + let nodeId = 1 + let recentNodeId = null + + for (let y = 0; y < yElements; y++) { + for (let x = 0; x < xElements; x++) { + const position = { x: x * 75, y: y * 75 } + const node = { + id: nodeId.toString(), + style: { width: `50px`, fontSize: `11px`, zIndex: 1 }, + label: `Node ${nodeId}`, + class: 'light', + position, + } + initialNodes.push(node) + + if (recentNodeId && nodeId <= xElements * yElements) { + initialEdges.push({ + id: `${x}-${y}`, + source: recentNodeId.toString(), + target: nodeId.toString(), + style: (edge) => { + if (!edge.sourceNode.selected && !edge.targetNode.selected) return + return { stroke: '#10b981', strokeWidth: 3 } + }, + }) + } + + recentNodeId = nodeId + nodeId++ + } + } + + return { + nodes: initialNodes, + edges: initialEdges, + } +} diff --git a/docs2/components/examples/teleport/App.vue b/docs2/components/examples/teleport/App.vue new file mode 100644 index 00000000..9ef3e18c --- /dev/null +++ b/docs2/components/examples/teleport/App.vue @@ -0,0 +1,46 @@ + + + diff --git a/docs2/components/examples/teleport/Sidebar.vue b/docs2/components/examples/teleport/Sidebar.vue new file mode 100644 index 00000000..e632a47b --- /dev/null +++ b/docs2/components/examples/teleport/Sidebar.vue @@ -0,0 +1,10 @@ + + + diff --git a/docs2/components/examples/teleport/TeleportableNode.vue b/docs2/components/examples/teleport/TeleportableNode.vue new file mode 100644 index 00000000..e1c4a8e9 --- /dev/null +++ b/docs2/components/examples/teleport/TeleportableNode.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/docs2/components/examples/teleport/index.ts b/docs2/components/examples/teleport/index.ts new file mode 100644 index 00000000..9a262f7b --- /dev/null +++ b/docs2/components/examples/teleport/index.ts @@ -0,0 +1,5 @@ +export { default as TeleportApp } from './App.vue?raw' +export { default as TeleportSidebar } from './Sidebar.vue?raw' +export { default as TeleportableNode } from './TeleportableNode.vue?raw' +export { default as TeleportableUseTransition } from './useTransition.js?raw' +export { default as TeleportCSS } from './style.css' diff --git a/docs2/components/examples/teleport/style.css b/docs2/components/examples/teleport/style.css new file mode 100644 index 00000000..ef076e6f --- /dev/null +++ b/docs2/components/examples/teleport/style.css @@ -0,0 +1,125 @@ +.teleportflow { + flex-direction: column; + display: flex; + height: 100%; +} + +.teleportflow aside { + display: flex; + flex-direction: column; + gap: 5px; + color: white; + font-weight: 700; + border-right: 1px solid #eee; + padding: 10px 10px; + font-size: 12px; + background: rgba(16, 185, 129, 0.75); + -webkit-box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); + box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.3); +} + +.teleportflow aside .port > * { + position: relative; + margin-bottom: 10px; + cursor: grab; + font-weight: 500; + -webkit-box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.25); + box-shadow: 5px 5px 10px 2px rgba(0, 0, 0, 0.25); +} + +.teleportflow aside .description { + margin-bottom: 10px; +} + +.teleportflow .vue-flow-wrapper { + flex-grow: 1; + height: 100%; +} + +@media screen and (min-width: 640px) { + .teleportflow { + flex-direction: row; + } + + .teleportflow aside { + min-width: 25%; + } +} + +@media screen and (max-width: 639px) { + .teleportflow aside .port { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 5px; + } +} + +.teleportable { + padding: 10px; + background: white; + border: 1px solid black; + border-radius: 10px; + color: black +} + +.buttons { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 5px; + gap: 5px; +} + +.button { + background-color: whitesmoke; + cursor: pointer; + padding: 5px 10px; + border: 1px solid black; + border-radius: 10px; + color: black; + font-weight: 700; + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); +} + +.button:hover { + background: black; + color: white; +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.5s ease; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.shrink-leave-active { + animation: shrink 0.5s; +} + +.shrink-enter-active { + animation: grow 0.5s; +} + +@keyframes grow { + from { + transform: scale(0.1); + } + to { + transform: scale(1); + } +} + +@keyframes shrink { + from { + transform: scale(1); + } + to { + transform: scale(0.1); + } +} + diff --git a/docs2/components/examples/teleport/useTransition.js b/docs2/components/examples/teleport/useTransition.js new file mode 100644 index 00000000..21eeedb1 --- /dev/null +++ b/docs2/components/examples/teleport/useTransition.js @@ -0,0 +1,107 @@ +import { getConnectedEdges, useVueFlow } from '@braks/vue-flow' +import { nextTick, ref } from 'vue' + +/** + * Utility composable for specifying animations + * + * Animations that resize a node need to call the `updateNodeDimensions` function from store to update node handle positions + * Otherwise edges do not connect properly + */ +export const useTransition = (id) => { + const animation = ref('fade') + const transition = ref(false) + const teleport = ref(null) + + const { updateNodeInternals, getNode, edges } = useVueFlow() + + /** + * specify a selector to teleport to + * + * teleported elements still behave like they're at their position before, + * i.e. if they emit events, they will still emit them up their regular tree + */ + const fade = (destination, onFinish) => { + setTimeout(() => { + // teleport to destination or disable teleport + teleport.value = destination + + setTimeout(() => { + transition.value = false + + // if destination is null, defer hiding edges until node is teleported back + if (!destination) { + onFinish() + } + }, 500) + }, 500) + } + + const shrink = (destination, onFinish) => { + setTimeout(() => { + // teleport to destination or disable teleport + teleport.value = destination + + setTimeout(() => { + transition.value = false + + setTimeout(() => { + // if destination is null, defer hiding edges until node is teleported back + if (!destination) { + updateNodeInternals([id]) + + nextTick(() => { + onFinish() + }) + } + }, 500) + }, 500) + }, 500) + } + + /** + * specify a selector to teleport to + * + * teleported elements still behave like they're at their position before, + * i.e. if they emit events, they will still emit them up their regular tree + */ + const onClick = (destination) => { + const node = getNode.value(id) + + transition.value = true + + // save current teleport destination to data of node + node.data.destination = destination + + // hide connected edges when teleporting + const connectedEdges = getConnectedEdges([node], edges.value) + + // if destination is not null, hide edges immediately + // check if nodes connected to edge are teleported and hide edge if one of them is + if (destination) { + connectedEdges.forEach( + (edge) => (edge.hidden = !!getNode.value(edge.source).data.destination || !!getNode.value(edge.target).data.destination), + ) + } + + const onFinish = () => { + connectedEdges.forEach( + (edge) => (edge.hidden = !!getNode.value(edge.source).data.destination || !!getNode.value(edge.target).data.destination), + ) + } + + switch (animation.value) { + case 'fade': + fade(destination, onFinish) + break + case 'shrink': + shrink(destination, onFinish) + } + } + + return { + animation, + transition, + teleport, + onClick, + } +} diff --git a/docs2/components/examples/update-edge/App.vue b/docs2/components/examples/update-edge/App.vue new file mode 100644 index 00000000..bb224f7a --- /dev/null +++ b/docs2/components/examples/update-edge/App.vue @@ -0,0 +1,47 @@ + + + diff --git a/docs2/components/examples/update-edge/index.ts b/docs2/components/examples/update-edge/index.ts new file mode 100644 index 00000000..ad531558 --- /dev/null +++ b/docs2/components/examples/update-edge/index.ts @@ -0,0 +1 @@ +export { default as UpdateEdgeApp } from './App.vue?raw' diff --git a/docs2/components/examples/update-node/App.vue b/docs2/components/examples/update-node/App.vue new file mode 100644 index 00000000..1e9bc50c --- /dev/null +++ b/docs2/components/examples/update-node/App.vue @@ -0,0 +1,48 @@ + + + diff --git a/docs2/components/examples/update-node/index.ts b/docs2/components/examples/update-node/index.ts new file mode 100644 index 00000000..2d3749b4 --- /dev/null +++ b/docs2/components/examples/update-node/index.ts @@ -0,0 +1,2 @@ +export { default as UpdateNodeApp } from './App.vue?raw' +export { default as UpdateNodeCSS } from './style.css' diff --git a/docs2/components/examples/update-node/style.css b/docs2/components/examples/update-node/style.css new file mode 100644 index 00000000..26021bf4 --- /dev/null +++ b/docs2/components/examples/update-node/style.css @@ -0,0 +1,30 @@ +.updatenode__controls { + position: absolute; + right: 10px; + top: 10px; + z-index: 4; + font-size: 11px; + background-color: lightgray; + border-radius: 10px; + padding: 8px; +} + +.updatenode__controls label { + display: blocK; +} + +.updatenode__controls input { + padding: 2px; + border-radius: 5px; +} + +.updatenode__bglabel { + margin-top: 8px; +} + +.updatenode__checkboxwrapper { + display: flex; + justify-content: center; + align-items: center; + margin-top: 8px; +} diff --git a/docs2/components/examples/validation/App.vue b/docs2/components/examples/validation/App.vue new file mode 100644 index 00000000..a9576e98 --- /dev/null +++ b/docs2/components/examples/validation/App.vue @@ -0,0 +1,47 @@ + + + diff --git a/docs2/components/examples/validation/CustomInput.vue b/docs2/components/examples/validation/CustomInput.vue new file mode 100644 index 00000000..f6501416 --- /dev/null +++ b/docs2/components/examples/validation/CustomInput.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/docs2/components/examples/validation/CustomNode.vue b/docs2/components/examples/validation/CustomNode.vue new file mode 100644 index 00000000..9d28c452 --- /dev/null +++ b/docs2/components/examples/validation/CustomNode.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/docs2/components/examples/validation/index.ts b/docs2/components/examples/validation/index.ts new file mode 100644 index 00000000..d2674919 --- /dev/null +++ b/docs2/components/examples/validation/index.ts @@ -0,0 +1,4 @@ +export { default as ValidationApp } from './App.vue?raw' +export { default as ValidationCustomInput } from './CustomInput.vue?raw' +export { default as ValidationCustomNode } from './CustomNode.vue?raw' +export { default as ValidationCSS } from './style.css' diff --git a/docs2/components/examples/validation/style.css b/docs2/components/examples/validation/style.css new file mode 100644 index 00000000..98f3a03b --- /dev/null +++ b/docs2/components/examples/validation/style.css @@ -0,0 +1,31 @@ +.validationflow .vue-flow__node { + width: 150px; + border-radius: 5px; + padding: 10px; + color: #555; + border: 1px solid #ddd; + text-align: center; + font-size: 12px; +} + +.validationflow .vue-flow__node-customnode { + background: #e6e6e9; + border: 1px solid #ddd; +} + +.validationflow .vue-flow__node-custominput .vue-flow__handle { + background: #e6e6e9; +} + +.validationflow .vue-flow__node-custominput { + background: #fff; + +} + +.validationflow .vue-flow__handle-connecting { + background: #ff6060; +} + +.validationflow .vue-flow__handle-valid { + background: #55dd99; +} diff --git a/docs2/components/home/Acknowledgement.vue b/docs2/components/home/Acknowledgement.vue new file mode 100644 index 00000000..e969fbe2 --- /dev/null +++ b/docs2/components/home/Acknowledgement.vue @@ -0,0 +1,27 @@ + + + diff --git a/docs2/components/home/Banner.vue b/docs2/components/home/Banner.vue new file mode 100644 index 00000000..2b3fcd0e --- /dev/null +++ b/docs2/components/home/Banner.vue @@ -0,0 +1,31 @@ + + + diff --git a/docs2/components/home/Features.vue b/docs2/components/home/Features.vue new file mode 100644 index 00000000..53bf7bae --- /dev/null +++ b/docs2/components/home/Features.vue @@ -0,0 +1,56 @@ + + + diff --git a/docs2/components/home/Home.vue b/docs2/components/home/Home.vue new file mode 100644 index 00000000..9965ce97 --- /dev/null +++ b/docs2/components/home/Home.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/docs2/components/home/edges/Custom.vue b/docs2/components/home/edges/Custom.vue new file mode 100644 index 00000000..cfd55976 --- /dev/null +++ b/docs2/components/home/edges/Custom.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/docs2/components/home/flows/Additional.vue b/docs2/components/home/flows/Additional.vue new file mode 100644 index 00000000..8d7d9b67 --- /dev/null +++ b/docs2/components/home/flows/Additional.vue @@ -0,0 +1,112 @@ + + + diff --git a/docs2/components/home/flows/Basic.vue b/docs2/components/home/flows/Basic.vue new file mode 100644 index 00000000..45c0d97e --- /dev/null +++ b/docs2/components/home/flows/Basic.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/docs2/components/home/flows/Intro.vue b/docs2/components/home/flows/Intro.vue new file mode 100644 index 00000000..7eddbdf6 --- /dev/null +++ b/docs2/components/home/flows/Intro.vue @@ -0,0 +1,451 @@ + + + + + diff --git a/docs2/components/home/flows/Nested.vue b/docs2/components/home/flows/Nested.vue new file mode 100644 index 00000000..261c7ca0 --- /dev/null +++ b/docs2/components/home/flows/Nested.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/docs2/components/home/flows/RGB.vue b/docs2/components/home/flows/RGB.vue new file mode 100644 index 00000000..7af38546 --- /dev/null +++ b/docs2/components/home/flows/RGB.vue @@ -0,0 +1,114 @@ + + + diff --git a/docs2/components/home/flows/confetti.ts b/docs2/components/home/flows/confetti.ts new file mode 100644 index 00000000..469b5ad7 --- /dev/null +++ b/docs2/components/home/flows/confetti.ts @@ -0,0 +1,69 @@ +import confetti from 'canvas-confetti' + +export const fireworks = (colors?: string[]) => { + return new Promise((resolve) => { + const duration = 15 * 1000 + const animationEnd = Date.now() + duration + const defaults = { startVelocity: 60, spread: 360, ticks: 20, zIndex: 0 } + + function randomInRange(min: number, max: number) { + return Math.random() * (max - min) + min + } + + const interval: any = setInterval(function () { + const timeLeft = animationEnd - Date.now() + + if (timeLeft <= 0) { + clearInterval(interval) + return resolve(true) + } + + const particleCount = 50 * (timeLeft / duration) + // since particles fall down, start a bit higher than random + confetti( + Object.assign({}, defaults, { + particleCount, + origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 }, + colors, + }), + ) + confetti( + Object.assign({}, defaults, { + particleCount, + origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 }, + colors, + }), + ) + }, 250) + }) +} + +export const cheer = (colors: string[]) => { + return new Promise((resolve) => { + const end = Date.now() + 2 * 1000 + + function frame() { + confetti({ + particleCount: 2, + angle: 60, + spread: 75, + origin: { x: 0 }, + colors, + }) + confetti({ + particleCount: 2, + angle: 120, + spread: 75, + origin: { x: 1 }, + colors, + }) + + if (Date.now() < end) { + requestAnimationFrame(frame) + } else { + resolve(true) + } + } + frame() + }) +} diff --git a/docs2/components/home/nodes/Input.vue b/docs2/components/home/nodes/Input.vue new file mode 100644 index 00000000..683377d9 --- /dev/null +++ b/docs2/components/home/nodes/Input.vue @@ -0,0 +1,46 @@ + + + diff --git a/docs2/components/home/nodes/Output.vue b/docs2/components/home/nodes/Output.vue new file mode 100644 index 00000000..50cdce16 --- /dev/null +++ b/docs2/components/home/nodes/Output.vue @@ -0,0 +1,21 @@ + + + diff --git a/docs2/package.json b/docs2/package.json new file mode 100644 index 00000000..b5c703d0 --- /dev/null +++ b/docs2/package.json @@ -0,0 +1,37 @@ +{ + "name": "docs2", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "vitepress dev src", + "build": "vitepress build src", + "serve": "vitepress serve src", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "@animxyz/core": "^0.6.6", + "@animxyz/vue3": "^0.6.7", + "@braks/vue-flow": "workspace:*", + "@stackblitz/sdk": "^1.8.0", + "@vue/repl": "1.1.2", + "blobity": "^0.1.7", + "canvas-confetti": "^1.5.1" + }, + "devDependencies": { + "@iconify/json": "^2.1.81", + "@types/canvas-confetti": "^1.4.3", + "@types/node": "^18.0.6", + "@windicss/plugin-scrollbar": "^1.2.3", + "dotenv": "^16.0.1", + "ohmyfetch": "^0.4.18", + "typedoc": "^0.22.18", + "typedoc-plugin-markdown": "^3.13.4", + "unplugin-auto-import": "^0.9.5", + "unplugin-icons": "^0.14.7", + "unplugin-vue-components": "^0.19.9", + "vite-plugin-windicss": "^1.8.7", + "vitepress": "^1.0.0-alpha.4", + "windicss": "^3.5.6" + } +} diff --git a/docs2/src/.vitepress/auto-imports.d.ts b/docs2/src/.vitepress/auto-imports.d.ts new file mode 100644 index 00000000..7821e0e8 --- /dev/null +++ b/docs2/src/.vitepress/auto-imports.d.ts @@ -0,0 +1,248 @@ +// Generated by 'unplugin-auto-import' +export {} +declare global { + const EffectScope: typeof import('vue')['EffectScope'] + const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] + const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] + const computed: typeof import('vue')['computed'] + const computedAsync: typeof import('@vueuse/core')['computedAsync'] + const computedEager: typeof import('@vueuse/core')['computedEager'] + const computedInject: typeof import('@vueuse/core')['computedInject'] + const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] + const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] + const controlledRef: typeof import('@vueuse/core')['controlledRef'] + const createApp: typeof import('vue')['createApp'] + const createEventHook: typeof import('@vueuse/core')['createEventHook'] + const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] + const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] + const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] + const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] + const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] + const customRef: typeof import('vue')['customRef'] + const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] + const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] + const effectScope: typeof import('vue')['effectScope'] + const extendRef: typeof import('@vueuse/core')['extendRef'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const h: typeof import('vue')['h'] + const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] + const inject: typeof import('vue')['inject'] + const isDefined: typeof import('@vueuse/core')['isDefined'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const logicAnd: typeof import('@vueuse/core')['logicAnd'] + const logicNot: typeof import('@vueuse/core')['logicNot'] + const logicOr: typeof import('@vueuse/core')['logicOr'] + const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] + const onLongPress: typeof import('@vueuse/core')['onLongPress'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] + const provide: typeof import('vue')['provide'] + const reactify: typeof import('@vueuse/core')['reactify'] + const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] + const reactive: typeof import('vue')['reactive'] + const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] + const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] + const reactivePick: typeof import('@vueuse/core')['reactivePick'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] + const refDebounced: typeof import('@vueuse/core')['refDebounced'] + const refDefault: typeof import('@vueuse/core')['refDefault'] + const refThrottled: typeof import('@vueuse/core')['refThrottled'] + const refWithControl: typeof import('@vueuse/core')['refWithControl'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const resolveRef: typeof import('@vueuse/core')['resolveRef'] + const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const syncRef: typeof import('@vueuse/core')['syncRef'] + const syncRefs: typeof import('@vueuse/core')['syncRefs'] + const templateRef: typeof import('@vueuse/core')['templateRef'] + const throttledRef: typeof import('@vueuse/core')['throttledRef'] + const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] + const toRaw: typeof import('vue')['toRaw'] + const toReactive: typeof import('@vueuse/core')['toReactive'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const triggerRef: typeof import('vue')['triggerRef'] + const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] + const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] + const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] + const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] + const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] + const unref: typeof import('vue')['unref'] + const unrefElement: typeof import('@vueuse/core')['unrefElement'] + const until: typeof import('@vueuse/core')['until'] + const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] + const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] + const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] + const useAttrs: typeof import('vue')['useAttrs'] + const useBase64: typeof import('@vueuse/core')['useBase64'] + const useBattery: typeof import('@vueuse/core')['useBattery'] + const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] + const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] + const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] + const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] + const useCached: typeof import('@vueuse/core')['useCached'] + const useClamp: typeof import('@vueuse/core')['useClamp'] + const useClipboard: typeof import('@vueuse/core')['useClipboard'] + const useColorMode: typeof import('@vueuse/core')['useColorMode'] + const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] + const useCounter: typeof import('@vueuse/core')['useCounter'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVar: typeof import('@vueuse/core')['useCssVar'] + const useCssVars: typeof import('vue')['useCssVars'] + const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] + const useCycleList: typeof import('@vueuse/core')['useCycleList'] + const useDark: typeof import('@vueuse/core')['useDark'] + const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] + const useDebounce: typeof import('@vueuse/core')['useDebounce'] + const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] + const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] + const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] + const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] + const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] + const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] + const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] + const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] + const useDraggable: typeof import('@vueuse/core')['useDraggable'] + const useDropZone: typeof import('@vueuse/core')['useDropZone'] + const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] + const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] + const useElementHover: typeof import('@vueuse/core')['useElementHover'] + const useElementSize: typeof import('@vueuse/core')['useElementSize'] + const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] + const useEventBus: typeof import('@vueuse/core')['useEventBus'] + const useEventListener: typeof import('@vueuse/core')['useEventListener'] + const useEventSource: typeof import('@vueuse/core')['useEventSource'] + const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] + const useFavicon: typeof import('@vueuse/core')['useFavicon'] + const useFetch: typeof import('@vueuse/core')['useFetch'] + const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] + const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] + const useFocus: typeof import('@vueuse/core')['useFocus'] + const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] + const useFps: typeof import('@vueuse/core')['useFps'] + const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] + const useGamepad: typeof import('@vueuse/core')['useGamepad'] + const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] + const useIdle: typeof import('@vueuse/core')['useIdle'] + const useImage: typeof import('@vueuse/core')['useImage'] + const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] + const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] + const useInterval: typeof import('@vueuse/core')['useInterval'] + const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] + const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] + const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] + const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] + const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] + const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] + const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] + const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] + const useMemoize: typeof import('@vueuse/core')['useMemoize'] + const useMemory: typeof import('@vueuse/core')['useMemory'] + const useMounted: typeof import('@vueuse/core')['useMounted'] + const useMouse: typeof import('@vueuse/core')['useMouse'] + const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] + const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] + const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] + const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] + const useNetwork: typeof import('@vueuse/core')['useNetwork'] + const useNow: typeof import('@vueuse/core')['useNow'] + const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] + const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] + const useOnline: typeof import('@vueuse/core')['useOnline'] + const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] + const useParallax: typeof import('@vueuse/core')['useParallax'] + const usePermission: typeof import('@vueuse/core')['usePermission'] + const usePointer: typeof import('@vueuse/core')['usePointer'] + const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] + const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] + const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] + const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] + const useRafFn: typeof import('@vueuse/core')['useRafFn'] + const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] + const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] + const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] + const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] + const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] + const useScroll: typeof import('@vueuse/core')['useScroll'] + const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] + const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] + const useShare: typeof import('@vueuse/core')['useShare'] + const useSlots: typeof import('vue')['useSlots'] + const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] + const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] + const useStepper: typeof import('@vueuse/core')['useStepper'] + const useStorage: typeof import('@vueuse/core')['useStorage'] + const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] + const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] + const useSwipe: typeof import('@vueuse/core')['useSwipe'] + const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] + const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] + const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] + const useThrottle: typeof import('@vueuse/core')['useThrottle'] + const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] + const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] + const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] + const useTimeout: typeof import('@vueuse/core')['useTimeout'] + const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] + const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] + const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] + const useTitle: typeof import('@vueuse/core')['useTitle'] + const useToggle: typeof import('@vueuse/core')['useToggle'] + const useTransition: typeof import('@vueuse/core')['useTransition'] + const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] + const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] + const useVModel: typeof import('@vueuse/core')['useVModel'] + const useVModels: typeof import('@vueuse/core')['useVModels'] + const useVibrate: typeof import('@vueuse/core')['useVibrate'] + const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] + const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] + const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] + const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] + const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] + const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] + const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] + const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] + const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] + const watch: typeof import('vue')['watch'] + const watchArray: typeof import('@vueuse/core')['watchArray'] + const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] + const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] + const watchOnce: typeof import('@vueuse/core')['watchOnce'] + const watchPausable: typeof import('@vueuse/core')['watchPausable'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] + const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] + const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] + const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] + const whenever: typeof import('@vueuse/core')['whenever'] +} diff --git a/docs2/src/.vitepress/components.d.ts b/docs2/src/.vitepress/components.d.ts new file mode 100644 index 00000000..4379bb9e --- /dev/null +++ b/docs2/src/.vitepress/components.d.ts @@ -0,0 +1,13 @@ +// generated by unplugin-vue-components +// We suggest you to commit this file into source control +// Read more: https://github.com/vuejs/core/pull/3399 +import '@vue/runtime-core' + +declare module '@vue/runtime-core' { + export interface GlobalComponents { + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + } +} + +export {} diff --git a/docs2/src/.vitepress/config.ts b/docs2/src/.vitepress/config.ts new file mode 100644 index 00000000..90a45c43 --- /dev/null +++ b/docs2/src/.vitepress/config.ts @@ -0,0 +1,154 @@ +import { resolve } from 'path' +import { readdirSync, statSync } from 'fs' +import type { HeadConfig } from 'vitepress' +import { DefaultTheme, defineConfigWithTheme } from 'vitepress' +import WindiCSS from 'vite-plugin-windicss' +import Icons from 'unplugin-icons/vite' +import IconsResolver from 'unplugin-icons/resolver' +import Components from 'unplugin-vue-components/vite' +import AutoImport from 'unplugin-auto-import/vite' +import { useVueFlow } from '@braks/vue-flow' +import { copyVueFlowPlugin } from './copy-plugin' +import head from './head' +import SidebarGroup = DefaultTheme.SidebarGroup + +const { vueFlowVersion } = useVueFlow() + +function capitalize(str: string) { + return str.charAt(0).toUpperCase() + str.slice(1) +} + +const typedocSidebarEntries = (): SidebarGroup[] => { + const filePath = resolve(__dirname, '../../typedocs') + + const docsModules = readdirSync(filePath).filter((name) => statSync(`${filePath}/${name}`).isDirectory()) + + const sidebarItems = docsModules.map((module) => { + let children = readdirSync(`${filePath}/${module}/`).map((entry) => `/typedocs/${module}/${entry}`) + + if (module === 'variables') { + children = children.filter((child) => { + return child.includes('default') + }) + } + + return { text: capitalize(module), children } + }) + + return [ + { + text: 'Modules', + link: '/typedocs/', + items: [...sidebarItems], + }, + ] +} + +export default defineConfigWithTheme({ + title: 'Vue Flow', + description: 'Visualize your ideas with Vue Flow, a highly customizable Vue3 Flowchart library.', + head: head as HeadConfig[], + + outDir: resolve(__dirname, '../../dist'), + + vite: { + optimizeDeps: { + exclude: ['@animxyz/vue3'], + }, + plugins: [ + copyVueFlowPlugin(), + AutoImport({ + imports: ['vue', '@vueuse/core'], + dts: resolve(__dirname, './auto-imports.d.ts'), + }), + WindiCSS({ + transformCSS: 'pre', + config: resolve(__dirname, './windi.config.ts'), + }), + Components({ + dirs: [resolve(__dirname, '../../components')], + deep: true, + // allow auto load markdown components under `./src/components/` + extensions: ['vue', 'md'], + // allow auto import and register components used in markdown + include: [/\.vue$/, /\.vue\?vue/, /\.md$/], + dts: resolve(__dirname, './components.d.ts'), + resolvers: [IconsResolver()], + }), + Icons({ + compiler: 'vue3', + }), + ], + }, + + themeConfig: { + logo: '/favicons/android-chrome-512x512.png', + nav: [ + { text: `v${vueFlowVersion.value}`, link: '/' }, + { text: 'Guide', link: '/guide/', activeMatch: '^/guide/' }, + { + text: 'Examples', + link: '/examples/', + activeMatch: '^/examples/', + }, + { + text: 'TypeDocs', + link: '/typedocs/', + activeMatch: '^/typedocs/', + }, + ], + sidebar: { + '/guide/': [ + { + text: 'Guide', + items: [ + { text: 'Introduction', link: '/guide/' }, + { text: 'Getting Started', link: '/guide/getting-started' }, + { text: 'Theming', link: '/guide/theming' }, + { text: 'Nodes', link: '/guide/node' }, + { text: 'Edges', link: '/guide/edge' }, + { text: 'Composables', link: '/guide/composables' }, + ], + }, + { + text: 'Vue Flow', + items: [ + { text: 'Config / Props', link: '/guide/vue-flow/config' }, + { text: 'State', link: '/guide/vue-flow/state' }, + { + text: 'Actions', + link: '/typedocs/interfaces/Actions.html', + }, + { + text: 'Getters', + link: '/typedocs/interfaces/Getters.html', + }, + { + text: 'Events', + link: '/typedocs/interfaces/FlowEvents.html', + }, + { text: 'Slots', link: '/guide/vue-flow/slots' }, + ], + }, + { + text: 'Utilities', + items: [ + { text: 'Graph', link: '/guide/utils/graph' }, + { text: 'Viewport', link: '/guide/utils/instance' }, + { text: 'Edges', link: '/guide/utils/edge' }, + ], + }, + { + text: 'Components', + items: [ + { text: 'Background', link: '/guide/components/background' }, + { text: 'MiniMap', link: '/guide/components/minimap' }, + { text: 'MiniMapNode', link: '/guide/components/minimap-node' }, + { text: 'Controls', link: '/guide/components/controls' }, + { text: 'Control Button', link: '/guide/components/control-button' }, + ], + }, + ], + }, + }, +}) diff --git a/docs2/src/.vitepress/copy-plugin.ts b/docs2/src/.vitepress/copy-plugin.ts new file mode 100644 index 00000000..7bcfa0a8 --- /dev/null +++ b/docs2/src/.vitepress/copy-plugin.ts @@ -0,0 +1,21 @@ +import { existsSync, readFileSync } from 'fs' +import { resolve } from 'path' +import type { Plugin } from 'vite' + +export function copyVueFlowPlugin(): Plugin { + return { + name: 'copy-vue-flow', + generateBundle() { + const filePath = resolve(__dirname, '../../node_modules/@braks/vue-flow/dist/vue-flow.es.js') + if (!existsSync(filePath)) { + throw new Error(`@braks/vue-flow/dist/vue-flow.es.js not built. ` + `Run "pnpm -w build" first.`) + } + + this.emitFile({ + type: 'asset', + fileName: 'vue-flow.es.js', + source: readFileSync(filePath, 'utf-8'), + }) + }, + } +} diff --git a/docs2/src/.vitepress/head.ts b/docs2/src/.vitepress/head.ts new file mode 100644 index 00000000..12cb45d4 --- /dev/null +++ b/docs2/src/.vitepress/head.ts @@ -0,0 +1,132 @@ +export const meta = { + title: '🌊 Vue Flow - The customizable Vue3 Flowchart Library', + description: `Bring interactivity to your flowcharts and graphs with Vue Flow. It's a highly customizable Vue3 Flowchart library that can be used to visualize your ideas with Vue3 Flowchart. Features seamless zoom & pan and a ton of more features!`, + keywords: 'vue, flowchart, graph, vue3, vuejs, vite, nuxt3, nuxtjs, quasar', + img: 'https://images.prismic.io/bcakmakoglu/8fbdad18-3cd4-46a9-83cf-dbd9fbf60484_vue-flow.png?auto=compress,format', + url: 'https://vueflow.dev/', +} + +export default [ + [ + 'meta', + { + name: 'description', + content: meta.description, + }, + ], + ['meta', { hid: 'og:title', name: 'og:title', content: meta.title }], + [ + 'meta', + { + hid: 'og:description', + property: 'og:description', + content: meta.description, + }, + ], + [ + 'meta', + { + hid: 'og:image', + property: 'og:image', + content: `http://${meta.img}`, + }, + ], + [ + 'meta', + { + hid: 'og:image:secure_url', + property: 'og:image:secure_url', + content: `https://${meta.img}`, + }, + ], + [ + 'meta', + { + hid: 'og:image:type', + property: 'og:image:type', + content: 'image/png', + }, + ], + [ + 'meta', + { + hid: 'og:image:width', + property: 'og:image:width', + content: '2428', + }, + ], + [ + 'meta', + { + hid: 'og:image:height', + property: 'og:image:height', + content: '1280', + }, + ], + ['meta', { hid: 'og:url', property: 'og:url', content: meta.url }], + [ + 'meta', + { + hid: 'twitter:card', + name: 'twitter:card', + content: 'summary_large_image', + }, + ], + [ + 'meta', + { + hid: 'twitter:url', + name: 'twitter:url', + content: meta.url, + }, + ], + [ + 'meta', + { + hid: 'twitter:title', + name: 'twitter:title', + content: meta.title, + }, + ], + [ + 'meta', + { + hid: 'twitter:description', + name: 'twitter:description', + content: meta.description, + }, + ], + [ + 'meta', + { + hid: 'twitter:image', + name: 'twitter:image', + content: meta.img, + }, + ], + [ + 'link', + { + hid: 'canonical', + rel: 'canonical', + href: meta.url, + }, + ], + [ + 'link', + { + hid: 'image_src', + rel: 'image_src', + href: meta.img, + }, + ], + ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/favicons/apple-touch-icon.png' }], + ['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicons/favicon-32x32.png' }], + ['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicons/favicon-16x16.png' }], + ['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicons/android-chrome-192x192.png' }], + ['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicons/android-chrome-512x512.png' }], + ['link', { rel: 'manifest', href: '/favicons/site.webmanifest' }], + ['link', { rel: 'shortcut icon', href: '/favicons/favicon.ico' }], + ['meta', { name: 'msapplication-TileColor', content: '#10b981' }], + ['meta', { name: 'theme-color', content: '#10b981' }], +] diff --git a/docs2/src/.vitepress/theme/index.ts b/docs2/src/.vitepress/theme/index.ts new file mode 100644 index 00000000..fdea9ec0 --- /dev/null +++ b/docs2/src/.vitepress/theme/index.ts @@ -0,0 +1,12 @@ +import type { Theme } from 'vitepress' +import VueAnimXyz from '@animxyz/vue3' +import DefaultTheme from 'vitepress/theme' + +const CustomTheme = { + ...DefaultTheme, + enhanceApp: ({ app }) => { + app.use(VueAnimXyz) + }, +} as Theme + +export default CustomTheme diff --git a/docs2/src/.vitepress/theme/layouts/default.vue b/docs2/src/.vitepress/theme/layouts/default.vue new file mode 100644 index 00000000..7bf2b309 --- /dev/null +++ b/docs2/src/.vitepress/theme/layouts/default.vue @@ -0,0 +1,83 @@ + + + + + + + diff --git a/docs2/src/.vitepress/windi.config.ts b/docs2/src/.vitepress/windi.config.ts new file mode 100644 index 00000000..9549961e --- /dev/null +++ b/docs2/src/.vitepress/windi.config.ts @@ -0,0 +1,73 @@ +import { resolve } from 'path' +import { defineConfig } from 'windicss/helpers' +import typography from 'windicss/plugin/typography' +import scrollbar from '@windicss/plugin-scrollbar' + +export default defineConfig({ + extract: { + include: [ + resolve(__dirname, './theme/**/*.{ts,md,vue}'), + resolve(__dirname, '../../components/**/*.{ts,md,vue}'), + resolve(__dirname, '../**/*.{ts,md,vue}'), + ], + }, + + darkMode: 'class', + + plugins: [ + typography({ + dark: true, + }), + scrollbar, + ], + + shortcuts: { + 'primary-gradient': 'bg-gradient-to-b from-accent-500 via-accent-700 to-accent-900', + }, + + theme: { + extend: { + colors: { + primary: { + '50': '#fcf9ff', + '100': '#f8f3ff', + '200': '#eee1fe', + '300': '#e4cffe', + '400': '#cfaafd', + '500': '#BB86FC', + '600': '#a879e3', + '700': '#8c65bd', + '800': '#705097', + '900': '#5c427b', + 'DEFAULT': '#BB86FC', + }, + secondary: { + '50': '#c4fef9', + '100': '#9df7ef', + '200': '#77f0e4', + '300': '#50e8da', + '400': '#2ae1cf', + '500': '#03dac5', + '600': '#03ae9d', + '700': '#028276', + '800': '#02564e', + '900': '#012a26', + 'DEFAULT': '#03dac5', + }, + accent: { + '50': '#e6d4ff', + '100': '#ccaafc', + '200': '#b17ff8', + '300': '#9755f5', + '400': '#7c2af1', + '500': '#6200ee', + '600': '#5000c1', + '700': '#3d0095', + '800': '#2b0068', + '900': '#18003b', + 'DEFAULT': '#6200ee', + }, + }, + }, + }, +}) diff --git a/docs2/src/assets/index.css b/docs2/src/assets/index.css new file mode 100644 index 00000000..9734ccf0 --- /dev/null +++ b/docs2/src/assets/index.css @@ -0,0 +1,111 @@ +:root { + --primary: #BB86FC; + --secondary: #03dac5; +} + +.dark { + --c-text-lighter: white !important; + --c-text: white !important; + --c-bg: black !important; +} + +.dark .tip { + --c-bg-light: gray; +} + +.tip { + --c-bg-light: white; +} + +html, body { + @apply scrollbar scrollbar-thin scrollbar-thumb-rounded scrollbar-thumb-green-500 scrollbar-track-black; +} + +.home { + --content-width: 100%; + max-width: 100% !important; + @apply !px-0; +} + +.page a { + @apply text-green-500 font-semibold; +} + +.examples .page, .examples .page-meta, .footer, .sidebar { + @apply dark:(!bg-black text-white); +} + +.examples .page { + --content-width: 100%; +} + +.theme-default-content { + @apply overflow-scroll md:overflow-hidden; +} + +.navbar { + @apply dark:bg-gray-900; +} + +h1 { + @apply text-xl lg:text-4xl mb-4 font-bold; +} + +h2 { + @apply text-lg lg:text-2xl mb-4 font-semibold; +} + +p { + line-height: inherit; + margin: revert; +} + +ul li { + @apply mt-2; +} + +.docs-button { + @apply z-1 shadow-lg transition-colors duration-200 text-white font-semibold text-lg mt-4 px-5 py-3 rounded-lg bg-green-500; +} + +.vue-flow__node.dark { + @apply bg-gray-800 text-white; +} + +.vue-flow__node-selector { + font-size: 14px; + background: #f0f2f3; + border: 1px solid #555; + border-radius: 5px; + text-align: center; +} + +.vue-flow__node-selector .vue-flow__handle { + border-color: #f0f2f3; +} + +.slider { + --color: red; + @apply bg-gray-200 w-full h-[10px] outline-none rounded-full; + -webkit-appearance: none; + appearance: none; + + &::-moz-range-thumb { + @apply w-[15px] h-[15px] cursor-pointer border-1 border-solid border-white rounded-full; + -webkit-appearance: none; + background: var(--color); + } + &::-webkit-slider-thumb { + @apply w-[15px] h-[15px] cursor-pointer border-1 border-solid border-white rounded-full; + -webkit-appearance: none; + background: var(--color); + } +} + +.theme-container.examples .theme-default-content .vue-repl pre, .theme-default-content .vue-repl pre[class*=language-] { + padding: unset; + margin: unset; + border-radius: unset; + line-height: unset; + +} diff --git a/docs2/src/assets/polygon-scatter.svg b/docs2/src/assets/polygon-scatter.svg new file mode 100644 index 00000000..5b07c11f --- /dev/null +++ b/docs2/src/assets/polygon-scatter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs2/src/examples/dnd.md b/docs2/src/examples/dnd.md new file mode 100644 index 00000000..3f112df2 --- /dev/null +++ b/docs2/src/examples/dnd.md @@ -0,0 +1,24 @@ +--- +pageClass: examples + +--- + +# Drag & Drop + +Adding nodes to an already existing graph can be done multiple ways. To create an interactive editor, you would probably +like them to be inserted with drag and drop. + +In this example we demonstrate how to build a basic Sidebar and implement drag and drop handlers to create new nodes. + +## State access + +This example shows another key feature of Vue Flow. You can initialize the Flow state at any point before the `VueFlow` component +is actually mounted. This can be achieved by using the [`useVueFlow`](/guide/composables.html#usevueflow) composable. + +
+ + + + + +
diff --git a/docs2/src/examples/edges/connection-line.md b/docs2/src/examples/edges/connection-line.md new file mode 100644 index 00000000..1c241cca --- /dev/null +++ b/docs2/src/examples/edges/connection-line.md @@ -0,0 +1,19 @@ +--- +pageClass: examples + +--- + +# Custom Connection Line + +If the default connection lines aren't to your liking, or you want to expand on the existing +functionality you can use your own custom connection line. + +Simply pass a component in the designated template slot, and you're good to go. + +
+ + + + + +
diff --git a/docs2/src/examples/edges/index.md b/docs2/src/examples/edges/index.md new file mode 100644 index 00000000..ad0fb745 --- /dev/null +++ b/docs2/src/examples/edges/index.md @@ -0,0 +1,17 @@ +--- +pageClass: examples + +--- + +# Edges + +Vue Flow comes with four pre-defined edge types - bezier-, step-, smoothstep and straight-edges. +In addition to the built-in edge types you can create your own custom edges. You can find more information on edge types [here](/guide/edge.html#default-edge-types). + +
+ + + + + +
diff --git a/docs2/src/examples/edges/updatable-edge.md b/docs2/src/examples/edges/updatable-edge.md new file mode 100644 index 00000000..7699da5d --- /dev/null +++ b/docs2/src/examples/edges/updatable-edge.md @@ -0,0 +1,22 @@ +--- +pageClass: examples + +--- + +# Updatable Edge + +Existing edges can be updated, meaning their source / target position can be changed interactively. + +Update an edge by simply dragging it from one node to another at the edge-anchor (handles). + +You can enable updating edges either globally by passing the `edgesUpdatable` prop or you can enable it +for specific edges by using the `updatable` attribute. + + +
+ + + + + +
diff --git a/docs2/src/examples/edges/validation.md b/docs2/src/examples/edges/validation.md new file mode 100644 index 00000000..c4037601 --- /dev/null +++ b/docs2/src/examples/edges/validation.md @@ -0,0 +1,39 @@ +--- +pageClass: examples + +--- + +# Connection Validation + +Connections can be validated before edges are created and nodes get connected. + +## Using a handle in a custom node +```vue:no-line-numbers +
+ [ ... ] + + +
+``` + +## Passing as node option +```ts +const nodes = [ + { + id: '1', + label: 'Node 1', + position: { x: 0, y: 0 }, + isValidSourcePos: (connection) => { + return connection.target === '2' + }, + }, +] +``` + +
+ + + + + +
diff --git a/docs2/src/examples/empty.md b/docs2/src/examples/empty.md new file mode 100644 index 00000000..9e265861 --- /dev/null +++ b/docs2/src/examples/empty.md @@ -0,0 +1,17 @@ +--- +pageClass: examples + +--- + +# Empty + +Similar to the drag and drop example, we can also add nodes to an empty graph on a button click, +which triggers a push into our elements / nodes array. + +
+ + + + + +
diff --git a/docs2/src/examples/floating-edges.md b/docs2/src/examples/floating-edges.md new file mode 100644 index 00000000..e713787f --- /dev/null +++ b/docs2/src/examples/floating-edges.md @@ -0,0 +1,25 @@ +--- +pageClass: examples + +--- + +This example demonstrates "floating edges". + +The positions of the source and target nodes are calculated dynamically, +the caveat here is, that edge-anchors are still tied to Handles (even though invisible in this example), +so connections would, by default, only be triggered when hovering over the handles (bottom / top by default). + +
+ + +
diff --git a/docs2/src/examples/hidden.md b/docs2/src/examples/hidden.md new file mode 100644 index 00000000..a3ca4422 --- /dev/null +++ b/docs2/src/examples/hidden.md @@ -0,0 +1,24 @@ +--- +pageClass: examples + +--- + +# Hidden + +You can toggle the visibility of nodes by simply setting their `hidden` attribute to either `true` or `false`. + +Edges that are connected to a hidden node will also be hidden. + +If you set the `onlyRenderVisibleElements` prop to `true`, only elements that are visible inside the current viewpane will be rendered. +This behavior is disabled by default, meaning all elements are rendered whether they are inside the view or not. + +This can save you some time on initial renders but consider that moving the pane can cause multiple renders of nodes into the dom, +which can cause performance spikes depending on the complexity of the components that have to be mounted. + +
+ + + + + +
diff --git a/docs2/src/examples/horizontal.md b/docs2/src/examples/horizontal.md new file mode 100644 index 00000000..30f329ba --- /dev/null +++ b/docs2/src/examples/horizontal.md @@ -0,0 +1,19 @@ +--- +pageClass: examples + +--- + +# Horizontal Layout + +Vue Flow doesn't require you to use vertical layouts. +You can use horizontal layouts with the default node types as well. + +You can define where source or target handle positions are with the `sourcePosition` or `targetPosition` properties of nodes. + +
+ + + + + +
diff --git a/docs2/src/examples/index.md b/docs2/src/examples/index.md new file mode 100644 index 00000000..072bb7fe --- /dev/null +++ b/docs2/src/examples/index.md @@ -0,0 +1,19 @@ +--- +pageClass: examples + +--- + +# Basic + +This is a basic example to help you familiarize with the basic features of Vue Flow. + +On the bottom left you see the viewport-controls and on the bottom right the minimap. +You can also see the built-in node (default, input, output) and edge (bezier, straight, step, smoothstep) types. + +
+ + + + + +
diff --git a/docs2/src/examples/interaction.md b/docs2/src/examples/interaction.md new file mode 100644 index 00000000..228a9d79 --- /dev/null +++ b/docs2/src/examples/interaction.md @@ -0,0 +1,18 @@ +--- +pageClass: examples + +--- +# Interaction + +Vue Flow provides options to interact and limit interaction with the viewport and graph. +This includes enabling/disabling zoom-scroll, pan-scroll, dragging etc. + +In the sandbox below you can find an example showing you how to toggle interaction options. + +
+ + + + + +
diff --git a/docs2/src/examples/multi.md b/docs2/src/examples/multi.md new file mode 100644 index 00000000..48abeb05 --- /dev/null +++ b/docs2/src/examples/multi.md @@ -0,0 +1,18 @@ +--- +pageClass: examples + +--- + +# Multi Flows + +Vue Flow is not limited to a single instance on a page. + +You can use as many component instances as you like. + +
+ + + + + +
diff --git a/docs2/src/examples/nodes/index.md b/docs2/src/examples/nodes/index.md new file mode 100644 index 00000000..eed446db --- /dev/null +++ b/docs2/src/examples/nodes/index.md @@ -0,0 +1,19 @@ +--- +pageClass: examples + +--- + +# Custom Node + +One of the key features of Vue Flow is implementing custom elements (nodes / edges) that allow you to expand on the basic functionalities (dragging, selecting etc). + +You can display any content and functionality inside a custom node. More documentation about how to set +up a custom node can be found on the [custom nodes page](/guide/node.html#custom-nodes). + +
+ + + + + +
diff --git a/docs2/src/examples/nodes/nesting.md b/docs2/src/examples/nodes/nesting.md new file mode 100644 index 00000000..0630efa2 --- /dev/null +++ b/docs2/src/examples/nodes/nesting.md @@ -0,0 +1,20 @@ +--- +pageClass: examples + +--- + +# Nested Nodes + +Another key feature is nested nodes (or even nested flows). + +You can define parents of a node, which are then nested inside that node. +You can also define the boundaries of a node, i.e. if the node can be dragged outside it's parent or if it's contained to the parent +or even let Vue Flow extend the area of a node to fit all it's children. + +
+ + + + + +
diff --git a/docs2/src/examples/nodes/update-node.md b/docs2/src/examples/nodes/update-node.md new file mode 100644 index 00000000..ab6a6f81 --- /dev/null +++ b/docs2/src/examples/nodes/update-node.md @@ -0,0 +1,22 @@ +--- +pageClass: examples + +--- + +# Update Node + +Updating internal node data is simple. +After initializing your elements and parsing them into either `GraphNode` or `GraphEdge` +Vue Flow will emit the changes back into your initial `ref`. + +That means you can manipulate any property of your original nodes, and it will trigger changes in the graph. + +You can of course also access the nodes directly from the state and change their properties from there. + +
+ + + + + +
diff --git a/docs2/src/examples/pinia.md b/docs2/src/examples/pinia.md new file mode 100644 index 00000000..30305b49 --- /dev/null +++ b/docs2/src/examples/pinia.md @@ -0,0 +1,15 @@ +--- +pageClass: examples + +--- + +# Pinia + +Using your existing storage implementation is not an issue. +You can store your elements in whatever store you're already using, mutate them there and pass the result to Vue Flow. + +In this example we use [pinia](https://pinia.vuejs.org/) to store our elements, update their positions and toggle classes. + +
+ +
diff --git a/docs2/src/examples/save.md b/docs2/src/examples/save.md new file mode 100644 index 00000000..87dc09fa --- /dev/null +++ b/docs2/src/examples/save.md @@ -0,0 +1,25 @@ +--- +pageClass: examples + +--- + +# Save & Restore + +There is no built-in persistent storage feature, however you can use your own storage implementation. + +::: tip State Management Libraries + Check the [pinia](/examples/pinia.html) example to see how to use Vue Flow with a state management library. +::: + +This example demonstrates save & restore functionality using the [`LocalStorage`](https://developer.mozilla.org/de/docs/Web/API/Window/localStorage) of the browser. + +You can extend on this basic idea however you like, i.e. fetch data that you transform into elements which are then passed to Vue Flow or +some other business logic you would like to handle. + +
+ + + + + +
diff --git a/docs2/src/examples/stress.md b/docs2/src/examples/stress.md new file mode 100644 index 00000000..ab96f358 --- /dev/null +++ b/docs2/src/examples/stress.md @@ -0,0 +1,18 @@ +--- +pageClass: examples + +--- + +# Stress + +Vue Flow is built to be fast but there are limits. + +Try out how many nodes you can get to render before your browser crashes. + +
+ + + + + +
diff --git a/docs2/src/examples/teleport.md b/docs2/src/examples/teleport.md new file mode 100644 index 00000000..5d769ee4 --- /dev/null +++ b/docs2/src/examples/teleport.md @@ -0,0 +1,16 @@ +--- +pageClass: examples + +--- + +# Teleport + +Teleport your nodes to another dom element using Vue 3 [`Teleport`](https://vuejs.org/guide/built-ins/teleport.html). + +
+ + + + + +
diff --git a/docs2/src/guide/components/background.md b/docs2/src/guide/components/background.md new file mode 100644 index 00000000..1f8b3236 --- /dev/null +++ b/docs2/src/guide/components/background.md @@ -0,0 +1,29 @@ +# Background + +Vue Flow comes with two background pattern variants: dots and lines. + +## Usage + +To use the background simply pass the `Background` component as a child to the `VueFlow` component. + +```vue + +``` + +## [Props](/typedocs/interfaces/BackgroundProps.html/) + +| Name | Definition | Type | Optional | Default | +|--------------|-------------------|--------------------------------------------------------------|----------|---------| +| variant | Pattern variant | [BackgroundVariant](/typedocs/enums/BackgroundVariant.html/) | true | dots | +| gap | Pattern gap | number | true | 10 | +| size | Pattern size | number | true | 0.4 | +| patternColor | Pattern color | string | true | #81818a | +| bgColor | Is node dragging | boolean | true | #fff | +| height | Background height | number | true | 100 | +| width | Background width | number | true | 100 | +| x | X-offset | number | true | 0 | +| y | Y-offset | number | true | 0 | diff --git a/docs2/src/guide/components/control-button.md b/docs2/src/guide/components/control-button.md new file mode 100644 index 00000000..78fd2bb3 --- /dev/null +++ b/docs2/src/guide/components/control-button.md @@ -0,0 +1,26 @@ +# Control Button + +You can use the existing `ControlButton` component to create new control buttons. + +## Usage + +To use the component pass the `ControlButton` component as a child to the [`Controls`](/guide/components/control-button.html/) component. + +```vue + +``` + +## Slots + +| Name | Definition | +|---------|--------------------------------------------------------| +| default | inner slot of btn (is wrapped by a `