Compare commits

...

28 Commits

Author SHA1 Message Date
2571cb4ceb chore: update license (#3309) 2023-02-27 16:19:16 +08:00
d83bcea863 chore: update contributors [skip ci] 2023-02-27 07:59:22 +00:00
38bdf65dde feat: support angular shape for 2.x (#3278)
* feat: add angular shape

* docs: add angular shape docs

* docs: update docs

* fix: 修复无法在 shape 内部安装依赖的问题
2023-02-27 15:59:01 +08:00
f5db2bb415 chore: update contributors [skip ci] 2023-02-27 07:43:52 +00:00
a3aa2a0da2 fix: fix editor-tool for edge (#3308) 2023-02-27 15:43:29 +08:00
2bce01dee8 chore: update CONTRIBUTORS [skip ci] 2023-02-27 03:42:56 +00:00
a30b6632a0 feat: add view:mounted and view:unmounted event (#3307) 2023-02-27 11:41:22 +08:00
7656b38735 fix: cannot be invoked without new (#3296)
fix Class constructor xx cannot be invoked without 'new'
2023-02-27 11:35:37 +08:00
d953a732b3 chore(release): release 1 package [skip ci]
[@antv/x6-sites@1.5.5](https://github.com/antvis/X6/releases/tag/%40antv/x6-sites%401.5.5)
2023-02-27 03:05:34 +00:00
6317493347 docs: optimize examples style for doc (#3306) 2023-02-27 10:54:45 +08:00
8fc0b72b66 chore: update contributors [skip ci] 2023-02-27 01:29:39 +00:00
18fca29bd7 chore: update contributors [skip ci] 2023-02-24 12:33:15 +00:00
7e61014b65 docs: set version list to 2.x and 1.x (#3301) 2023-02-24 20:32:48 +08:00
8dd2b66633 chore(release): release 3 packages [skip ci]
[@antv/x6-common@2.0.10](https://www.npmjs.com/package/@antv/x6-common/v/2.0.10)
[@antv/x6-common@2.0.10](https://github.com/antvis/X6/releases/tag/%40antv/x6-common%402.0.10)

[@antv/x6-plugin-transform@2.1.6](https://www.npmjs.com/package/@antv/x6-plugin-transform/v/2.1.6)
[@antv/x6-plugin-transform@2.1.6](https://github.com/antvis/X6/releases/tag/%40antv/x6-plugin-transform%402.1.6)

[@antv/x6-sites@1.5.4](https://github.com/antvis/X6/releases/tag/%40antv/x6-sites%401.5.4)
2023-02-24 08:56:41 +00:00
76fb1acf74 fix: add textLength & lengthAdjust to CASE_SENSITIVE_ATTR (#3281) 2023-02-24 16:45:35 +08:00
709a141e28 fix: transform active-handle class should remove when active removed (#3298)
fix: transform
2023-02-24 16:42:49 +08:00
2ee81fd94b chore: update CONTRIBUTORS [skip ci] 2023-02-23 15:00:09 +00:00
054eb998fa chore: update contributors [skip ci] 2023-02-23 14:53:56 +00:00
e32227ae31 docs: fix warning display style (#3294) 2023-02-23 22:53:33 +08:00
278b798c0a chore: update CONTRIBUTORS [skip ci] 2023-02-23 13:37:37 +00:00
c4e11dc98f chore: update contributors [skip ci] 2023-02-23 13:29:51 +00:00
df8466aa33 doc: 修复graph文档 (#3293) 2023-02-23 21:29:31 +08:00
1b958d626f chore: release x6@2.5.1 (#3284) 2023-02-23 11:17:21 +08:00
946582c242 fix: add judgment for edge view (#3282) 2023-02-23 11:12:42 +08:00
482d77ad09 chore(release): release 1 package [skip ci]
[@antv/x6-sites@1.5.3](https://github.com/antvis/X6/releases/tag/%40antv/x6-sites%401.5.3)
2023-02-23 03:01:42 +00:00
3103c11991 chore: change docsearch appid (#3280) 2023-02-23 10:50:48 +08:00
3c9093f3ec chore: release 2 packages (#3279) 2023-02-23 10:50:29 +08:00
8a89caab27 chore: update contributors [skip ci] 2023-02-23 01:29:28 +00:00
64 changed files with 44863 additions and 18565 deletions

View File

@ -15,6 +15,7 @@ James Tsang <wtzeng1@gmail.com>
Jógvan Olsen <jogvanolsen@hotmail.com>
Ken Geis <geis.ken@gmail.com>
Kent Wood <minzojian@hotmail.com>
Ko.Rei <32183014+Ko-Rei@users.noreply.github.com>
Limbo <49612796+JUST-Limbo@users.noreply.github.com>
Lixu <37231473+wflixu@users.noreply.github.com>
Lloyd Zhou <lloydzhou@users.noreply.github.com>
@ -69,6 +70,7 @@ newbyvector <vectorse@126.com>
niexq <1879633916@qq.com>
niexq <niexq@firstgrid.cn>
njshuisheng <34205271+njshuisheng@users.noreply.github.com>
nobugforever <84232410+mengYu-Jin@users.noreply.github.com>
pengxingjian.pxj <pengxingjian.pxj@alibaba-inc.com>
pfdgithub <pfdgithub@users.noreply.github.com>
qingchi <qinky94@163.com>
@ -81,6 +83,7 @@ wenbei <38773084+wb-wenbei@users.noreply.github.com>
wgf <34190465+evelope@users.noreply.github.com>
wind X <35559153+XueMeijing@users.noreply.github.com>
wjqsummer <52412389+wjqsummer@users.noreply.github.com>
wseven7677 <caoyu_92@126.com>
wtzeng1 <wtzeng1@gmail.com>
x6-bot <x6-bot@users.noreply.github.com>
xrkffgg <xrkffgg@gmail.com>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

View File

@ -51,7 +51,7 @@
"prettier --write --ignore-unknown"
],
"*.less": [
"stylelint --syntax less --fix"
"stylelint --customSyntax postcss-less --fix"
],
"*.js": [
"prettier --write"

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,136 @@
# @antv/x6-angular-shape
## 渲染节点
我们提供了一个独立的包 `@antv/x6-angular-shape` 以支持将 Angular 的组件/模板作为节点进行渲染。
### Component 渲染
```ts
@Component({
selector: 'app-node',
templateUrl: './node.component.html',
styleUrls: ['./node.component.scss'],
})
export class NodeComponent implements AfterViewInit, OnChanges {
@Input() value: string;
}
```
```ts
import { register } from "@antv/x6-angular-shape";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements AfterViewInit {
ngAfterViewInit(): void {
register({
shape: 'custom-angular-component-node',
width: 120,
height: 20,
content: NodeComponent,
injector: this.injector,
});
this.graph.addNode({
shape: 'custom-angular-component-node',
x: 100,
y: 100,
data: {
// Input 的参数必须放在这里
ngArguments: {
value: '糟糕糟糕 Oh my god',
},
},
});
}
}
```
### TemplateRef 渲染
```html
<ng-template #template let-data="ngArguments">
<section class="template-container">
<span class="value">{{ data.value }}</span>
</section>
</ng-template>
```
```ts
import { register } from "@antv/x6-angular-shape";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements AfterViewInit {
@ViewChild('template') template: TemplateRef<{}>;
ngAfterViewInit(): void {
register({
shape: 'custom-angular-template-node',
width: 120,
height: 20,
content: this.template,
injector: this.injector,
});
this.graph.addNode({
shape: 'custom-angular-template-node',
x: 100,
y: 100,
data: {
ngArguments: {
value: '魔法怎么失灵啦',
},
},
});
}
}
```
## 更新节点
无论是使用 Component 还是 TemplateRef, 都是一样的更新方式.
```ts
node.setData({
ngArguments: {
value: '晚风中闪过 几帧从前啊',
},
});
```
## 有 demo 吗?
有的, 因为X6渲染节点部分与框架是解耦的. 因此 `x6-angular-shape` 包并非是直接在源代码里改的, 而是在一个单独的Angular环境中开发的. 该 demo 还提供了多种节点类型的性能测试, 详情请参考[Eve-Sama/x6-angular-shape](https://github.com/Eve-Sama/x6-angular-shape)、[X6与G6的性能对比, 以及X6多节点类型下的FPS临界点讨论](https://github.com/antvis/X6/issues/3266)
## FAQ
### 为什么输入属性不能直接放在 data 中而需要放在 ngArguments 中? 且为什么不叫 ngInput?
因为并非所有 `node.data` 中的属性都是输入属性, 所以遍历 `data` 中的所有属性进行赋值是不合适的. 至于为什么叫 `ngArguments` 主要是有两点考虑.
- 1.x版本中已经这么用了, 沿用该API可以降低用户升级成本
- `Input` 的概念其实是来自 `Component`, 而 `TemplateRef` 中是 `context`, 在二者的基础上抽象一个 `Arguments` 的概念更通用些
### 2.x版本的 x6-angular-shape 相比较1.x版本有什么新特性吗?
实现思路其实和之前是差不多的. 但是确实有几个点值得一提.
#### demo更聚焦
1.x版本的 demo 除了渲染组件外, 还写了连线、清除等一系列案例. 看似扩展, 实则眼花缭乱. 作为 `x6-angular-shape`的 demo, 2.x版本更加聚焦, 更加聚焦于shape的使用与性能测试等, 与插件无关的内容请查看X6官网.
#### 功能更稳定
在1.x版本中, 虽然实现了功能, 但是使用场景的思考不够全面. 比如`ngArguments`的变化, 对 `TemplateRef`的场景并不生效. 虽然对`Component`生效但是无法触发`ngOnChanges`. 而在新版本中, 这些问题都将不复存在.
### 版本要求
你的Angular版本至少在14及以上才可以. 14以下需要用 hack 的方式实现一些特性, 比较麻烦. 暂时不提供, 如有需要可提issue, 我再专门介绍下如何实现.

View File

@ -0,0 +1,65 @@
{
"name": "@antv/x6-angular-shape",
"version": "2.0.0",
"description": "X6 shape for rendering angular components.",
"main": "lib/index.js",
"module": "es/index.js",
"unpkg": "dist/index.js",
"jsdelivr": "dist/index.js",
"types": "lib/index.d.ts",
"files": [
"dist",
"es",
"lib"
],
"keywords": [
"shape",
"angular",
"render",
"x6",
"antv"
],
"scripts": {
"clean:turbo": "rss",
"clean:build": "rss",
"clean:coverage": "rss",
"clean": "rss",
"build:esm": "rss",
"build:cjs": "rss",
"build:umd": "rss",
"build:dev": "rss",
"build:watch": "rss",
"build:watch:esm": "rss",
"build:watch:cjs": "rss",
"build": "rss",
"prebuild": "rss",
"test": "rss",
"coveralls": "rss",
"pretest": "rss"
},
"peerDependencies": {
"@antv/x6": "^2.x",
"@angular/core": ">= 14"
},
"devDependencies": {
"@antv/x6": "^2.x"
},
"author": {
"name": "Eve-Sama",
"email": "948832626@qq.com"
},
"license": "MIT",
"homepage": "https://x6.antv.antgroup.com/tutorial/intermediate/angular",
"bugs": {
"url": "https://github.com/antvis/x6/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/antvis/x6.git",
"directory": "packages/x6-angular-shape"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
}
}

View File

@ -0,0 +1,3 @@
export * from './node'
export * from './view'
export * from './registry'

View File

@ -0,0 +1,102 @@
import { Node, Markup, ObjectExt } from '@antv/x6'
export class AngularShape<
Properties extends AngularShape.Properties = AngularShape.Properties,
> extends Node<Properties> {}
export namespace AngularShape {
export type Primer =
| 'rect'
| 'circle'
| 'path'
| 'ellipse'
| 'polygon'
| 'polyline'
export interface Properties extends Node.Properties {
primer?: Primer
}
}
export namespace AngularShape {
function getMarkup(primer?: Primer) {
const markup: Markup.JSONMarkup[] = []
const content = Markup.getForeignObjectMarkup()
if (primer) {
markup.push(
...[
{
tagName: primer,
selector: 'body',
},
content,
],
)
} else {
markup.push(content)
}
return markup
}
AngularShape.config<Properties>({
view: 'angular-shape-view',
markup: getMarkup(),
attrs: {
body: {
fill: 'none',
stroke: 'none',
refWidth: '100%',
refHeight: '100%',
},
fo: {
refWidth: '100%',
refHeight: '100%',
},
},
propHooks(metadata: Properties) {
if (metadata.markup == null) {
const primer = metadata.primer
if (primer) {
metadata.markup = getMarkup(primer)
let attrs = {}
switch (primer) {
case 'circle':
attrs = {
refCx: '50%',
refCy: '50%',
refR: '50%',
}
break
case 'ellipse':
attrs = {
refCx: '50%',
refCy: '50%',
refRx: '50%',
refRy: '50%',
}
break
default:
break
}
metadata.attrs = ObjectExt.merge(
{},
{
body: {
refWidth: null,
refHeight: null,
...attrs,
},
},
metadata.attrs || {},
)
}
}
return metadata
},
})
Node.registry.register('angular-shape', AngularShape, true)
}

View File

@ -0,0 +1,32 @@
import { Injector, TemplateRef, Type } from '@angular/core'
import { Graph, Node } from '@antv/x6'
export type Content = TemplateRef<any> | Type<any>
export type AngularShapeConfig = Node.Properties & {
shape: string
injector: Injector
content: Content
}
export const registerInfo: Map<
string,
{
injector: Injector
content: Content
}
> = new Map()
export function register(config: AngularShapeConfig) {
const { shape, injector, content, ...others } = config
registerInfo.set(shape, { injector, content })
Graph.registerNode(
shape,
{
inherit: 'angular-shape',
...others,
},
true,
)
}

View File

@ -0,0 +1,124 @@
import {
ComponentRef,
EmbeddedViewRef,
TemplateRef,
ViewContainerRef,
} from '@angular/core'
import { Dom, NodeView } from '@antv/x6'
import { AngularShape } from './node'
import { Content, registerInfo } from './registry'
export class AngularShapeView extends NodeView<AngularShape> {
getNodeContainer(): HTMLDivElement {
return this.selectors && (this.selectors.foContent as HTMLDivElement)
}
override confirmUpdate(flag: number): number {
const ret = super.confirmUpdate(flag)
return this.handleAction(ret, AngularShapeView.action, () =>
this.renderAngularContent(),
)
}
private getNgArguments(): Record<string, any> {
const input = (this.cell.data?.ngArguments as Record<string, any>) || {}
return input
}
/** 当执行 node.setData() 时需要对实例设置新的输入值 */
private setInstanceInput(
content: Content,
ref: EmbeddedViewRef<any> | ComponentRef<any>,
): void {
const ngArguments = this.getNgArguments()
if (content instanceof TemplateRef) {
const embeddedViewRef = ref as EmbeddedViewRef<any>
embeddedViewRef.context = { ngArguments }
} else {
const componentRef = ref as ComponentRef<any>
Object.keys(ngArguments).forEach((v) =>
componentRef.setInput(v, ngArguments[v]),
)
componentRef.changeDetectorRef.detectChanges()
}
}
protected renderAngularContent(): void {
this.unmountAngularContent()
const container = this.getNodeContainer()
if (container) {
const node = this.cell
const { injector, content } = registerInfo.get(node.shape)!
const viewContainerRef = injector.get(ViewContainerRef)
if (content instanceof TemplateRef) {
const ngArguments = this.getNgArguments()
const embeddedViewRef = viewContainerRef.createEmbeddedView(content, {
ngArguments,
})
embeddedViewRef.rootNodes.forEach((node) => container.appendChild(node))
embeddedViewRef.detectChanges()
node.on('change:data', () =>
this.setInstanceInput(content, embeddedViewRef),
)
} else {
const componentRef = viewContainerRef.createComponent(content)
const insertNode = (componentRef.hostView as EmbeddedViewRef<any>)
.rootNodes[0] as HTMLElement
container.appendChild(insertNode)
this.setInstanceInput(content, componentRef)
node.on('change:data', () =>
this.setInstanceInput(content, componentRef),
)
}
}
}
protected unmountAngularContent(): HTMLDivElement {
const container = this.getNodeContainer()
container.innerHTML = ''
return container
}
override onMouseDown(e: Dom.MouseDownEvent, x: number, y: number) {
const target = e.target as Element
const tagName = target.tagName.toLowerCase()
if (tagName === 'input') {
const type = target.getAttribute('type')
if (
type == null ||
[
'text',
'password',
'number',
'email',
'search',
'tel',
'url',
].includes(type)
) {
return
}
}
super.onMouseDown(e, x, y)
}
override unmount(): this {
this.unmountAngularContent()
super.unmount()
return this
}
}
export namespace AngularShapeView {
export const action = 'angular' as any
AngularShapeView.config({
bootstrap: [action],
actions: {
component: action,
},
})
NodeView.registry.register('angular-shape-view', AngularShapeView, true)
}

View File

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

View File

@ -1,3 +1,10 @@
## @antv/x6-common [2.0.10](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.9...@antv/x6-common@2.0.10) (2023-02-24)
### Bug Fixes
* add textLength & lengthAdjust to CASE_SENSITIVE_ATTR ([#3281](https://github.com/antvis/x6/issues/3281)) ([76fb1ac](https://github.com/antvis/x6/commit/76fb1acf74b0f1c308f7c824d02c12244b7ac8f3))
## @antv/x6-common [2.0.8](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.7...@antv/x6-common@2.0.8) (2023-02-18)

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-common",
"version": "2.0.8",
"version": "2.0.10",
"description": "Basic toolkit for X6",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -6,6 +6,8 @@ export const CASE_SENSITIVE_ATTR = [
'attributeName',
'attributeType',
'repeatCount',
'textLength',
'lengthAdjust',
]
export type Attributes = { [key: string]: string | number | null | undefined }

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,3 +1,10 @@
## @antv/x6-plugin-transform [2.1.6](https://github.com/antvis/x6/compare/@antv/x6-plugin-transform@2.1.5...@antv/x6-plugin-transform@2.1.6) (2023-02-24)
### Bug Fixes
* transform active-handle class should remove when active removed ([#3298](https://github.com/antvis/x6/issues/3298)) ([709a141](https://github.com/antvis/x6/commit/709a141e28e9f25d54ece0ade353bd343ac0e55f))
## @antv/x6-plugin-transform [2.1.5](https://github.com/antvis/x6/compare/@antv/x6-plugin-transform@2.1.4...@antv/x6-plugin-transform@2.1.5) (2022-12-24)

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-transform",
"version": "2.1.5",
"version": "2.1.6",
"description": "transform plugin for X6",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -493,7 +493,7 @@ export class TransformImpl extends View<TransformImpl.EventArgs> {
Dom.removeClass(this.container, `${this.containerClassName}-active`)
if (this.handle) {
Dom.removeClass(this.handle, `${this.containerClassName}-active`)
Dom.removeClass(this.handle, `${this.containerClassName}-active-handle`)
const pos = this.handle.getAttribute(
'data-position',

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2022 Alipay.inc
Copyright (c) 2021-2023 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
{
"name": "@antv/x6",
"version": "2.3.0",
"version": "2.5.1",
"description": "JavaScript diagramming library that uses SVG and HTML for rendering",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -1,6 +1,7 @@
import { Dom } from '@antv/x6-common'
import { Model } from '../model'
import { CellView } from '../view'
import { Scheduler } from '../renderer/scheduler'
interface CommonEventArgs<E> {
e: E
@ -13,7 +14,8 @@ interface PositionEventArgs<E> extends CommonEventArgs<E> {
export interface EventArgs
extends Omit<Model.EventArgs, 'sorted' | 'updated' | 'reseted'>,
CellView.EventArgs {
CellView.EventArgs,
Scheduler.EventArgs {
'model:sorted'?: Model.EventArgs['sorted']
'model:updated': Model.EventArgs['updated']
'model:reseted': Model.EventArgs['reseted']

View File

@ -92,6 +92,7 @@ export class CellEditor extends ToolsView.ToolItem<
index: this.labelIndex,
})
}
editor.innerText = text || ''
// clear display value when edit status because char ghosting.
@ -105,7 +106,8 @@ export class CellEditor extends ToolsView.ToolItem<
const cell = this.cell
const value = this.editor.innerText.replace(/\n$/, '') || ''
// set value
this.setCellText(value)
// when value is null, we will remove label in edge
this.setCellText(value !== '' ? value : null)
// remove tool
cell.removeTool(cell.isEdge() ? 'edge-editor' : 'node-editor')
this.undelegateDocumentEvents()
@ -137,7 +139,7 @@ export class CellEditor extends ToolsView.ToolItem<
}
}
setCellText(value: string) {
setCellText(value: string | null) {
const setText = this.options.setText
if (typeof setText === 'function') {
FunctionExt.call(setText, this.cellView, {
@ -170,7 +172,7 @@ export namespace CellEditor {
this: CellView,
args: {
cell: Cell
value: string
value: string | null
index?: number
distance?: number
},
@ -204,7 +206,9 @@ export namespace CellEditor {
return cell.attr('text/text')
},
setText({ cell, value }) {
cell.attr('text/text', value)
if (value !== null) {
cell.attr('text/text', value)
}
},
})
@ -225,18 +229,20 @@ export namespace CellEditor {
setText({ cell, value, index, distance }) {
const edge = cell as Edge
if (index === -1) {
edge.appendLabel({
position: {
distance: distance!,
},
attrs: {
label: {
text: value,
},
},
})
} else {
if (value) {
edge.appendLabel({
position: {
distance: distance!,
},
attrs: {
label: {
text: value,
},
},
})
}
} else {
if (value !== null) {
edge.prop(`labels/${index}/attrs/label/text`, value)
} else if (typeof index === 'number') {
edge.removeLabelAt(index)

View File

@ -313,6 +313,7 @@ export class Scheduler extends Disposable {
}
viewItem.state = Scheduler.ViewState.MOUNTED
this.graph.trigger('view:mounted', { view })
}
}
@ -334,6 +335,7 @@ export class Scheduler extends Disposable {
if (view) {
viewItem.view.remove()
delete this.willRemoveViews[cell.id]
this.graph.trigger('view:unmounted', { view })
}
}
@ -450,9 +452,13 @@ export class Scheduler extends Disposable {
for (let i = 0, n = edges.length; i < n; i += 1) {
const edge = edges[i]
const viewItem = this.views[edge.id]
const edgeView = viewItem.view
if (!viewItem || !this.isViewMounted(edgeView)) {
if (!viewItem) {
continue
}
const edgeView = viewItem.view
if (!this.isViewMounted(edgeView)) {
continue
}
@ -532,4 +538,9 @@ export namespace Scheduler {
options: any
state: ViewState
}
export interface EventArgs {
'view:mounted': { view: CellView }
'view:unmounted': { view: CellView }
}
}

62166
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
import { defineConfig } from 'dumi'
import { repository, version } from './package.json'
import { repository } from './package.json'
export default defineConfig({
locales: [
@ -22,7 +22,7 @@ export default defineConfig({
showChartResize: true, // 是否在 demo 页展示图表视图切换
showAPIDoc: false, // 是否在 demo 页展示API文档
versions: {
[version]: 'https://x6.antv.antgroup.com',
'2.x': 'https://x6.antv.antgroup.com',
'1.x': 'https://x6.antv.vision',
},
navs: [
@ -288,8 +288,10 @@ export default defineConfig({
},
],
docsearchOptions: {
apiKey: 'fe8bee8366e56a9463229c3c81200866',
indexName: 'antv_x6',
appId: '7J0MWEOGMO',
apiKey: 'e0d8089bb224298dfd4415b3e98bb700',
indexName: 'x6_sites_2.0',
versionV3: true,
},
playground: {
extraLib: '',

View File

@ -1,3 +1,9 @@
## @antv/x6-sites [1.5.5](https://github.com/antvis/x6/compare/@antv/x6-sites@1.5.4...@antv/x6-sites@1.5.5) (2023-02-27)
## @antv/x6-sites [1.5.4](https://github.com/antvis/x6/compare/@antv/x6-sites@1.5.3...@antv/x6-sites@1.5.4) (2023-02-24)
## @antv/x6-sites [1.5.3](https://github.com/antvis/x6/compare/@antv/x6-sites@1.5.2...@antv/x6-sites@1.5.3) (2023-02-23)
## @antv/x6-sites [1.5.2](https://github.com/antvis/x6/compare/@antv/x6-sites@1.5.1...@antv/x6-sites@1.5.2) (2023-02-18)
# @antv/x6-sites [1.5.0](https://github.com/antvis/x6/compare/@antv/x6-sites@1.4.1...@antv/x6-sites@1.5.0) (2023-02-06)

View File

@ -241,8 +241,9 @@ getBBox(): Rectangle
返回边的包围盒。
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该方法通过边的端点和路径点计算包围盒,并不是渲染到画布后的包围盒,涉及的计算只是一些算数运算。
:::
#### getPolyline()

View File

@ -247,8 +247,9 @@ getBBox(options: { deep?: boolean }): Rectangle
获取节点的包围盒。
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该方法通过节点的大小和位置计算包围盒,并不是渲染到画布后的包围盒,涉及的计算只是一些算数运算。
:::
<span class="tag-param">参数<span>

View File

@ -78,8 +78,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的宽度是参照宽度百分之多少。例如 `refWidth: 0.75` 表示元素的宽度是参照宽度的 `75%`
- 当其值 `<0``>1` 时,表示元素的宽度在参照宽度的基础上减少或增加多少。例如 `refWidth: 20` 表示元素比相对元素宽 `20px`
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持宽度 `width` 和高度 `height` 的元素,如 `<rect>` 元素。
:::
### refWidth2
@ -101,8 +102,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的高度是参照高度百分之多少。例如 `refHeight: 0.75` 表示元素的高度是参照高度的 `75%`
- 当其值 `<0``>1` 时,表示元素的高度在参照高度的基础上减少或增加多少。例如 `refHeight: 20` 表示元素比相对元素高 `20px`
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持宽度 `width` 和高度 `height` 的元素,如 `<rect>` 元素。
:::
### refHeight2
@ -124,8 +126,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `cx` 是参照宽度百分之多少。例如 `refCx: 0.75` 表示元素中心 `x` 坐标位于参照宽度的 `75%` 处。
- 当其值 `<0``>1` 时,表示元素的 `cx` 是在参照宽度的基础上减少或增加多少。例如 `refCx: 20` 表示元素中心 `x` 坐标位于参照宽度加 `20px` 处。
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持 `cx``cy` 属性的元素,如 `<ellipse>` 元素。
:::
### refCy
@ -134,8 +137,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `cy` 是参照高度百分之多少。例如 `refCy: 0.75` 表示元素中心 `y` 坐标位于参照高度的 `75%` 处。
- 当其值 `<0``>1` 时,表示元素的 `cy` 是在参照宽度的基础上减少或增加多少。例如 `refCy: 20` 表示元素中心 `y` 坐标位于参照高度加 `20px` 处。
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持 `cx``cy` 属性的元素,如 `<ellipse>` 元素。
:::
### refRx
@ -144,8 +148,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `rx` 是参照宽度百分之多少。例如 `refRx: 0.75` 表示元素的 `rx` 是参照宽度的 `75%`
- 当其值 `<0``>1` 时,表示元素的 `rx` 是在参照宽度的基础上减少或增加多少。例如 `refRx: 20` 表示元素的 `rx` 是参照宽度加 `20px`
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持 `rx``ry` 属性的元素,如 `<rect>` 元素。
:::
### refRy
@ -154,8 +159,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `ry` 是参照高度百分之多少。例如 `refRy: 0.75` 表示元素的 `ry` 是参照高度的 `75%`
- 当其值 `<0``>1` 时,表示元素的 `ry` 是在参照宽度的基础上减少或增加多少。例如 `refRy: 20` 表示元素的 `ry` 是参照高度加 `20px`
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持 `rx``ry` 属性的元素,如 `<rect>` 元素。
:::
### refRCircumscribed
@ -164,8 +170,9 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示 `r` 是参照长度百分之多少。例如 `refRCircumscribed: 0.75` 表示 `r` 是参照长度的 `75%`
- 当其值 `<0``>1` 时,表示 `r` 是在参照长度的基础上减少或增加多少。例如 `refRCircumscribed: 20` 表示 `r` 是参照长度加 `20px`
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持 `r` 属性的元素,如 `<rect>` 元素。
:::
### refRInscribed
@ -176,8 +183,9 @@ _简称_**`refR`**
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示 `r` 是参照长度百分之多少。例如 `refRInscribed: 0.75` 表示 `r` 是参照长度的 `75%`
- 当其值 `<0``>1` 时,表示 `r` 是在参照长度的基础上减少或增加多少。例如 `refRInscribed: 20` 表示 `r` 是参照长度加 `20px`
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该属性只适用于那些支持 `r` 属性的元素,如 `<rect>` 元素。
:::
### refDKeepOffset
@ -561,8 +569,9 @@ edge.attr("connection/sourceMarker", {
适用于所有 `<path>` 元素,在路径的终点添加一个 SVG 元素(如终点箭头),并自动旋转该元素,使其与根据路径方向保持一致。了解更多详情请参考[这篇教程](/zh/docs/tutorial/intermediate/marker)。
[[warning]]
:::warning{title=注意:}
| 需要注意的是,该元素初始时就被旋转了 `180` 度,在此基础上再自动调整旋转角度,并与路径的方向保持一致。例如,对于一个水平的直线,我们为其起点指定了一个向左的箭头,我们也可以为其重点指定相同的箭头,这个箭头会自动指向右侧(自动旋转了 `180` 度)。
:::
### vertexMarker

View File

@ -62,8 +62,9 @@ graph.addNode({
上面这些属性默认相对于节点的大小进行计算,另外我们可以通过 `ref` 属性来提供一个子元素选择器,这时所有的计算都相对于 `ref` 指代的元素,从而实现相对于子元素的大小和位置。
[[warning]]
:::warning{title=注意:}
| 需要注意的是,设置 `ref` 后,所有计算都依赖子元素在浏览器中的 bbox 测量,所以性能会比相对于节点的方式要慢。
:::
```ts
graph.addNode({

View File

@ -21,7 +21,7 @@ redirect_from:
在项目实践中,经常会遇到下面两种场景:
- 画布容器还没有渲染完成(此时尺寸为 0就实例化画布对象导致布元素显示异常。
- 画布容器还没有渲染完成(此时尺寸为 0就实例化画布对象导致布元素显示异常。
- 页面的 `resize` 导致画布容器大小改变,导致画布元素显示异常。
我们可以使用 `autoResize` 配置来解决上述问题。

View File

@ -0,0 +1,150 @@
---
title: Angular 节点
order: 4
redirect_from:
- /zh/docs
- /zh/docs/tutorial
- /zh/docs/tutorial/inermediate
---
:::info{title=在本章节中,你可以了解到:}
- 如何使用 Angular 来渲染节点内容
- 如何更新节点内容
- FAQ
:::
## 渲染节点
我们提供了一个独立的包 `@antv/x6-angular-shape` 以支持将 Angular 的组件/模板作为节点进行渲染。
### Component 渲染
```ts
@Component({
selector: 'app-node',
templateUrl: './node.component.html',
styleUrls: ['./node.component.scss'],
})
export class NodeComponent implements AfterViewInit, OnChanges {
@Input() value: string;
}
```
```ts
import { register } from "@antv/x6-angular-shape";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements AfterViewInit {
ngAfterViewInit(): void {
register({
shape: 'custom-angular-component-node',
width: 120,
height: 20,
content: NodeComponent,
injector: this.injector,
});
this.graph.addNode({
shape: 'custom-angular-component-node',
x: 100,
y: 100,
data: {
// Input 的参数必须放在这里
ngArguments: {
value: '糟糕糟糕 Oh my god',
},
},
});
}
}
```
### TemplateRef 渲染
```html
<ng-template #template let-data="ngArguments">
<section class="template-container">
<span class="value">{{ data.value }}</span>
</section>
</ng-template>
```
```ts
import { register } from "@antv/x6-angular-shape";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements AfterViewInit {
@ViewChild('template') template: TemplateRef<{}>;
ngAfterViewInit(): void {
register({
shape: 'custom-angular-template-node',
width: 120,
height: 20,
content: this.template,
injector: this.injector,
});
this.graph.addNode({
shape: 'custom-angular-template-node',
x: 100,
y: 100,
data: {
ngArguments: {
value: '魔法怎么失灵啦',
},
},
});
}
}
```
## 更新节点
无论是使用 Component 还是 TemplateRef, 都是一样的更新方式.
```ts
node.setData({
ngArguments: {
value: '晚风中闪过 几帧从前啊',
},
});
```
## 有 demo 吗?
有的, 因为X6渲染节点部分与框架是解耦的. 因此 `x6-angular-shape` 包并非是直接在源代码里改的, 而是在一个单独的Angular环境中开发的. 该 demo 还提供了多种节点类型的性能测试, 详情请参考[Eve-Sama/x6-angular-shape](https://github.com/Eve-Sama/x6-angular-shape)、[X6与G6的性能对比, 以及X6多节点类型下的FPS临界点讨论](https://github.com/antvis/X6/issues/3266)
## FAQ
### 为什么输入属性不能直接放在 data 中而需要放在 ngArguments 中? 且为什么不叫 ngInput?
因为并非所有 `node.data` 中的属性都是输入属性, 所以遍历 `data` 中的所有属性进行赋值是不合适的. 至于为什么叫 `ngArguments` 主要是有两点考虑.
- 1.x版本中已经这么用了, 沿用该API可以降低用户升级成本
- `Input` 的概念其实是来自 `Component`, 而 `TemplateRef` 中是 `context`, 在二者的基础上抽象一个 `Arguments` 的概念更通用些
### 2.x版本的 x6-angular-shape 相比较1.x版本有什么新特性吗?
实现思路其实和之前是差不多的. 但是确实有几个点值得一提.
#### demo更聚焦
1.x版本的 demo 除了渲染组件外, 还写了连线、清除等一系列案例. 看似扩展, 实则眼花缭乱. 作为 `x6-angular-shape`的 demo, 2.x版本更加聚焦, 更加聚焦于shape的使用与性能测试等, 与插件无关的内容请查看X6官网.
#### 功能更稳定
在1.x版本中, 虽然实现了功能, 但是使用场景的思考不够全面. 比如`ngArguments`的变化, 对 `TemplateRef`的场景并不生效. 虽然对`Component`生效但是无法触发`ngOnChanges`. 而在新版本中, 这些问题都将不复存在.
### 版本要求
你的Angular版本至少在14及以上才可以. 14以下需要用 hack 的方式实现一些特性, 比较麻烦. 暂时不提供, 如有需要可提issue, 我再专门介绍下如何实现.

View File

@ -1,6 +1,6 @@
---
title: HTML 节点
order: 4
order: 7
redirect_from:
- /zh/docs
- /zh/docs/tutorial

View File

@ -1,7 +1,7 @@
{
"private": true,
"name": "@antv/x6-sites",
"version": "1.5.2",
"version": "1.5.5",
"description": "X6 sites deployed on gh-pages",
"scripts": {
"dev": "dumi dev",
@ -31,9 +31,9 @@
"@antv/x6-plugin-transform": "^2.x",
"@antv/x6-react-components": "^2.x",
"@antv/x6-react-shape": "^2.x",
"antd": "^4.4.2",
"antd": "^5.0.0",
"dagre": "^0.8.5",
"dumi": "2.0.16",
"dumi": "^2.1.14",
"elkjs": "^0.8.2",
"highlight.js": "^10.1.2",
"react": "^18.0.0",

View File

@ -1,29 +1,26 @@
.app {
.auto-resize-app {
display: flex;
width: 600px;
height: 400px;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
.full {
width: 100%;
height: 100%;
}
:global {
.x6-split-box-horizontal > .x6-split-box-resizer,
.x6-split-box-vertical > .x6-split-box-resizer {
background: #e3e6e9;
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
}
.full {
width: 100%;
height: 100%;
}
}
.x6-split-box-horizontal > .x6-split-box-resizer,
.x6-split-box-vertical > .x6-split-box-resizer {
background: #e3e6e9;
}

View File

@ -3,7 +3,7 @@ import React from 'react'
import { Graph } from '@antv/x6'
import { SplitBox } from '@antv/x6-react-components'
import '@antv/x6-react-components/es/split-box/style/index.css'
import styles from './index.less'
import './index.less'
export default class Example extends React.Component {
private container1: HTMLDivElement
@ -50,16 +50,16 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className="auto-resize-app">
<SplitBox split="horizontal">
<div className={styles.full}>
<div className="full">
<div ref={this.refContainer1} />
</div>
<SplitBox split="vertical">
<div className={styles.full}>
<div className="full">
<div ref={this.refContainer2} />
</div>
<div className={styles.full}>
<div className="full">
<div ref={this.refContainer3} />
</div>
</SplitBox>

View File

@ -1,15 +1,15 @@
.app {
.backgournd-grid-app {
display: flex;
width: 100%;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
}

View File

@ -1,6 +1,6 @@
import React from 'react'
import { Graph } from '@antv/x6'
import styles from './index.less'
import './index.less'
const data = {
nodes: [
@ -93,8 +93,8 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className={styles['app-content']} ref={this.refContainer} />
<div className="backgournd-grid-app">
<div className="app-content" ref={this.refContainer} />
</div>
)
}

View File

@ -1,15 +1,15 @@
.app {
.panning-mousewheel-app {
display: flex;
width: 100%;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
}

View File

@ -1,6 +1,6 @@
import React from 'react'
import { Graph } from '@antv/x6'
import styles from './index.less'
import './index.less'
const data = {
nodes: [
@ -98,8 +98,8 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className={styles['app-content']} ref={this.refContainer} />
<div className="panning-mousewheel-app">
<div className="app-content" ref={this.refContainer} />
</div>
)
}

View File

@ -1,21 +1,20 @@
.app {
display: flex;
flex-direction: column;
.transform-app {
width: 100%;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;
}
.app-btns {
bottom: 0;
padding: 0 8px;
}
.app-btns {
bottom: 0;
padding: 0 8px;
}
.app-content {
height: 240px;
margin-top: 16px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
.app-content {
width: 100%;
height: 240px;
margin-top: 16px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
}

View File

@ -1,8 +1,7 @@
import React from 'react'
import { Graph } from '@antv/x6'
import { Button } from 'antd'
import styles from './index.less'
import './index.less'
const data = {
nodes: [
@ -150,8 +149,8 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className={styles['app-btns']}>
<div className="transform-app">
<div className="app-btns">
<Button.Group>
{commands.map((item) => (
<Button onClick={() => this.transform(item.key)} key={item.key}>
@ -160,7 +159,7 @@ export default class Example extends React.Component {
))}
</Button.Group>
</div>
<div className={styles['app-content']} ref={this.refContainer} />
<div className="app-content" ref={this.refContainer} />
</div>
)
}

View File

@ -1,14 +1,15 @@
.app {
.helloworld-app {
display: flex;
width: 100%;
padding: 0;
font-family: sans-serif;
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
}

View File

@ -1,6 +1,6 @@
import React from 'react'
import { Graph } from '@antv/x6'
import styles from './index.less'
import './index.less'
const data = {
nodes: [
@ -81,8 +81,8 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className={styles['app-content']} ref={this.refContainer} />
<div className="helloworld-app">
<div className="app-content" ref={this.refContainer} />
</div>
)
}

View File

@ -1,31 +1,31 @@
.app {
.react-shape-app {
display: flex;
width: 100%;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
.custom-react-node {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border: 1px solid #8f8f8f;
border-radius: 6px;
}
.custom-react-node {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border: 1px solid #8f8f8f;
border-radius: 6px;
}
.custom-react-node span {
display: inline-block;
width: 100%;
height: 100%;
.custom-react-node span {
display: inline-block;
width: 100%;
height: 100%;
}
}

View File

@ -2,7 +2,7 @@ import React from 'react'
import { Graph, Node } from '@antv/x6'
import { register } from '@antv/x6-react-shape'
import { Dropdown } from 'antd'
import styles from './index.less'
import './index.less'
const CustomComponent = ({ node }: { node: Node }) => {
const label = node.prop('label')
@ -26,7 +26,7 @@ const CustomComponent = ({ node }: { node: Node }) => {
}}
trigger={['contextMenu']}
>
<div className={styles['custom-react-node']}>{label}</div>
<div className="custom-react-node">{label}</div>
</Dropdown>
)
}
@ -92,8 +92,8 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className={styles['app-content']} ref={this.refContainer} />
<div className="react-shape-app">
<div className="app-content" ref={this.refContainer} />
</div>
)
}

View File

@ -1,25 +1,25 @@
.app {
.use-plugin-app {
display: flex;
padding: 0;
padding: 16px 8px;
font-family: sans-serif;
}
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
.custom-react-node {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border: 1px solid #8f8f8f;
border-radius: 6px;
padding: 0;
font-family: sans-serif;
.app-content {
flex: 1;
height: 280px;
margin-right: 8px;
margin-left: 8px;
border-radius: 5px;
box-shadow: 0 12px 5px -10px rgb(0 0 0 / 10%), 0 0 4px 0 rgb(0 0 0 / 10%);
}
.custom-react-node {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border: 1px solid #8f8f8f;
border-radius: 6px;
}
}

View File

@ -3,8 +3,7 @@ import { Graph, Node } from '@antv/x6'
import { register } from '@antv/x6-react-shape'
import { Dropdown } from 'antd'
import { Snapline } from '@antv/x6-plugin-snapline'
import styles from './index.less'
import './index.less'
const CustomComponent = ({ node }: { node: Node }) => {
const label = node.prop('label')
@ -28,7 +27,7 @@ const CustomComponent = ({ node }: { node: Node }) => {
}}
trigger={['contextMenu']}
>
<div className={styles['custom-react-node']}>{label}</div>
<div className="custom-react-node">{label}</div>
</Dropdown>
)
}
@ -99,8 +98,8 @@ export default class Example extends React.Component {
render() {
return (
<div className={styles.app}>
<div className={styles['app-content']} ref={this.refContainer} />
<div className="use-plugin-app">
<div className="app-content" ref={this.refContainer} />
</div>
)
}

View File

@ -14,7 +14,7 @@
"resolveJsonModule": true,
"experimentalDecorators": true,
"jsx": "react",
"target": "es5",
"target": "es6",
"lib": ["DOM", "ES2020"]
}
}