@next-bricks/diagram 0.68.8 → 0.68.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/bricks.json +3 -3
  2. package/dist/chunks/1265.bf280e6d.js +3 -0
  3. package/dist/chunks/1265.bf280e6d.js.map +1 -0
  4. package/dist/chunks/1889.fa8b5dbe.js +2 -0
  5. package/dist/chunks/1889.fa8b5dbe.js.map +1 -0
  6. package/dist/chunks/3171.8057c0f4.js +2 -0
  7. package/dist/chunks/3171.8057c0f4.js.map +1 -0
  8. package/dist/chunks/{3654.59bd8992.js → 3654.6a028b09.js} +3 -3
  9. package/dist/chunks/{3654.59bd8992.js.map → 3654.6a028b09.js.map} +1 -1
  10. package/dist/chunks/{3746.591c50d8.js → 3746.7fad241d.js} +2 -2
  11. package/dist/chunks/{3746.591c50d8.js.map → 3746.7fad241d.js.map} +1 -1
  12. package/dist/chunks/515.23d8419d.js +2 -0
  13. package/dist/chunks/515.23d8419d.js.map +1 -0
  14. package/dist/chunks/5399.d786845a.js +2 -0
  15. package/dist/chunks/5399.d786845a.js.map +1 -0
  16. package/dist/chunks/5552.7718c4ca.js +2 -0
  17. package/dist/chunks/5552.7718c4ca.js.map +1 -0
  18. package/dist/chunks/577.c9c65352.js.map +1 -1
  19. package/dist/chunks/6376.a8716290.js +2 -0
  20. package/dist/chunks/6376.a8716290.js.map +1 -0
  21. package/dist/chunks/7920.367555e2.js +3 -0
  22. package/dist/chunks/7920.367555e2.js.map +1 -0
  23. package/dist/chunks/9118.8a9d6592.js +3 -0
  24. package/dist/chunks/9118.8a9d6592.js.LICENSE.txt +11 -0
  25. package/dist/chunks/9118.8a9d6592.js.map +1 -0
  26. package/dist/chunks/948.e308c274.js +3 -0
  27. package/dist/chunks/948.e308c274.js.map +1 -0
  28. package/dist/chunks/editable-label.667b04d5.js.map +1 -1
  29. package/dist/chunks/eo-diagram.78450578.js.map +1 -1
  30. package/dist/chunks/eo-display-canvas.2a43ce91.js.map +1 -1
  31. package/dist/chunks/eo-draw-canvas.e01342d6.js.map +1 -1
  32. package/dist/chunks/experimental-node.2f4d802a.js.map +1 -1
  33. package/dist/chunks/main.91a8e473.js +2 -0
  34. package/dist/chunks/main.91a8e473.js.map +1 -0
  35. package/dist/examples.json +10 -7
  36. package/dist/index.f358949f.js +2 -0
  37. package/dist/index.f358949f.js.map +1 -0
  38. package/dist/manifest.json +359 -220
  39. package/dist/types.json +5163 -5163
  40. package/dist-types/diagram/index.d.ts +48 -1
  41. package/dist-types/diagram/interfaces.d.ts +3 -3
  42. package/dist-types/display-canvas/index.d.ts +37 -3
  43. package/dist-types/draw-canvas/index.d.ts +75 -7
  44. package/dist-types/draw-canvas/interfaces.d.ts +3 -3
  45. package/dist-types/editable-label/index.d.ts +14 -1
  46. package/dist-types/experimental-node/index.d.ts +11 -1
  47. package/docs/editable-label.md +71 -1
  48. package/docs/editable-label.react.md +100 -0
  49. package/docs/eo-diagram.md +54 -87
  50. package/docs/eo-diagram.react.md +399 -0
  51. package/docs/eo-display-canvas.md +60 -21
  52. package/docs/eo-display-canvas.react.md +376 -0
  53. package/docs/eo-draw-canvas.md +95 -40
  54. package/docs/eo-draw-canvas.react.md +989 -0
  55. package/docs/experimental-node.md +156 -0
  56. package/docs/experimental-node.react.md +157 -0
  57. package/package.json +2 -2
  58. package/dist/chunks/1265.55a02b5a.js +0 -3
  59. package/dist/chunks/1265.55a02b5a.js.map +0 -1
  60. package/dist/chunks/1889.9e9ad16a.js +0 -2
  61. package/dist/chunks/1889.9e9ad16a.js.map +0 -1
  62. package/dist/chunks/3171.3bd2c8f0.js +0 -2
  63. package/dist/chunks/3171.3bd2c8f0.js.map +0 -1
  64. package/dist/chunks/4667.53203ccd.js +0 -2
  65. package/dist/chunks/4667.53203ccd.js.map +0 -1
  66. package/dist/chunks/4837.32dece7c.js +0 -2
  67. package/dist/chunks/4837.32dece7c.js.map +0 -1
  68. package/dist/chunks/5399.b1b4981d.js +0 -2
  69. package/dist/chunks/5399.b1b4981d.js.map +0 -1
  70. package/dist/chunks/5552.e3e728b7.js +0 -2
  71. package/dist/chunks/5552.e3e728b7.js.map +0 -1
  72. package/dist/chunks/7218.e0bf22af.js +0 -2
  73. package/dist/chunks/7218.e0bf22af.js.map +0 -1
  74. package/dist/chunks/7920.df65d810.js +0 -3
  75. package/dist/chunks/7920.df65d810.js.map +0 -1
  76. package/dist/chunks/948.83e23068.js +0 -3
  77. package/dist/chunks/948.83e23068.js.map +0 -1
  78. package/dist/chunks/main.4630d30e.js +0 -2
  79. package/dist/chunks/main.4630d30e.js.map +0 -1
  80. package/dist/index.c366c6da.js +0 -2
  81. package/dist/index.c366c6da.js.map +0 -1
  82. /package/dist/chunks/{1265.55a02b5a.js.LICENSE.txt → 1265.bf280e6d.js.LICENSE.txt} +0 -0
  83. /package/dist/chunks/{3654.59bd8992.js.LICENSE.txt → 3654.6a028b09.js.LICENSE.txt} +0 -0
  84. /package/dist/chunks/{7920.df65d810.js.LICENSE.txt → 7920.367555e2.js.LICENSE.txt} +0 -0
  85. /package/dist/chunks/{948.83e23068.js.LICENSE.txt → 948.e308c274.js.LICENSE.txt} +0 -0
@@ -1,9 +1,60 @@
1
- 用于展示查看的画布构件。
1
+ ---
2
+ tagName: eo-display-canvas
3
+ displayName: WrappedEoDisplayCanvas
4
+ description: 用于展示查看的画布构件,支持 manual、force、dagre 多种布局,可展示节点、边和装饰器,支持缩放、平移、激活目标高亮、淡化无关元素等功能。
5
+ category: diagram
6
+ source: "@next-bricks/diagram"
7
+ ---
8
+
9
+ # eo-display-canvas
10
+
11
+ > 用于展示查看的画布构件,支持 manual、force、dagre 多种布局,可展示节点、边和装饰器,支持缩放、平移、激活目标高亮、淡化无关元素等功能。
12
+
13
+ ## Props
14
+
15
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
16
+ | ----------------------------------- | ----------------------------------- | ---- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
17
+ | cells | `InitialCell[] \| undefined` | - | - | 画布中的单元格数据,包含节点(node)、边(edge)和装饰器(decorator)。 |
18
+ | layout | `LayoutType` | 是 | - | 画布布局类型,支持 `manual`(手动定位)、`force`(力导向)、`dagre`(层次有向图)。 |
19
+ | layoutOptions | `LayoutOptions \| undefined` | - | - | 布局算法选项,根据 layout 类型不同,支持不同参数(如 dagre 的 ranksep/nodesep,force 的碰撞参数等)。 |
20
+ | autoSize | `AutoSize \| undefined` | - | - | 是否自动计算节点尺寸,启用后画布会根据节点内容自动调整节点大小。 |
21
+ | defaultNodeSize | `SizeTuple` | 是 | `[DEFAULT_NODE_SIZE, DEFAULT_NODE_SIZE]` | 节点默认尺寸,格式为 `[width, height]`,在节点未指定尺寸时使用。 |
22
+ | defaultNodeBricks | `NodeBrickConf[] \| undefined` | - | - | 节点默认砖块配置,指定渲染节点的自定义构件,可按节点类型匹配不同配置。 |
23
+ | degradedThreshold | `number \| undefined` | - | `500` | 当节点数量达到或超过 `degradedThreshold` 时,节点将被降级展示。 |
24
+ | degradedNodeLabel | `string \| undefined` | - | `"<% DATA.node.id %>"` | 设置节点将降级展示时显示的名称。 |
25
+ | defaultEdgeLines | `EdgeLineConf[] \| undefined` | - | - | 使用条件判断设置默认的边对应的连线。在 `if` 表达式中 `DATA` 为 `{ edge }`。 |
26
+ | activeTarget | `ActiveTarget \| null \| undefined` | - | - | 当前激活目标,可以是节点(`{ type: "node", id }`)或边(`{ type: "edge", id }`)等,为 null 表示无激活目标。 |
27
+ | fadeUnrelatedCells | `boolean \| undefined` | - | - | 当鼠标悬浮到某节点上时,隐藏其他跟该节点无关的元素,高亮相关节点和边。 |
28
+ | zoomable | `boolean \| undefined` | - | `true` | 是否允许通过鼠标滚轮或触控板捏合手势缩放画布,默认为 true。 |
29
+ | scrollable | `boolean \| undefined` | - | `true` | 是否允许通过滚轮平移画布(非捏合手势),默认为 true。 |
30
+ | pannable | `boolean \| undefined` | - | `true` | 是否允许通过鼠标拖拽平移画布,默认为 true。 |
31
+ | scaleRange | `RangeTuple \| undefined` | - | - | 缩放比例范围,格式为 `[min, max]`,默认范围由内部常量决定。 |
32
+ | hideZoomBar | `boolean \| undefined` | - | - | 隐藏右下角放大缩小的控制栏。 |
33
+ | autoCenterWhenCellsChange | `boolean \| undefined` | - | - | 每当 cells 改变时,重新自动居中。 |
34
+ | doNotResetActiveTargetForSelector | `string \| undefined` | - | - | 选择器,点击该选择器对应的元素时不重置 `activeTarget`。 |
35
+ | doNotResetActiveTargetOutsideCanvas | `boolean \| undefined` | - | - | 在画布外点击时不重置 `activeTarget`。 |
36
+ | extraStyleTexts | `string[] \| undefined` | - | - | 注入到 Shadow DOM 的额外 CSS 样式文本列表。 |
37
+
38
+ ## Events
39
+
40
+ | 事件 | detail | 说明 |
41
+ | ------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
42
+ | activeTarget.change | `ActiveTarget \| null` — 当前激活目标,节点/边对象或 null | 激活目标变化时触发,当用户点击节点或边使其激活,或点击空白处取消激活时触发。 |
43
+ | cell.contextmenu | `CellContextMenuDetail` — 右键菜单详情,包含 `{ cell: 对应的单元格, clientX: 鼠标X坐标, clientY: 鼠标Y坐标 }` | 用户右键点击节点或边时触发,常用于弹出上下文菜单。 |
44
+ | cell.click | `CellContextMenuDetail` — 点击详情,包含 `{ cell: 对应的单元格, clientX: 鼠标X坐标, clientY: 鼠标Y坐标 }` | 用户左键点击节点或边时触发。 |
45
+
46
+ ## Methods
47
+
48
+ | 方法 | 参数 | 返回值 | 说明 |
49
+ | ------ | ------------ | ------ | ------------------------------------------------------ |
50
+ | center | `() => void` | `void` | 将画布视图重置并居中,使所有单元格重新显示在视口中央。 |
2
51
 
3
52
  ## Examples
4
53
 
5
54
  ### Basic
6
55
 
56
+ 展示基本的手动布局画布,包含节点、边、装饰器,并支持右键菜单和激活高亮。
57
+
7
58
  ```yaml preview minHeight="600px"
8
59
  - brick: div
9
60
  properties:
@@ -139,7 +190,6 @@
139
190
  height: 100%
140
191
  activeTarget: <%= CTX.activeTarget %>
141
192
  fadeUnrelatedCells: true
142
- # Initial nodes only
143
193
  defaultNodeSize: [60, 60]
144
194
  defaultNodeBricks:
145
195
  - useBrick:
@@ -150,10 +200,6 @@
150
200
  <%=
151
201
  CTX.activeTarget?.type === "node" && CTX.activeTarget.id === DATA.node.id
152
202
  ? "highlighted"
153
- // : CTX.unrelated.some(n =>
154
- // n.type === "node" && n.id === DATA.node.id
155
- // )
156
- // ? "faded"
157
203
  : "default"
158
204
  %>
159
205
  defaultEdgeLines:
@@ -202,6 +248,8 @@
202
248
 
203
249
  ### Force layout
204
250
 
251
+ 展示 force(力导向)布局画布,节点位置由物理引擎自动计算。
252
+
205
253
  ```yaml preview minHeight="600px"
206
254
  - brick: div
207
255
  properties:
@@ -282,7 +330,6 @@
282
330
  activeTarget: <%= CTX.activeTarget %>
283
331
  fadeUnrelatedCells: true
284
332
  layout: force
285
- # Initial nodes only
286
333
  defaultNodeSize: [60, 60]
287
334
  defaultNodeBricks:
288
335
  - useBrick:
@@ -293,10 +340,6 @@
293
340
  <%=
294
341
  CTX.activeTarget?.type === "node" && CTX.activeTarget.id === DATA.node.id
295
342
  ? "highlighted"
296
- // : CTX.unrelated.some(n =>
297
- // n.type === "node" && n.id === DATA.node.id
298
- // )
299
- // ? "faded"
300
343
  : "default"
301
344
  %>
302
345
  defaultEdgeLines:
@@ -335,6 +378,8 @@
335
378
 
336
379
  ### Dagre layout
337
380
 
381
+ 展示 dagre(层次有向图)布局画布,节点按层级排列,支持折线连线和自定义连线样式。
382
+
338
383
  ```yaml preview minHeight="600px"
339
384
  - brick: div
340
385
  properties:
@@ -413,7 +458,6 @@
413
458
  layoutOptions:
414
459
  ranksep: 80
415
460
  nodesep: 80
416
- # Initial nodes only
417
461
  defaultNodeSize: [60, 60]
418
462
  defaultNodeBricks:
419
463
  - useBrick:
@@ -424,10 +468,6 @@
424
468
  <%=
425
469
  CTX.activeTarget?.type === "node" && CTX.activeTarget.id === DATA.node.id
426
470
  ? "highlighted"
427
- // : CTX.unrelated.some(n =>
428
- // n.type === "node" && n.id === DATA.node.id
429
- // )
430
- // ? "faded"
431
471
  : "default"
432
472
  %>
433
473
  defaultEdgeLines:
@@ -474,6 +514,8 @@
474
514
 
475
515
  ### Degraded diagram
476
516
 
517
+ 展示节点数量超过降级阈值时的降级模式,节点以简单 SVG 形式渲染以提升性能。
518
+
477
519
  ```yaml preview minHeight="600px"
478
520
  - brick: div
479
521
  properties:
@@ -514,8 +556,9 @@
514
556
  activeTarget: <%= CTX.activeTarget %>
515
557
  fadeUnrelatedCells: true
516
558
  layout: force
517
- # Initial nodes only
518
559
  defaultNodeSize: [60, 60]
560
+ degradedThreshold: 500
561
+ degradedNodeLabel: <% DATA.node.id %>
519
562
  defaultNodeBricks:
520
563
  - useBrick:
521
564
  brick: diagram.experimental-node
@@ -525,10 +568,6 @@
525
568
  <%=
526
569
  CTX.activeTarget?.type === "node" && CTX.activeTarget.id === DATA.node.id
527
570
  ? "highlighted"
528
- // : CTX.unrelated.some(n =>
529
- // n.type === "node" && n.id === DATA.node.id
530
- // )
531
- // ? "faded"
532
571
  : "default"
533
572
  %>
534
573
  defaultEdgeLines:
@@ -0,0 +1,376 @@
1
+ ---
2
+ tagName: eo-display-canvas
3
+ displayName: WrappedEoDisplayCanvas
4
+ description: 用于展示查看的画布构件,支持 manual、force、dagre 多种布局,可展示节点、边和装饰器,支持缩放、平移、激活目标高亮、淡化无关元素等功能。
5
+ category: diagram
6
+ source: "@next-bricks/diagram"
7
+ ---
8
+
9
+ # WrappedEoDisplayCanvas
10
+
11
+ > 用于展示查看的画布构件,支持 manual、force、dagre 多种布局,可展示节点、边和装饰器,支持缩放、平移、激活目标高亮、淡化无关元素等功能。
12
+
13
+ ## 导入
14
+
15
+ ```tsx
16
+ import { WrappedEoDisplayCanvas } from "@easyops/wrapped-components";
17
+ ```
18
+
19
+ ## Props
20
+
21
+ | 属性 | 类型 | 必填 | 默认值 | 说明 |
22
+ | ----------------------------------- | ------------------------------------------------- | ---- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
23
+ | cells | `InitialCell[] \| undefined` | - | - | 画布中的单元格数据,包含节点(node)、边(edge)和装饰器(decorator)。 |
24
+ | layout | `LayoutType` | 是 | - | 画布布局类型,支持 `manual`(手动定位)、`force`(力导向)、`dagre`(层次有向图)。 |
25
+ | layoutOptions | `LayoutOptions \| undefined` | - | - | 布局算法选项,根据 layout 类型不同,支持不同参数(如 dagre 的 ranksep/nodesep,force 的碰撞参数等)。 |
26
+ | autoSize | `AutoSize \| undefined` | - | - | 是否自动计算节点尺寸,启用后画布会根据节点内容自动调整节点大小。 |
27
+ | defaultNodeSize | `SizeTuple` | 是 | `[DEFAULT_NODE_SIZE, DEFAULT_NODE_SIZE]` | 节点默认尺寸,格式为 `[width, height]`,在节点未指定尺寸时使用。 |
28
+ | defaultNodeBricks | `NodeBrickConf[] \| undefined` | - | - | 节点默认砖块配置,指定渲染节点的自定义构件,可按节点类型匹配不同配置。 |
29
+ | degradedThreshold | `number \| undefined` | - | `500` | 当节点数量达到或超过 `degradedThreshold` 时,节点将被降级展示。 |
30
+ | degradedNodeLabel | `string \| undefined` | - | `"<% DATA.node.id %>"` | 设置节点将降级展示时显示的名称。 |
31
+ | defaultEdgeLines | `EdgeLineConf[] \| undefined` | - | - | 使用条件判断设置默认的边对应的连线。在 `if` 表达式中 `DATA` 为 `{ edge }`。 |
32
+ | activeTarget | `ActiveTarget \| null \| undefined` | - | - | 当前激活目标,可以是节点(`{ type: "node", id }`)或边(`{ type: "edge", id }`)等,为 null 表示无激活目标。 |
33
+ | fadeUnrelatedCells | `boolean \| undefined` | - | - | 当鼠标悬浮到某节点上时,隐藏其他跟该节点无关的元素,高亮相关节点和边。 |
34
+ | zoomable | `boolean \| undefined` | - | `true` | 是否允许通过鼠标滚轮或触控板捏合手势缩放画布,默认为 true。 |
35
+ | scrollable | `boolean \| undefined` | - | `true` | 是否允许通过滚轮平移画布(非捏合手势),默认为 true。 |
36
+ | pannable | `boolean \| undefined` | - | `true` | 是否允许通过鼠标拖拽平移画布,默认为 true。 |
37
+ | scaleRange | `RangeTuple \| undefined` | - | - | 缩放比例范围,格式为 `[min, max]`,默认范围由内部常量决定。 |
38
+ | hideZoomBar | `boolean \| undefined` | - | - | 隐藏右下角放大缩小的控制栏。 |
39
+ | autoCenterWhenCellsChange | `boolean \| undefined` | - | - | 每当 cells 改变时,重新自动居中。 |
40
+ | doNotResetActiveTargetForSelector | `string \| undefined` | - | - | 选择器,点击该选择器对应的元素时不重置 `activeTarget`。 |
41
+ | doNotResetActiveTargetOutsideCanvas | `boolean \| undefined` | - | - | 在画布外点击时不重置 `activeTarget`。 |
42
+ | extraStyleTexts | `string[] \| undefined` | - | - | 注入到 Shadow DOM 的额外 CSS 样式文本列表。 |
43
+ | onActiveTargetChange | `(e: CustomEvent<ActiveTarget \| null>) => void` | - | - | 激活目标变化时触发。 |
44
+ | onCellContextmenu | `(e: CustomEvent<CellContextMenuDetail>) => void` | - | - | 用户右键点击节点或边时触发。 |
45
+ | onCellClick | `(e: CustomEvent<CellContextMenuDetail>) => void` | - | - | 用户左键点击节点或边时触发。 |
46
+
47
+ ## Events
48
+
49
+ | 事件 | detail | 说明 |
50
+ | -------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
51
+ | onActiveTargetChange | `ActiveTarget \| null` — 当前激活目标,节点/边对象或 null | 激活目标变化时触发,当用户点击节点或边使其激活,或点击空白处取消激活时触发。 |
52
+ | onCellContextmenu | `CellContextMenuDetail` — 右键菜单详情,包含 `{ cell: 对应的单元格, clientX: 鼠标X坐标, clientY: 鼠标Y坐标 }` | 用户右键点击节点或边时触发,常用于弹出上下文菜单。 |
53
+ | onCellClick | `CellContextMenuDetail` — 点击详情,包含 `{ cell: 对应的单元格, clientX: 鼠标X坐标, clientY: 鼠标Y坐标 }` | 用户左键点击节点或边时触发。 |
54
+
55
+ ## Methods
56
+
57
+ | 方法 | 参数 | 返回值 | 说明 |
58
+ | ------ | ------------ | ------ | ------------------------------------------------------ |
59
+ | center | `() => void` | `void` | 将画布视图重置并居中,使所有单元格重新显示在视口中央。 |
60
+
61
+ ## Examples
62
+
63
+ ### Basic
64
+
65
+ 展示基本的手动布局画布,包含节点、边、装饰器,并支持右键菜单和激活高亮。
66
+
67
+ ```tsx
68
+ import { useState, useRef } from "react";
69
+ import { WrappedEoDisplayCanvas } from "@easyops/wrapped-components";
70
+
71
+ function BasicDisplayCanvas() {
72
+ const [activeTarget, setActiveTarget] = useState(null);
73
+ const [targetCell, setTargetCell] = useState(null);
74
+ const contextMenuRef = useRef(null);
75
+
76
+ const initialCells = [
77
+ {
78
+ type: "decorator",
79
+ id: "area-1",
80
+ decorator: "area",
81
+ view: { x: 10, y: 20, width: 400, height: 300 },
82
+ },
83
+ {
84
+ type: "decorator",
85
+ id: "container-1",
86
+ decorator: "container",
87
+ view: {
88
+ x: 50,
89
+ y: 400,
90
+ width: 280,
91
+ height: 120,
92
+ direction: "top",
93
+ text: "上层服务",
94
+ },
95
+ },
96
+ {
97
+ type: "edge",
98
+ source: "X",
99
+ target: "Y",
100
+ data: { strokeColor: "red", strokeWidth: 5 },
101
+ },
102
+ {
103
+ type: "edge",
104
+ source: "X",
105
+ target: "W",
106
+ data: { strokeColor: "pink", animate: { useAnimate: true, duration: 4 } },
107
+ },
108
+ {
109
+ type: "edge",
110
+ source: "X",
111
+ target: "Z",
112
+ data: {
113
+ virtual: true,
114
+ strokeColor: "blue",
115
+ animate: { useAnimate: true },
116
+ },
117
+ },
118
+ {
119
+ type: "edge",
120
+ source: "W",
121
+ target: "Z",
122
+ view: { entryPosition: { x: 0, y: 0.5 }, exitPosition: { x: 0.5, y: 0 } },
123
+ },
124
+ ...["X", "Y", "Z", "W"].map((id) => ({
125
+ type: "node",
126
+ id,
127
+ containerId: ["X", "Y", "Z"].includes(id) ? "container-1" : undefined,
128
+ data: { name: `Node ${id}` },
129
+ view: {
130
+ x: 100 + Math.random() * 200,
131
+ y: (id === "X" ? 0 : 300) + Math.round(Math.random() * 200),
132
+ width: 60,
133
+ height: 60,
134
+ },
135
+ })),
136
+ {
137
+ type: "decorator",
138
+ id: "text-1",
139
+ decorator: "text",
140
+ view: { x: 100, y: 120, width: 100, height: 20, text: "Hello!" },
141
+ },
142
+ ];
143
+
144
+ return (
145
+ <div style={{ display: "flex", height: 600, gap: "1em" }}>
146
+ <div style={{ flex: 1, minWidth: 0 }}>
147
+ <WrappedEoDisplayCanvas
148
+ style={{ width: "100%", height: "100%" }}
149
+ cells={initialCells}
150
+ layout="manual"
151
+ defaultNodeSize={[60, 60]}
152
+ activeTarget={activeTarget}
153
+ fadeUnrelatedCells={true}
154
+ defaultNodeBricks={[
155
+ {
156
+ useBrick: {
157
+ brick: "diagram.experimental-node",
158
+ properties: {
159
+ textContent: "<% `Node ${DATA.node.id}` %>",
160
+ status:
161
+ "<%= CTX.activeTarget?.type === 'node' && CTX.activeTarget.id === DATA.node.id ? 'highlighted' : 'default' %>",
162
+ },
163
+ },
164
+ },
165
+ ]}
166
+ defaultEdgeLines={[
167
+ {
168
+ dashed: "<% DATA.edge?.data?.virtual %>",
169
+ strokeColor: "<% DATA.edge?.data?.strokeColor %>",
170
+ strokeWidth: "<% DATA.edge?.data?.strokeWidth %>",
171
+ animate: "<% DATA.edge?.data?.animate %>",
172
+ markers: [
173
+ { placement: "end", type: "circle" },
174
+ { placement: "start", type: "arrow" },
175
+ ],
176
+ },
177
+ ]}
178
+ onActiveTargetChange={(e) => setActiveTarget(e.detail)}
179
+ onCellContextmenu={(e) => {
180
+ contextMenuRef.current?.open({
181
+ position: [e.detail.clientX, e.detail.clientY],
182
+ });
183
+ setTargetCell(e.detail.cell);
184
+ }}
185
+ onCellClick={(e) =>
186
+ setActiveTarget({ type: e.detail.cell.type, id: e.detail.cell.id })
187
+ }
188
+ />
189
+ </div>
190
+ </div>
191
+ );
192
+ }
193
+ ```
194
+
195
+ ### Force layout
196
+
197
+ 展示 force(力导向)布局画布,节点位置由物理引擎自动计算。
198
+
199
+ ```tsx
200
+ import { useState } from "react";
201
+ import { WrappedEoDisplayCanvas } from "@easyops/wrapped-components";
202
+
203
+ function ForceLayoutCanvas() {
204
+ const [activeTarget, setActiveTarget] = useState(null);
205
+
206
+ const initialCells = [
207
+ { type: "edge", source: "X", target: "Y" },
208
+ { type: "edge", source: "X", target: "Z", data: { virtual: true } },
209
+ ...["X", "Y", "Z", "W"].map((id) => ({
210
+ type: "node",
211
+ id,
212
+ data: { name: `Node ${id}` },
213
+ view: { width: 60, height: 60 },
214
+ })),
215
+ {
216
+ type: "decorator",
217
+ id: "text-1",
218
+ decorator: "text",
219
+ view: { x: 100, y: 120, width: 100, height: 20, text: "Hello!" },
220
+ },
221
+ ];
222
+
223
+ return (
224
+ <div style={{ height: 600 }}>
225
+ <WrappedEoDisplayCanvas
226
+ style={{ width: "100%", height: "100%" }}
227
+ cells={initialCells}
228
+ layout="force"
229
+ defaultNodeSize={[60, 60]}
230
+ activeTarget={activeTarget}
231
+ fadeUnrelatedCells={true}
232
+ defaultNodeBricks={[
233
+ {
234
+ useBrick: {
235
+ brick: "diagram.experimental-node",
236
+ properties: {
237
+ textContent: "<% `Node ${DATA.node.id}` %>",
238
+ status:
239
+ "<%= activeTarget?.type === 'node' && activeTarget.id === DATA.node.id ? 'highlighted' : 'default' %>",
240
+ },
241
+ },
242
+ },
243
+ ]}
244
+ defaultEdgeLines={[
245
+ { if: "<% DATA.edge.data?.virtual %>", dashed: true },
246
+ ]}
247
+ onActiveTargetChange={(e) => setActiveTarget(e.detail)}
248
+ />
249
+ </div>
250
+ );
251
+ }
252
+ ```
253
+
254
+ ### Dagre layout
255
+
256
+ 展示 dagre(层次有向图)布局画布,节点按层级排列,支持折线连线和自定义连线样式。
257
+
258
+ ```tsx
259
+ import { useState } from "react";
260
+ import { WrappedEoDisplayCanvas } from "@easyops/wrapped-components";
261
+
262
+ function DagreLayoutCanvas() {
263
+ const [activeTarget, setActiveTarget] = useState(null);
264
+
265
+ const initialCells = [
266
+ { type: "edge", source: "X", target: "Y", view: { type: "polyline" } },
267
+ { type: "edge", source: "X", target: "Z", data: { virtual: true } },
268
+ { type: "edge", source: "Z", target: "W" },
269
+ ...["X", "Y", "Z", "W"].map((id) => ({
270
+ type: "node",
271
+ id,
272
+ data: { name: `Node ${id}` },
273
+ view: { width: 60, height: 60 },
274
+ })),
275
+ ];
276
+
277
+ return (
278
+ <div style={{ height: 600 }}>
279
+ <WrappedEoDisplayCanvas
280
+ style={{ width: "100%", height: "100%" }}
281
+ cells={initialCells}
282
+ layout="dagre"
283
+ layoutOptions={{ ranksep: 80, nodesep: 80 }}
284
+ defaultNodeSize={[60, 60]}
285
+ activeTarget={activeTarget}
286
+ fadeUnrelatedCells={true}
287
+ defaultNodeBricks={[
288
+ {
289
+ useBrick: {
290
+ brick: "diagram.experimental-node",
291
+ properties: {
292
+ textContent: "<% `Node ${DATA.node.id}` %>",
293
+ status:
294
+ "<%= activeTarget?.type === 'node' && activeTarget.id === DATA.node.id ? 'highlighted' : 'default' %>",
295
+ },
296
+ },
297
+ },
298
+ ]}
299
+ defaultEdgeLines={[
300
+ {
301
+ dashed: "<% !!DATA.edge.data?.virtual %>",
302
+ strokeColor: "var(--palette-blue-6)",
303
+ overrides: {
304
+ active: {
305
+ strokeWidth: "<% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>",
306
+ strokeColor: "cyan",
307
+ },
308
+ activeRelated: {
309
+ strokeWidth: "<% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>",
310
+ motion: {
311
+ shape: "<% DATA.edge.data?.virtual ? 'dot' : 'triangle' %>",
312
+ },
313
+ },
314
+ },
315
+ },
316
+ ]}
317
+ onActiveTargetChange={(e) => setActiveTarget(e.detail)}
318
+ />
319
+ </div>
320
+ );
321
+ }
322
+ ```
323
+
324
+ ### Degraded diagram
325
+
326
+ 展示节点数量超过降级阈值时的降级模式,节点以简单 SVG 形式渲染以提升性能。
327
+
328
+ ```tsx
329
+ import { useState } from "react";
330
+ import { WrappedEoDisplayCanvas } from "@easyops/wrapped-components";
331
+
332
+ function DegradedCanvas() {
333
+ const [activeTarget, setActiveTarget] = useState(null);
334
+
335
+ const initialCells = new Array(500).fill(null).map((_, i) => ({
336
+ type: "node",
337
+ id: String(i),
338
+ data: { name: String(i) },
339
+ }));
340
+
341
+ return (
342
+ <div style={{ height: 600 }}>
343
+ <WrappedEoDisplayCanvas
344
+ style={{ width: "100%", height: "100%" }}
345
+ cells={initialCells}
346
+ layout="force"
347
+ defaultNodeSize={[60, 60]}
348
+ degradedThreshold={500}
349
+ degradedNodeLabel="<% DATA.node.id %>"
350
+ activeTarget={activeTarget}
351
+ fadeUnrelatedCells={true}
352
+ defaultNodeBricks={[
353
+ {
354
+ useBrick: {
355
+ brick: "diagram.experimental-node",
356
+ properties: {
357
+ textContent: "<% `Node ${DATA.node.id}` %>",
358
+ status:
359
+ "<%= activeTarget?.type === 'node' && activeTarget.id === DATA.node.id ? 'highlighted' : 'default' %>",
360
+ },
361
+ },
362
+ },
363
+ ]}
364
+ defaultEdgeLines={[
365
+ {
366
+ dashed: "<% DATA.edge?.data?.virtual %>",
367
+ strokeColor: "<% DATA.edge?.data?.strokeColor %>",
368
+ strokeWidth: "<% DATA.edge?.data?.strokeWidth %>",
369
+ },
370
+ ]}
371
+ onActiveTargetChange={(e) => setActiveTarget(e.detail)}
372
+ />
373
+ </div>
374
+ );
375
+ }
376
+ ```