feat: ✨ use vue-demi manage vue3 and vue2
This commit is contained in:
@ -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",
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
@ -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>
|
||||
```
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
@ -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(),
|
||||
],
|
||||
}
|
@ -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
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
import './hook'
|
||||
export * from './node'
|
||||
export * from './view'
|
||||
export * from './registry'
|
@ -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)
|
||||
}
|
@ -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
|
5
packages/x6-vue3-shape/src/shims-vue.d.ts
vendored
5
packages/x6-vue3-shape/src/shims-vue.d.ts
vendored
@ -1,5 +0,0 @@
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
@ -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)
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "../../tslint.json"
|
||||
}
|
Reference in New Issue
Block a user