feat: use vue-demi manage vue3 and vue2

This commit is contained in:
vector
2021-03-12 16:30:54 +08:00
parent 30a81ff649
commit a96130d126
14 changed files with 44 additions and 567 deletions

View File

@ -36,9 +36,18 @@
"tslint -c tslint.json -p ./tsconfig.json --fix"
]
},
"dependencies": {
"vue-demi": "^0.7.1"
},
"peerDependencies": {
"@antv/x6": ">=1.0.0",
"vue": ">=2.6.11"
"@vue/composition-api": "^1.0.0-rc.2",
"vue": "^2.6.12 || ^3.0.0",
"@antv/x6": ">=1.0.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
@ -58,8 +67,9 @@
"ts-node": "^9.1.1",
"tslint": "^6.1.3",
"typescript": "^4.1.2",
"vue": "^2.6.11",
"watch": "^1.0.2"
"vue": "^3.0.5",
"watch": "^1.0.2",
"@vue/composition-api": "^1.0.0-rc.1"
},
"author": {
"name": "bubkoo",

View File

@ -1,7 +1,7 @@
import { NodeView } from '@antv/x6'
import { VueShape } from './node'
import { VueComponent } from './registry'
import Vue from 'vue'
import { isVue2, isVue3, createApp, h, Vue2 } from 'vue-demi'
export class VueShapeView extends NodeView<VueShape> {
protected init() {
@ -27,29 +27,42 @@ export class VueShapeView extends NodeView<VueShape> {
if (root) {
const component = this.graph.hook.getVueComponent(node)
const div = document.createElement('div')
div.style.width = '100%'
div.style.height = '100%'
let instance = null
if (typeof component === 'string') {
div.innerHTML = component
instance = new Vue({ el: div })
} else {
const { template, ...other } = component as VueComponent
div.innerHTML = template
instance = new Vue({
el: div,
if (isVue2) {
const div = document.createElement('div')
div.style.width = '100%'
div.style.height = '100%'
let instance = null
if (typeof component === 'string') {
div.innerHTML = component
instance = new Vue2({ el: div })
} else {
const { template, ...other } = component as VueComponent
div.innerHTML = template
instance = new Vue2({
el: div,
provide() {
return {
getGraph: () => graph,
getNode: () => node,
}
},
...other,
})
}
root.appendChild(instance.$el)
} else if (isVue3) {
createApp({
render() {
return h(component as any)
},
provide() {
return {
getGraph: () => graph,
getNode: () => node,
}
},
...other,
})
}).mount(root)
}
root.appendChild(instance.$el)
}
}

View File

@ -1,31 +0,0 @@
# @antv/x6-vue3-shape 1.0.0 (2021-03-10)
### Bug Fixes
* 🐛 add propHooks to Vue3Shape.config, fix the issues mentioned in code review ([b1f820f](https://github.com/antvis/x6/commit/b1f820fcc083e4d3d53d7b00ef7b0e5f5db51c5c))
### Features
* ✨ add x6-vue3-shape ([d880fc6](https://github.com/antvis/x6/commit/d880fc6c9497a85e787b1dc336b06d4302f2708c))
### Dependencies
* **@antv/x6:** upgraded to 1.15.0
# @antv/x6-vue3-shape 1.0.0 (2021-03-07)
### Bug Fixes
* 🐛 add propHooks to Vue3Shape.config, fix the issues mentioned in code review ([b1f820f](https://github.com/antvis/x6/commit/b1f820fcc083e4d3d53d7b00ef7b0e5f5db51c5c))
### Features
* ✨ add x6-vue3-shape ([d880fc6](https://github.com/antvis/x6/commit/d880fc6c9497a85e787b1dc336b06d4302f2708c))

View File

@ -1,101 +0,0 @@
# @antv/x6-vue3-shape
> x6 shape for rendering vue3 components
## Installation
```shell
# npm
$ npm install @antv/x6-vue3-shape --save
# yarn
$ yarn add @antv/x6-vue3-shape
```
## Usage
### useGraph
```ts
import { shallowRef, ref, onMounted } from 'vue'
import { Graph } from '@antv/x6'
import '@antv/x6-vue3-shape'
import Comp from './Comp'
export default function useGraph() {
const container = ref<HTMLElement | null>(null)
const graph = shallowRef<Graph | null>()
onMounted(() => {
if (container.value) {
graph.value = new Graph({
container: container.value,
panning: true,
})
graph.value.addNode({
id: 'node1',
x: 40,
y: 40,
width: 100,
height: 40,
shape: 'vue3-shape',
// here are 4 ways usages:
// 1. component: Comp
// 2. component: <Comp />
// 3. component: () => <Comp />
// 4. component: 'text node'
component: Comp,
})
}
})
return {
container,
graph,
}
}
```
### usage in tsx
```tsx
import { defineComponent } from 'vue'
import useGraph from './useGraph'
export default defineComponent({
name: 'Home',
setup() {
const { container } = useGraph()
return () => {
return (
<div class="home">
<div class="home__container" ref={container}></div>
</div>
)
}
}
})
```
### usage in vue sfc
```vue
<template>
<div ref="container">xxx</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import useGraph from './useGraph'
export default defineComponent({
name: 'app',
setup() {
const { container } = useGraph()
return {
container,
}
}
})
</script>
```

View File

@ -1,87 +0,0 @@
{
"name": "@antv/x6-vue3-shape",
"version": "1.0.0",
"description": "X6 shape for rendering vue3 components.",
"main": "lib/index.js",
"module": "es/index.js",
"unpkg": "dist/x6-vue3-shape.js",
"jsdelivr": "dist/x6-vue3-shape.js",
"types": "lib/index.d.ts",
"files": [
"dist",
"es",
"lib"
],
"keywords": [
"shape",
"vue3",
"vue-next",
"render",
"x6",
"antv"
],
"scripts": {
"clean": "rimraf dist es lib",
"lint": "tslint -c tslint.json -p tsconfig.json --fix",
"watch": "watch 'yarn build' ./src",
"build:esm": "tsc --module esnext --target es2015 --outDir ./es",
"build:cjs": "tsc --module commonjs --target es5 --outDir ./lib",
"build:umd": "rollup -c",
"build": "run-p build:cjs build:esm build:umd",
"prebuild": "run-s lint clean",
"prepare": "yarn build",
"precommit": "lint-staged"
},
"lint-staged": {
"src/**/*.ts": [
"tslint -c tslint.json -p ./tsconfig.json --fix"
]
},
"peerDependencies": {
"@antv/x6": ">=1.0.0",
"vue": ">=3.0.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-replace": "^2.3.4",
"@rollup/plugin-typescript": "^8.1.0",
"@types/node": "^14.14.14",
"lint-staged": "^10.5.3",
"npm-run-all": "^4.1.5",
"rimraf": "^3.0.0",
"rollup": "^2.35.1",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-filesize": "^9.1.0",
"rollup-plugin-terser": "^7.0.2",
"sinon": "^7.5.0",
"ts-jest": "^24.0.2",
"ts-node": "^9.1.1",
"tslint": "^6.1.3",
"typescript": "^4.1.2",
"vue": "^3.0.0",
"watch": "^1.0.2"
},
"author": {
"name": "bubkoo",
"email": "bubkoo.wy@gmail.com"
},
"contributors": [],
"license": "MIT",
"homepage": "https://github.com/antvis/x6",
"bugs": {
"url": "https://github.com/antvis/x6/issues"
},
"repository": {
"type": "git",
"url": "ssh://git@github.com/antvis/x6.git",
"directory": "packages/x6-vue3-shape"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"dependencies": {
"vue": "^3.0.7"
}
}

View File

@ -1,31 +0,0 @@
import { terser } from 'rollup-plugin-terser'
import replace from '@rollup/plugin-replace'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import filesize from 'rollup-plugin-filesize'
import typescript from '@rollup/plugin-typescript'
import autoExternal from 'rollup-plugin-auto-external'
export default {
input: './src/index.ts',
output: [
{
name: 'X6VueShape',
format: 'umd',
file: 'dist/x6-vue-shape.js',
sourcemap: true,
globals: {
'@antv/x6': 'X6',
},
},
],
plugins: [
typescript({ declaration: false }),
resolve(),
commonjs(),
replace({ 'process.env.NODE_ENV': JSON.stringify('production') }),
terser(),
filesize(),
autoExternal(),
],
}

View File

@ -1,35 +0,0 @@
import { Graph, FunctionExt } from '@antv/x6'
import { registry, Definition } from './registry'
import { Vue3Shape } from './node'
declare module '@antv/x6/lib/graph/hook' {
namespace Hook {
interface IHook {
getVue3Component(this: Graph, node: Vue3Shape): Definition
}
}
interface Hook {
getVue3Component(node: Vue3Shape): Definition
}
}
Graph.Hook.prototype.getVue3Component = function (node: Vue3Shape) {
const getVue3Component = this.options.getVue3Component
if (typeof getVue3Component === 'function') {
const ret = FunctionExt.call(getVue3Component, this.graph, node)
if (ret != null) {
return ret
}
}
let ret = node.getComponent()
if (typeof ret === 'string') {
const component = registry.get(ret)
if (component == null) {
return registry.onNotFound(ret)
}
ret = component
}
return ret as Definition
}

View File

@ -1,4 +0,0 @@
import './hook'
export * from './node'
export * from './view'
export * from './registry'

View File

@ -1,147 +0,0 @@
import { Node, Markup, ObjectExt } from '@antv/x6'
import { Definition } from './registry'
export class Vue3Shape<
Properties extends Vue3Shape.Properties = Vue3Shape.Properties
> extends Node {
get component() {
return this.getComponent()
}
getComponent(): Vue3Shape.Properties['component'] {
return this.store.get('component')
}
setComponent(
component: Vue3Shape.Properties['component'],
options: Node.SetOptions,
) {
if (component == null) {
this.removeComponent(options)
} else {
this.store.set('component', component, options)
}
return this
}
removeComponent(options: Node.SetOptions = {}) {
this.store.remove('component', options)
return this
}
// static getMarkup: (
// useForeignObject: boolean,
// primer?: Vue3Shape.Primer,
// ) => Markup.JSONMarkup[]
}
export namespace Vue3Shape {
export type Primer =
| 'rect'
| 'circle'
| 'path'
| 'ellipse'
| 'polygon'
| 'polyline'
export interface Properties extends Node.Properties {
primer?: Primer
useForeignObject?: boolean
component?: Definition | string
}
}
function getMarkup(
useForeignObject: boolean,
primer: Vue3Shape.Primer = 'rect',
) {
const markup: Markup.JSONMarkup[] = [
{
tagName: primer,
selector: 'body',
},
]
if (useForeignObject) {
markup.push(Markup.getForeignObjectMarkup())
} else {
markup.push({
tagName: 'g',
selector: 'content',
})
}
markup.push({
tagName: 'text',
selector: 'label',
})
return markup
}
export namespace Vue3Shape {
Vue3Shape.config<Properties>({
view: 'vue3-shape-view',
markup: getMarkup(true),
attrs: {
body: {
fill: 'none',
stroke: 'none',
refWidth: '100%',
refHeight: '100%',
},
fo: {
refWidth: '100%',
refHeight: '100%',
},
label: {
fontSize: 14,
fill: '#333',
refX: '50%',
refY: '50%',
textAnchor: 'middle',
textVerticalAnchor: 'middle',
},
},
propHooks(metadata: Properties) {
if (metadata.markup == null) {
const primer = metadata.primer
const useForeignObject = metadata.useForeignObject
if (primer != null || useForeignObject != null) {
metadata.markup = getMarkup(useForeignObject !== false, primer)
if (primer) {
if (metadata.attrs == null) {
metadata.attrs = {}
}
let attrs = {}
if (primer === 'circle') {
attrs = {
refCx: '50%',
refCy: '50%',
refR: '50%',
}
} else if (primer === 'ellipse') {
attrs = {
refCx: '50%',
refCy: '50%',
refRx: '50%',
refRy: '50%',
}
}
if (primer !== 'rect') {
metadata.attrs = ObjectExt.merge({}, metadata.attrs, {
body: {
refWidth: null,
refHeight: null,
...attrs,
},
})
}
}
}
}
return metadata
},
})
Node.registry.register('vue3-shape', Vue3Shape, true)
}

View File

@ -1,24 +0,0 @@
import { Graph, Node, Registry } from '@antv/x6'
import { DefineComponent } from 'vue'
export type Definition =
| JSX.Element
| DefineComponent
| ((
this: Graph,
node: Node,
) => JSX.Element | DefineComponent | null | undefined)
export const registry = Registry.create<Definition>({
type: 'vue3 component',
})
declare module '@antv/x6/lib/graph/graph' {
namespace Graph {
let registerVue3Component: typeof registry.register
let unregisterVue3Component: typeof registry.unregister
}
}
Graph.registerVue3Component = registry.register
Graph.unregisterVue3Component = registry.unregister

View File

@ -1,5 +0,0 @@
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

View File

@ -1,75 +0,0 @@
import { NodeView } from '@antv/x6'
import { Vue3Shape } from './node'
import { h, createApp, App } from 'vue'
export class Vue3ShapeView extends NodeView<Vue3Shape> {
protected init() {
super.init()
}
getComponentContainer() {
return this.selectors.foContent as HTMLDivElement
}
confirmUpdate(flag: number) {
const ret = super.confirmUpdate(flag)
return this.handleAction(ret, Vue3ShapeView.action, () =>
this.renderVue3Component(),
)
}
protected vue3App: App | null = null
renderVue3Component() {
// unmount
this.unMountVue3Component()
const root = this.getComponentContainer()
const node = this.cell
const graph = this.graph
if (root) {
const component = this.graph.hook.getVue3Component(node)
this.vue3App = createApp({
render() {
return h(component)
},
provide() {
return {
getGraph: () => graph,
getNode: () => node,
}
},
})
this.vue3App.mount(root)
}
}
protected unMountVue3Component() {
const root = this.getComponentContainer()
if (this.vue3App) {
this.vue3App.unmount()
}
return root
}
// @NodeView.dispose()
dispose() {
// this.unMountVue3Component()
NodeView.dispose()
this.unMountVue3Component()
}
}
export namespace Vue3ShapeView {
export const action = 'vue3' as any
Vue3ShapeView.config({
bootstrap: [action],
actions: {
component: action,
},
})
NodeView.registry.register('vue3-shape-view', Vue3ShapeView, true)
}

View File

@ -1,3 +0,0 @@
{
"extends": "../../tsconfig.json",
}

View File

@ -1,3 +0,0 @@
{
"extends": "../../tslint.json"
}