Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add plugin API #363

Closed
wants to merge 78 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f3732a3
refactor(core)!: update handle styles
bcakmakoglu Feb 17, 2023
fccea17
chore: add changeset
bcakmakoglu Feb 17, 2023
95437ba
chore: fix package versions together
bcakmakoglu Feb 24, 2023
d43421b
refactor(core)!: remove experimental features flag
bcakmakoglu Feb 16, 2023
c89190c
chore: add changeset
bcakmakoglu Feb 24, 2023
0d0d909
refactor(core): `GraphNode`, `GraphEdge` as generic for `findNode`, `…
bcakmakoglu Feb 1, 2023
8e4ef50
chore: add changeset
bcakmakoglu Feb 1, 2023
93bed0d
refactor(core): change generic of `useNode`, `useEdges`
bcakmakoglu Feb 1, 2023
ce9a51d
chore(core): update find action types
bcakmakoglu Mar 17, 2023
ae82180
chore: update changeset
bcakmakoglu Mar 18, 2023
3cd01e5
chore(changeset): enter pre mode
bcakmakoglu Mar 22, 2023
e5bb526
chore(core): cleanup
bcakmakoglu Apr 2, 2023
2ccf133
feat(core): add plugin API
bcakmakoglu Oct 10, 2022
61a81b3
feat(core): add `StoreBase` interface for interface declaration merges
bcakmakoglu Oct 10, 2022
e7e77e7
chore: add changeset
bcakmakoglu Oct 10, 2022
8241f80
chore(core): move `Storage` class to utils dir
bcakmakoglu Oct 10, 2022
04eb4c2
feat(core): add option to set global config
bcakmakoglu Oct 12, 2022
5ea5588
feat(core): add `createVueFlow` helper
bcakmakoglu Oct 12, 2022
ed09a0a
chore(core): optional arg
bcakmakoglu Oct 12, 2022
20d0269
chore(core): plugin hook name
bcakmakoglu Oct 13, 2022
3e12dfd
refactor(core): rename `Storage` to `VueFlowApp`
bcakmakoglu Oct 18, 2022
8d9445d
refactor(core): only install one plugin per `use` call
bcakmakoglu Oct 18, 2022
346508f
tests: add tests for plugin api install
bcakmakoglu Nov 4, 2022
9db1368
chore(core): move `Storage` class to utils dir
bcakmakoglu Oct 10, 2022
e00547e
refactor(core): rename `Storage` to `VueFlowApp`
bcakmakoglu Oct 18, 2022
e2ee96c
feat(plugins): add screenshot plugin
bcakmakoglu Oct 18, 2022
fe8a68d
chore: add changeset
bcakmakoglu Oct 18, 2022
2f08cb6
chore: update readme
bcakmakoglu Oct 18, 2022
2634c9a
chore(plugins): correct gitignore path
bcakmakoglu Nov 4, 2022
171200d
chore(plugins): remove optimizeDeps
bcakmakoglu Nov 4, 2022
718eef5
examples: add screenshot example
bcakmakoglu Nov 4, 2022
2b368d5
feat(plugins): add dagre layout plugin
bcakmakoglu Oct 18, 2022
f19e55b
chore(plugins): correct gitignore path
bcakmakoglu Nov 4, 2022
925e30f
chore(plugins): correct export path
bcakmakoglu Nov 4, 2022
106cf3b
chore(plugins): exclude dagre from dagre plugin
bcakmakoglu Nov 4, 2022
be8002d
examples: use dagre plugin in layouting example
bcakmakoglu Nov 4, 2022
3997228
feat(plugins): add drag and drop plugin pkg
bcakmakoglu Oct 18, 2022
f32cca6
examples: add drag and drop plugin to dnd example
bcakmakoglu Oct 18, 2022
aea641e
chore: add changeset
bcakmakoglu Oct 18, 2022
3da6050
examples: only install one plugin per `use` call
bcakmakoglu Oct 18, 2022
3892563
chore(plugins): project node position on drop
bcakmakoglu Oct 18, 2022
63a40c8
examples: center node on drop
bcakmakoglu Oct 18, 2022
f04415b
chore(plugins): rename shims to `store.ts`
bcakmakoglu Oct 18, 2022
fc21b93
chore(plugins): add README.md
bcakmakoglu Oct 18, 2022
6e4c6ec
chore(plugins): pass store to dnd plugin
bcakmakoglu Oct 18, 2022
3403267
chore(plugins): correct gitignore path
bcakmakoglu Nov 4, 2022
f0e534c
chore: update pnpm-lock.yaml
bcakmakoglu Nov 4, 2022
2d1d2b5
feat(plugins): add `UseScreenshotOptions` to screenshot plugin
bcakmakoglu Nov 5, 2022
2cc990d
refactor(core): use factory function for default vue flow app config
bcakmakoglu Nov 6, 2022
a37c773
chore(examples): update screenshot example
bcakmakoglu Nov 6, 2022
27e19c6
docs: update introduction
bcakmakoglu Nov 6, 2022
7cc435a
docs: add plugin api docs page
bcakmakoglu Nov 6, 2022
ba061e3
chore(plugins): upgrade to vite 3
bcakmakoglu Nov 6, 2022
8da6e9c
chore: update pnpm-lock.yaml
bcakmakoglu Nov 6, 2022
283a541
chore(examples): update layouting example
bcakmakoglu Nov 6, 2022
aa59a5e
chore(additional-components): add grabbing cursor on pannable minimap
bcakmakoglu Nov 6, 2022
0dee635
chore(plugins): update README files
bcakmakoglu Nov 8, 2022
6b2386c
docs: copy plugin README files to docs
bcakmakoglu Nov 8, 2022
0820cf8
chore: update changeset
bcakmakoglu Nov 14, 2022
36aa2d4
feat(plugins): auto-bind `dragOver` and `drop` events to vue flow con…
bcakmakoglu Nov 17, 2022
13ebaf8
chore(examples): cleanup dnd example
bcakmakoglu Nov 17, 2022
e9ddd7a
chore(core): remove explicit imports
bcakmakoglu Dec 8, 2022
7ac40c3
fix(additional-components): use type-fix for `getNodes` in MiniMap
bcakmakoglu Dec 8, 2022
75b0ea0
chore: cleanup
bcakmakoglu Dec 13, 2022
54dd33c
chore: update typedocs config
bcakmakoglu Dec 13, 2022
ff0e812
fix(minimap): var naming
bcakmakoglu Dec 13, 2022
abe70c6
chore: fix slots patch and update package.json
bcakmakoglu Dec 13, 2022
b0b89fc
chore(plugins): use typecasts so typedoc works
bcakmakoglu Dec 13, 2022
3af9e58
refactor(plugin-dagre): use `getNodesInitialized` as layout nodes
bcakmakoglu Dec 19, 2022
78b9da2
feat(plugin-dagre): add `direction` to dagre state
bcakmakoglu Dec 19, 2022
86dda94
feat(plugin-dagre): add option to auto layout elements
bcakmakoglu Dec 19, 2022
f7d205b
chore: cleanup
bcakmakoglu Feb 5, 2023
aba033d
refactor(core,plugins): add extend fn to created hook
bcakmakoglu Feb 21, 2023
921cc6e
refactor(plugins): rename dagre dir to layout
bcakmakoglu Feb 22, 2023
8a47744
chore(plugins): cleanup
bcakmakoglu Feb 22, 2023
def3445
chore(tests): move plugin test files
bcakmakoglu Feb 24, 2023
ce773f4
chore(plugins): install tooling pkgs
bcakmakoglu Mar 22, 2023
3fae582
chore: cleanup
bcakmakoglu Mar 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"repo": "bcakmakoglu/vue-flow"
}
],
"fixed": [],
"fixed": [["@vue-flow/*"]],
"updateInternalDependencies": "patch",
"snapshot": {
"useCalculatedVersion": true
Expand Down
5 changes: 5 additions & 0 deletions .changeset/cool-coats-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vue-flow/plugin-drag-n-drop': major
---

Add drag and drop plugin pkg to help simplify implementing a dnd UI for vue flow
5 changes: 5 additions & 0 deletions .changeset/cyan-melons-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@vue-flow/core": major
---

Remove experimental features flag
5 changes: 5 additions & 0 deletions .changeset/fluffy-pans-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vue-flow/core': major
---

Use `GraphNode` or `GraphEdge` as optional generic types for `findNode` or `findEdge` actions
5 changes: 5 additions & 0 deletions .changeset/hip-melons-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vue-flow/core': major
---

Update handle styles and avoid using fixed pixel positions to offset handle position and instead use transform to align handles
27 changes: 27 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"mode": "pre",
"tag": "next",
"initialVersions": {
"@vue-flow/docs": "1.0.0",
"@vue-flow/examples-nuxt3": "0.0.0",
"@vue-flow/examples-quasar": "0.0.0",
"@vue-flow/examples-vite": "0.0.0",
"@vue-flow/background": "1.0.5",
"@vue-flow/controls": "1.0.4",
"@vue-flow/core": "1.16.5",
"@vue-flow/minimap": "1.0.4",
"@vue-flow/node-resizer": "1.3.0",
"@vue-flow/node-toolbar": "1.0.6",
"@vue-flow/pathfinding-edge": "1.0.5",
"vueflow": "1.0.0",
"@vue-flow/tests": "0.0.0",
"@tooling/eslint-config": "0.0.0",
"@tooling/tsconfig": "0.0.0",
"@tooling/vite-config": "0.0.0"
},
"changesets": [
"cyan-melons-unite.md",
"fluffy-pans-boil.md",
"hip-melons-peel.md"
]
}
5 changes: 5 additions & 0 deletions .changeset/slimy-seas-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vue-flow/plugin-layout': major
---

Add dagre layout plugin pkg
71 changes: 71 additions & 0 deletions .changeset/weak-points-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
'@vue-flow/core': minor

---

Add plugin API to Vue Flow App

## What's changed?

- Allow setting global store config that is applied as default to all stores that are created
- A simple API to extend the vue flow store (⚠️ *NOT* a Vue Plugin)
- Provide hooks to hook into store lifecycle (`beforeCreate`, `created`, `beforeDestroy`, `destroyed`)
- Add some simple plugins to start off
- DnD
- Layout
- Screenshot

## Plugin

```ts
interface PluginHooks {
beforeCreate: EventHookOn<[string, FlowOptions | undefined]>
created: EventHookOn<[VueFlowStore, (plugin: Partial<VueFlowStore>) => void]>
beforeDestroy: EventHookOn<VueFlowStore>
destroyed: EventHookOn<string>
}

type Plugin = (hooks: PluginHooks) => void
```

## Example

```ts
// main.ts or your App entry point
import { createVueFlow, Plugin } from '@vue-flow/core'

const plugin: Plugin = (hooks) => {
hooks.beforeCreate(([id, preloadedState]) => {
// do something before a store instance is created
})

// after a store has been created
hooks.created(([storeInstance, extendFn]) => {})

// before a store is destroyed
hooks.beforeDestroy((storeInstance) => {})

// after a store is destroyed
hooks.destroyed(() => {})
}

// You can pass a factory function to set default values to each new store instance
const vueFlowApp = createVueFlow(() => ({
fitViewOnInit: true,
}))

vueFlowApp.use(plugin)
```

## Extending Store Type (TypeScript)

```ts
// my-shims.d.ts
declare module '@vue-flow/core' {
// the StoreBase interface can be used to extend the VueFlowStore type
interface StoreBase {
myProperty: boolean
myRefProperty: Ref<boolean>
}
}
```
5 changes: 5 additions & 0 deletions .changeset/wild-carrots-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vue-flow/plugin-screenshot': major
---

Add screenshot plugin pkg to create a downloadable image of the graph
56 changes: 8 additions & 48 deletions docs/src/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { resolve } from 'node:path'
import { readdirSync, statSync } from 'node:fs'
import type { DefaultTheme, HeadConfig } from 'vitepress'
import { defineConfigWithTheme } from 'vitepress'
import WindiCSS from 'vite-plugin-windicss'
Expand All @@ -9,56 +8,11 @@ import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import { useVueFlow } from '@vue-flow/core'
import head from './head'
import { copyVueFlowPlugin, files } from './plugins'
import { copyVueFlowPlugin } from './plugins'
import { changelogSidebarEntries, pluginSidebarEntries, typedocSidebarEntries } from './utils'

const { vueFlowVersion } = useVueFlow()

function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
}

function typedocSidebarEntries() {
const filePath = resolve(__dirname, '../typedocs')

const docsModules = readdirSync(filePath).filter((name) => statSync(`${filePath}/${name}`).isDirectory())

return docsModules.map((module) => {
let children = readdirSync(`${filePath}/${module}/`).map<DefaultTheme.SidebarItem>((entry) => ({
text: entry.replace('.md', ''),
link: `/typedocs/${module}/${entry.replace('.md', '')}`,
}))

if (module === 'variables') {
children = children.filter((child) => {
return child.link.includes('default')
})
}

return { text: capitalize(module), collapsed: false, items: children } as DefaultTheme.SidebarItem
})
}

function changelogSidebarEntries(): DefaultTheme.SidebarItem[] {
return [
{
text: 'CHANGELOG',
collapsed: true,
items: files.map((file) => {
const name = file.pkgName.replace('.md', '')
const isCore = name === 'core'

return {
text: name
.split('-')
.map((s) => capitalize(s))
.join(' '),
link: `/changelog/${isCore ? '' : name}`,
}
}),
},
]
}

export default defineConfigWithTheme<DefaultTheme.Config>({
title: 'Vue Flow',
description: 'Visualize your ideas with Vue Flow, a highly customizable Vue3 Flowchart library.',
Expand Down Expand Up @@ -130,6 +84,11 @@ export default defineConfigWithTheme<DefaultTheme.Config>({
link: '/examples/',
activeMatch: '^/examples/',
},
{
text: 'Plugins',
link: '/plugins/',
activeMatch: '^/plugins/',
},
{
text: 'Migration',
link: '/migration/',
Expand Down Expand Up @@ -244,6 +203,7 @@ export default defineConfigWithTheme<DefaultTheme.Config>({
],
'/typedocs/': typedocSidebarEntries(),
'/changelog/': changelogSidebarEntries(),
'/plugins/': pluginSidebarEntries(),
},
},
})
4 changes: 2 additions & 2 deletions docs/src/.vitepress/plugins/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ const getAllFiles = function (dirPath: string, needle?: string, arrayOfFiles: Ch
return arrayOfFiles
}

export const files = getAllFiles(resolve(__dirname, '../../../../packages'), 'CHANGELOG')
export const changelogFiles = getAllFiles(resolve(__dirname, '../../../../packages'), 'CHANGELOG')

const changelogDirPath = resolve(__dirname, `../../changelog/`)

if (!existsSync(changelogDirPath)) {
mkdirSync(changelogDirPath)
}

files.forEach(({ path, pkgName }) => {
changelogFiles.forEach(({ path, pkgName }) => {
const isCore = pkgName === 'core'

const filePath = resolve(__dirname, `${path}`)
Expand Down
1 change: 1 addition & 0 deletions docs/src/.vitepress/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './changelog'
export * from './copy'
export * from './plugins'
41 changes: 41 additions & 0 deletions docs/src/.vitepress/plugins/plugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { copyFile, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs'
import { resolve } from 'node:path'

interface PluginFile {
path: string
pkgName: string
}

const skip = ['node_modules', 'dist', 'turbo']

const getAllFiles = function (dirPath: string, needle?: string, arrayOfFiles: PluginFile[] = [], pkgName?: string) {
readdirSync(dirPath).forEach((file) => {
if (skip.includes(file)) return

if (statSync(`${dirPath}/${file}`).isDirectory()) {
getAllFiles(`${dirPath}/${file}`, needle, arrayOfFiles, file)
} else {
if (file.includes('README')) {
arrayOfFiles.push({ path: `${dirPath}/${file}`, pkgName })
}
}
})

return arrayOfFiles
}

export const pluginFiles = getAllFiles(resolve(__dirname, '../../../../packages/plugins'), 'README')

const pluginDirPath = resolve(__dirname, `../../plugins/`)

if (!existsSync(pluginDirPath)) {
mkdirSync(pluginDirPath)
}

pluginFiles.forEach(({ path, pkgName }) => {
const filePath = resolve(__dirname, `${path}`)

copyFile(filePath, `${pluginDirPath}/${pkgName}.md`, () => {})

console.log(`Copied ${filePath} to ${pluginDirPath}/${pkgName}.md`)
})
70 changes: 70 additions & 0 deletions docs/src/.vitepress/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { resolve } from 'node:path'
import { readdirSync, statSync } from 'node:fs'
import type { DefaultTheme } from 'vitepress'
import { changelogFiles, pluginFiles } from './plugins'

export function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
}

export const typedocSidebarEntries = (): DefaultTheme.SidebarGroup[] => {
const filePath = resolve(__dirname, '../typedocs')

const docsModules = readdirSync(filePath).filter((name) => statSync(`${filePath}/${name}`).isDirectory())

return docsModules.map((module) => {
let children = readdirSync(`${filePath}/${module}/`).map<DefaultTheme.SidebarItem>((entry) => ({
text: entry.replace('.md', ''),
link: `/typedocs/${module}/${entry.replace('.md', '')}`,
}))

if (module === 'variables') {
children = children.filter((child) => {
return child.link.includes('default')
})
}

return { text: capitalize(module), collapsible: true, items: children } as DefaultTheme.SidebarGroup
})
}

export const changelogSidebarEntries = (): DefaultTheme.SidebarGroup[] => {
return [
{
text: 'CHANGELOG',
collapsible: true,
items: changelogFiles.map((file) => {
const name = file.pkgName.replace('.md', '')
const isCore = name === 'core'

return {
text: name
.split('-')
.map((s) => capitalize(s))
.join(' '),
link: `/changelog/${isCore ? '' : name}`,
}
}),
},
]
}

export const pluginSidebarEntries = (): DefaultTheme.SidebarGroup[] => {
return [
{
text: 'Plugins',
collapsible: true,
items: pluginFiles.map((file) => {
const name = file.pkgName.replace('.md', '')

return {
text: name
.split('-')
.map((s) => capitalize(s))
.join(' '),
link: `/plugins/${name}`,
}
}),
},
]
}
12 changes: 6 additions & 6 deletions docs/src/guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ Check out the [examples](/examples/) if you want to dive directly into the code.

- 👶 __Easy setup__: Get started hassle-free - Built-in zoom- & pan features, element dragging, selection and much more

- 🎨 __Customizable__: Use your own custom nodes, edges, connection lines and expand on the Vue Flows functionality
- 🎨 __Customizable__: Use your own custom nodes, edges, connection-lines and a multitude of plugins to extend the functionality of Vue Flow

- 🚀 __Fast__: Tracks changes reactively and only re-renders the appropriate elements

- 🧲 __Utils & Composition__: Comes with graph helper and state composable functions for advanced uses
- 🧲 __Utils & Composition__: Built for Composition API and comes with a set of useful utilities to make your life easier

- 📦 __Additional Components__:

- 🖼 Background: With two built-in patterns and some configuration options like height, width or color.
- 🖼 Background: With two built-in patterns (grid & dots) and the ability to add your own custom background shapes

- 🧭 Minimap: Shows current nodes in a small map shape in the bottom right corner
- 🧭 Interactive Minimap: Shows current nodes in a small map shape and allows dragging or zooming the viewport using the mini map

- 🕹 Controls: Control zoom behavior from a panel on the bottom left
- 🕹 Controls: A panel with buttons to zoom in, zoom out, fit the view or lock interaction. You can also add your own custom controls to the panel.

- 🦾 __Reliable__: Fully written in TypeScript
- 🦾 __Reliable__: Fully written in TypeScript and tested with Cypress 10
Loading
Loading