@rxflow/bloodline 0.0.1-alpha.0
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.
- package/README.md +41 -0
- package/cjs/BaseNodeWrapper/index.d.ts +18 -0
- package/cjs/BaseNodeWrapper/index.d.ts.map +1 -0
- package/cjs/BaseNodeWrapper/index.js +51 -0
- package/cjs/GroupNodeWrapper/index.d.ts +15 -0
- package/cjs/GroupNodeWrapper/index.d.ts.map +1 -0
- package/cjs/GroupNodeWrapper/index.js +64 -0
- package/cjs/components/Connector.d.ts +8 -0
- package/cjs/components/Connector.d.ts.map +1 -0
- package/cjs/components/Connector.js +147 -0
- package/cjs/constants.d.ts +26 -0
- package/cjs/constants.d.ts.map +1 -0
- package/cjs/constants.js +35 -0
- package/cjs/index.d.ts +7 -0
- package/cjs/index.d.ts.map +1 -0
- package/cjs/index.js +82 -0
- package/cjs/style/index.less +1 -0
- package/cjs/style/theme.less +16 -0
- package/cjs/types.d.ts +49 -0
- package/cjs/types.d.ts.map +1 -0
- package/cjs/types.js +3 -0
- package/cjs/utils/_layoutCells.d.ts +14 -0
- package/cjs/utils/_layoutCells.d.ts.map +1 -0
- package/cjs/utils/_layoutCells.js +483 -0
- package/cjs/utils/keys.d.ts +3 -0
- package/cjs/utils/keys.d.ts.map +1 -0
- package/cjs/utils/keys.js +18 -0
- package/cjs/utils/layoutCells.d.ts +14 -0
- package/cjs/utils/layoutCells.d.ts.map +1 -0
- package/cjs/utils/layoutCells.js +308 -0
- package/esm/BaseNodeWrapper/index.d.ts +18 -0
- package/esm/BaseNodeWrapper/index.d.ts.map +1 -0
- package/esm/BaseNodeWrapper/index.js +44 -0
- package/esm/GroupNodeWrapper/index.d.ts +15 -0
- package/esm/GroupNodeWrapper/index.d.ts.map +1 -0
- package/esm/GroupNodeWrapper/index.js +56 -0
- package/esm/components/Connector.d.ts +8 -0
- package/esm/components/Connector.d.ts.map +1 -0
- package/esm/components/Connector.js +162 -0
- package/esm/constants.d.ts +26 -0
- package/esm/constants.d.ts.map +1 -0
- package/esm/constants.js +30 -0
- package/esm/index.d.ts +7 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +55 -0
- package/esm/style/index.less +1 -0
- package/esm/style/theme.less +16 -0
- package/esm/types.d.ts +49 -0
- package/esm/types.d.ts.map +1 -0
- package/esm/types.js +13 -0
- package/esm/utils/_layoutCells.d.ts +14 -0
- package/esm/utils/_layoutCells.d.ts.map +1 -0
- package/esm/utils/_layoutCells.js +477 -0
- package/esm/utils/keys.d.ts +3 -0
- package/esm/utils/keys.d.ts.map +1 -0
- package/esm/utils/keys.js +11 -0
- package/esm/utils/layoutCells.d.ts +14 -0
- package/esm/utils/layoutCells.d.ts.map +1 -0
- package/esm/utils/layoutCells.js +305 -0
- package/package.json +47 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.layoutCells = void 0;
|
|
7
|
+
var _hierarchy = _interopRequireDefault(require("@antv/hierarchy"));
|
|
8
|
+
var _base = require("@rxflow/base");
|
|
9
|
+
var _constants = require("../constants");
|
|
10
|
+
var _keys = require("./keys");
|
|
11
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
+
/**
|
|
13
|
+
* @author: yanxianliang
|
|
14
|
+
* @date: 2025-07-03 13:20
|
|
15
|
+
* @desc: 血缘布局
|
|
16
|
+
*
|
|
17
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// 支持 innerNodes 配置
|
|
21
|
+
function getChildren(direction, origin) {
|
|
22
|
+
let children = [];
|
|
23
|
+
if (origin.innerNodes) {
|
|
24
|
+
origin.innerNodes.forEach(innerNode => {
|
|
25
|
+
const connectorState = direction === _constants.BloodlineDirection.downstream ? innerNode.downstream : innerNode.upstream;
|
|
26
|
+
if (connectorState?.state === 'expanded') {
|
|
27
|
+
const list = connectorState.list || [];
|
|
28
|
+
children.push(...list.map(child => {
|
|
29
|
+
return {
|
|
30
|
+
...child,
|
|
31
|
+
[_constants.sideSymbol]: direction === _constants.BloodlineDirection.upstream ? _constants.SplitSide.left : _constants.SplitSide.right,
|
|
32
|
+
[_constants.parentIdSymbol]: innerNode.id
|
|
33
|
+
};
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
const connectorState = direction === _constants.BloodlineDirection.downstream ? origin.downstream : origin.upstream;
|
|
39
|
+
if (connectorState?.state === 'expanded') {
|
|
40
|
+
const list = connectorState.list || [];
|
|
41
|
+
children.push(...list.map(child => {
|
|
42
|
+
return {
|
|
43
|
+
...child,
|
|
44
|
+
[_constants.sideSymbol]: direction === _constants.BloodlineDirection.upstream ? _constants.SplitSide.left : _constants.SplitSide.right
|
|
45
|
+
};
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return children;
|
|
50
|
+
}
|
|
51
|
+
function getSiblings(node) {
|
|
52
|
+
const {
|
|
53
|
+
depth,
|
|
54
|
+
side,
|
|
55
|
+
parent
|
|
56
|
+
} = node;
|
|
57
|
+
if (!parent || !parent.children) {
|
|
58
|
+
return {
|
|
59
|
+
firstNode: null
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
let firstNode = null;
|
|
63
|
+
for (const child of parent.children) {
|
|
64
|
+
if (depth === 1 && child.side === side) {
|
|
65
|
+
!firstNode && (firstNode = child);
|
|
66
|
+
}
|
|
67
|
+
if (depth !== 1) {
|
|
68
|
+
!firstNode && (firstNode = child);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
firstNode
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function getChildrenNodes(node, cycleCheckNodeSet) {
|
|
76
|
+
const side = node.side;
|
|
77
|
+
let children = [];
|
|
78
|
+
switch (side) {
|
|
79
|
+
case 'left':
|
|
80
|
+
children = getChildren(_constants.BloodlineDirection.upstream, node);
|
|
81
|
+
break;
|
|
82
|
+
case 'right':
|
|
83
|
+
children = getChildren(_constants.BloodlineDirection.downstream, node);
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
{
|
|
87
|
+
const leftChildren = getChildren(_constants.BloodlineDirection.upstream, node);
|
|
88
|
+
const rightChildren = getChildren(_constants.BloodlineDirection.downstream, node);
|
|
89
|
+
children = [...(leftChildren || []), ...(rightChildren || [])];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 支持 nodeList 处理
|
|
94
|
+
|
|
95
|
+
if (cycleCheckNodeSet) {
|
|
96
|
+
// 剔除循环引用的列表
|
|
97
|
+
return children.filter(child => {
|
|
98
|
+
if (cycleCheckNodeSet.has(child.id)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
cycleCheckNodeSet.add(child.id);
|
|
102
|
+
return true;
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
return children;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const layoutCells = config => {
|
|
109
|
+
const {
|
|
110
|
+
nodeTypes,
|
|
111
|
+
originNodes,
|
|
112
|
+
theme,
|
|
113
|
+
store,
|
|
114
|
+
flowProps
|
|
115
|
+
} = config;
|
|
116
|
+
|
|
117
|
+
// const {autoHideIntermediateNode} = flowProps as IBloodlineFlowProps;
|
|
118
|
+
|
|
119
|
+
const {
|
|
120
|
+
nodeLookup
|
|
121
|
+
} = store;
|
|
122
|
+
const innerNodeLookup = new Map();
|
|
123
|
+
if (originNodes.length === 0) {
|
|
124
|
+
return {
|
|
125
|
+
nodes: [],
|
|
126
|
+
edges: []
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 需不需要进行 clone ??? 需要设置 side 等属性,要回显回去吗??不需要的吧
|
|
131
|
+
const root = originNodes[0]; // 根节点
|
|
132
|
+
|
|
133
|
+
const align = theme.align || _constants.Align.top;
|
|
134
|
+
const layoutType = theme.layout || 'compactBox';
|
|
135
|
+
const layoutUtil = layoutType === 'mindmap' ? _hierarchy.default.mindmap : _hierarchy.default.compactBox;
|
|
136
|
+
let edges = [];
|
|
137
|
+
|
|
138
|
+
// split side
|
|
139
|
+
root?.upstream?.list?.forEach(item => {
|
|
140
|
+
item[_constants.sideSymbol] = _constants.SplitSide.left;
|
|
141
|
+
});
|
|
142
|
+
root?.downstream?.list?.forEach(item => {
|
|
143
|
+
item[_constants.sideSymbol] = _constants.SplitSide.right;
|
|
144
|
+
});
|
|
145
|
+
const cycleCheckNodeSet = new Set([root.id]); // 循环依赖节点检测
|
|
146
|
+
|
|
147
|
+
const layoutResult = layoutUtil(root, {
|
|
148
|
+
direction: 'H',
|
|
149
|
+
getHGap: () => {
|
|
150
|
+
return 40;
|
|
151
|
+
},
|
|
152
|
+
getVGap: () => {
|
|
153
|
+
return 20;
|
|
154
|
+
},
|
|
155
|
+
getWidth(node) {
|
|
156
|
+
const width = (0, _base.getNodeWidth)(node, nodeTypes, theme, nodeLookup);
|
|
157
|
+
node.measured ?? (node.measured = {});
|
|
158
|
+
node.measured.width = width;
|
|
159
|
+
return width;
|
|
160
|
+
},
|
|
161
|
+
getHeight(node) {
|
|
162
|
+
const height = (0, _base.getNodeHeight)(node, nodeTypes, theme, nodeLookup);
|
|
163
|
+
node.measured ?? (node.measured = {});
|
|
164
|
+
node.measured.height = height;
|
|
165
|
+
return height;
|
|
166
|
+
},
|
|
167
|
+
getSide: node => {
|
|
168
|
+
// side 计算,上下游需要区分左和右
|
|
169
|
+
return node.data[_constants.sideSymbol] || 'right';
|
|
170
|
+
},
|
|
171
|
+
getChildren: node => {
|
|
172
|
+
return getChildrenNodes(node, cycleCheckNodeSet);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
let layoutNodes = [];
|
|
176
|
+
const {
|
|
177
|
+
x: rootX,
|
|
178
|
+
y: rootY
|
|
179
|
+
} = layoutResult;
|
|
180
|
+
// 开始节点x,y 以(0,0)进行修正,根节点需要能够被检测显示在画布区域
|
|
181
|
+
|
|
182
|
+
const loopCycleCheckNodeSet = new Set();
|
|
183
|
+
// source 表示上游节点,target 表示下游节点
|
|
184
|
+
layoutResult.BFTraverse(node => {
|
|
185
|
+
const {
|
|
186
|
+
x,
|
|
187
|
+
y,
|
|
188
|
+
data,
|
|
189
|
+
side,
|
|
190
|
+
parent,
|
|
191
|
+
depth
|
|
192
|
+
} = node;
|
|
193
|
+
const {
|
|
194
|
+
id,
|
|
195
|
+
type,
|
|
196
|
+
measured
|
|
197
|
+
} = data;
|
|
198
|
+
if (loopCycleCheckNodeSet.has(id)) {
|
|
199
|
+
// 循环节点进行剔除
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
loopCycleCheckNodeSet.add(id);
|
|
203
|
+
const {
|
|
204
|
+
firstNode
|
|
205
|
+
} = getSiblings(node); // 同级节点
|
|
206
|
+
|
|
207
|
+
const offsetY = firstNode ? firstNode.y - parent.position.y : 0;
|
|
208
|
+
const direction = side === 'left' ? _constants.BloodlineDirection.upstream : _constants.BloodlineDirection.downstream;
|
|
209
|
+
const adjustX = x - rootX;
|
|
210
|
+
// 是否居中, 可居中,可顶部对齐
|
|
211
|
+
const adjustY = align === _constants.Align.top ? y - (parent ? offsetY : rootY) : y - rootY;
|
|
212
|
+
const position = {
|
|
213
|
+
x: adjustX,
|
|
214
|
+
y: adjustY
|
|
215
|
+
};
|
|
216
|
+
node.position = position;
|
|
217
|
+
if (!innerNodeLookup.has(id)) {
|
|
218
|
+
// 已经存在相同的节点了,直接关联到之前的节点上
|
|
219
|
+
// 实例每次都是新的,使用 data 实例缓存,但是所有节点外面都需要包一层????
|
|
220
|
+
const definition = nodeTypes?.[type];
|
|
221
|
+
const instance = {
|
|
222
|
+
id,
|
|
223
|
+
type,
|
|
224
|
+
measured: measured,
|
|
225
|
+
width: measured.width,
|
|
226
|
+
// 宽度固定,高度自动计算
|
|
227
|
+
height: measured.height,
|
|
228
|
+
// 血缘节点高度标准化模式为固定
|
|
229
|
+
data: {
|
|
230
|
+
isRoot: node.isRoot(),
|
|
231
|
+
depth,
|
|
232
|
+
id,
|
|
233
|
+
direction,
|
|
234
|
+
origin: data
|
|
235
|
+
// leaf 节点属性,当展开和折叠时需要处理对应的 leaf。
|
|
236
|
+
},
|
|
237
|
+
position: position,
|
|
238
|
+
zIndex: 10 // 节点默认 zIndex
|
|
239
|
+
};
|
|
240
|
+
const handles = definition?.measureHandles?.(instance);
|
|
241
|
+
instance.handles = (0, _base.parseHandles)(handles);
|
|
242
|
+
|
|
243
|
+
// 重复检测,如果已经存在相同节点,节点id相同,自动复用之前的节点。
|
|
244
|
+
layoutNodes.push(instance);
|
|
245
|
+
innerNodeLookup.set(id, instance);
|
|
246
|
+
}
|
|
247
|
+
const childrenNodes = getChildrenNodes(data);
|
|
248
|
+
|
|
249
|
+
// 如果已经存在的,则使用上下节点进行标记。解决直线回连显示问题
|
|
250
|
+
let edgeIndex = 0;
|
|
251
|
+
childrenNodes.forEach(child => {
|
|
252
|
+
const side = child[_constants.sideSymbol] || 'right';
|
|
253
|
+
const {
|
|
254
|
+
innerNodes
|
|
255
|
+
} = child; // 如果有父级的子节点标记
|
|
256
|
+
// 连线是从 __parentId__ 到 child
|
|
257
|
+
const parentNodeId = child[_constants.parentIdSymbol] || id;
|
|
258
|
+
const childId = child.id;
|
|
259
|
+
if (!innerNodes) {
|
|
260
|
+
const sourceNode = side === 'left' ? childId : id; // 上游节点
|
|
261
|
+
const targetNode = side === 'left' ? id : childId; // 下游节点
|
|
262
|
+
|
|
263
|
+
const sourceHandleNode = side === 'left' ? childId : parentNodeId;
|
|
264
|
+
const targetHandleNode = side === 'left' ? parentNodeId : childId; // targetHandleNode 是
|
|
265
|
+
|
|
266
|
+
const sourceHandle = (0, _keys.getConnectorId)(_constants.BloodlineDirection.downstream, sourceHandleNode);
|
|
267
|
+
const targetHandle = (0, _keys.getConnectorId)(_constants.BloodlineDirection.upstream, targetHandleNode);
|
|
268
|
+
// if(edgeIndex === 1){
|
|
269
|
+
edges.push({
|
|
270
|
+
id: `source.${sourceHandle}_target.${targetHandle}`,
|
|
271
|
+
type: 'smart',
|
|
272
|
+
source: sourceNode,
|
|
273
|
+
target: targetNode,
|
|
274
|
+
sourceHandle: sourceHandle,
|
|
275
|
+
// 可能链接其中某个版本
|
|
276
|
+
targetHandle: targetHandle
|
|
277
|
+
});
|
|
278
|
+
// }
|
|
279
|
+
edgeIndex++;
|
|
280
|
+
} else {
|
|
281
|
+
innerNodes.forEach(innerNode => {
|
|
282
|
+
const sourceNode = side === 'left' ? childId : id; // 上游节点
|
|
283
|
+
const targetNode = side === 'left' ? id : childId; // 下游节点
|
|
284
|
+
|
|
285
|
+
const sourceHandleNode = side === 'left' ? innerNode.id : parentNodeId;
|
|
286
|
+
const targetHandleNode = side === 'left' ? parentNodeId : innerNode.id; // targetHandleNode 是
|
|
287
|
+
|
|
288
|
+
const sourceHandle = (0, _keys.getConnectorId)(_constants.BloodlineDirection.downstream, sourceHandleNode);
|
|
289
|
+
const targetHandle = (0, _keys.getConnectorId)(_constants.BloodlineDirection.upstream, targetHandleNode);
|
|
290
|
+
edges.push({
|
|
291
|
+
id: `source.${sourceHandle}_target.${targetHandle}`,
|
|
292
|
+
type: 'smart',
|
|
293
|
+
source: sourceNode,
|
|
294
|
+
target: targetNode,
|
|
295
|
+
sourceHandle: sourceHandle,
|
|
296
|
+
// 可能链接其中某个版本
|
|
297
|
+
targetHandle: targetHandle
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
return {
|
|
304
|
+
nodes: layoutNodes,
|
|
305
|
+
edges: edges
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
exports.layoutCells = layoutCells;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author: yanxianliang
|
|
3
|
+
* @date: 2025-09-18 14:16
|
|
4
|
+
* @modified:2025/9/18 14:16 by yanxianliang
|
|
5
|
+
* @desc: 节点的外层组件,实现内置的折叠、加载功能
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
8
|
+
*/
|
|
9
|
+
import { NodeTypeComponent } from '@rxflow/base';
|
|
10
|
+
import { BloodlineDirection } from "..";
|
|
11
|
+
import { BaseBloodNode } from "../types";
|
|
12
|
+
export declare const BaseNodeWrapper: NodeTypeComponent<{
|
|
13
|
+
direction: BloodlineDirection;
|
|
14
|
+
origin: BaseBloodNode;
|
|
15
|
+
isRoot?: boolean;
|
|
16
|
+
depth: number;
|
|
17
|
+
}>;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAC,iBAAiB,EAAiB,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAC,kBAAkB,EAAC,WAA0B;AAGrD,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAIvC,eAAO,MAAM,eAAe,EAAE,iBAAiB,CAAC;IAC9C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAyBA,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
/**
|
|
8
|
+
* @author: yanxianliang
|
|
9
|
+
* @date: 2025-09-18 14:16
|
|
10
|
+
* @modified:2025/9/18 14:16 by yanxianliang
|
|
11
|
+
* @desc: 节点的外层组件,实现内置的折叠、加载功能
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
14
|
+
*/
|
|
15
|
+
import { useNodeTypeMap } from '@rxflow/base';
|
|
16
|
+
import { BloodlineDirection } from "./..";
|
|
17
|
+
import React, { useMemo } from "react";
|
|
18
|
+
import { Connector } from "../components/Connector";
|
|
19
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
21
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
22
|
+
// 末级叶子节点,前面显示折叠器
|
|
23
|
+
export var BaseNodeWrapper = function BaseNodeWrapper(props) {
|
|
24
|
+
var type = props.type,
|
|
25
|
+
data = props.data;
|
|
26
|
+
var nodeTypeMap = useNodeTypeMap();
|
|
27
|
+
var Component = useMemo(function () {
|
|
28
|
+
var _nodeTypeMap$get;
|
|
29
|
+
return (_nodeTypeMap$get = nodeTypeMap.get(type)) === null || _nodeTypeMap$get === void 0 ? void 0 : _nodeTypeMap$get._component;
|
|
30
|
+
}, [nodeTypeMap]);
|
|
31
|
+
var origin = data.origin;
|
|
32
|
+
|
|
33
|
+
// 创建更多的占位连接桩,当出现重复时可以使用上下进行链接
|
|
34
|
+
|
|
35
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
36
|
+
children: [/*#__PURE__*/_jsx(Connector, {
|
|
37
|
+
source: origin,
|
|
38
|
+
direction: BloodlineDirection.upstream
|
|
39
|
+
}), Component ? /*#__PURE__*/_jsx(Component, _objectSpread({}, props)) : null, /*#__PURE__*/_jsx(Connector, {
|
|
40
|
+
source: origin,
|
|
41
|
+
direction: BloodlineDirection.downstream
|
|
42
|
+
})]
|
|
43
|
+
});
|
|
44
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author: yanxianliang
|
|
3
|
+
* @date: 2025-09-25 10:16
|
|
4
|
+
* @modified:2025/9/25 10:16 by yanxianliang
|
|
5
|
+
* @desc: 组合节点,支持多个连接桩
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
8
|
+
*/
|
|
9
|
+
import { type NodeTypeComponent } from '@rxflow/base';
|
|
10
|
+
import { BaseBloodNode, BloodlineDirection } from "..";
|
|
11
|
+
export declare const GroupWrapper: NodeTypeComponent<{
|
|
12
|
+
direction: BloodlineDirection;
|
|
13
|
+
origin: BaseBloodNode;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAiB,KAAK,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAC,aAAa,EAAE,kBAAkB,EAAC,WAA0B;AAIpE,eAAO,MAAM,YAAY,EAAE,iBAAiB,CAAC;IAC3C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,aAAa,CAAC;CACvB,CAsCA,CAAA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
/**
|
|
8
|
+
* @author: yanxianliang
|
|
9
|
+
* @date: 2025-09-25 10:16
|
|
10
|
+
* @modified:2025/9/25 10:16 by yanxianliang
|
|
11
|
+
* @desc: 组合节点,支持多个连接桩
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
14
|
+
*/
|
|
15
|
+
import { useNodeTypeMap } from '@rxflow/base';
|
|
16
|
+
import { BloodlineDirection } from "./..";
|
|
17
|
+
import React, { useMemo } from "react";
|
|
18
|
+
import { Connector } from "../components/Connector";
|
|
19
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
21
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
22
|
+
export var GroupWrapper = function GroupWrapper(props) {
|
|
23
|
+
var type = props.type,
|
|
24
|
+
data = props.data;
|
|
25
|
+
var nodeTypeMap = useNodeTypeMap();
|
|
26
|
+
var Component = useMemo(function () {
|
|
27
|
+
var _nodeTypeMap$get;
|
|
28
|
+
return (_nodeTypeMap$get = nodeTypeMap.get(type)) === null || _nodeTypeMap$get === void 0 ? void 0 : _nodeTypeMap$get._component;
|
|
29
|
+
}, [nodeTypeMap]);
|
|
30
|
+
var origin = data.origin,
|
|
31
|
+
direction = data.direction;
|
|
32
|
+
var innerNodes = (origin === null || origin === void 0 ? void 0 : origin.innerNodes) || [];
|
|
33
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
34
|
+
children: [Component ? /*#__PURE__*/_jsx(Component, _objectSpread({}, props)) : null, innerNodes === null || innerNodes === void 0 ? void 0 : innerNodes.map(function (node) {
|
|
35
|
+
var _nodeTypeMap$get2;
|
|
36
|
+
var NodeComponent = (_nodeTypeMap$get2 = nodeTypeMap.get(node.type)) === null || _nodeTypeMap$get2 === void 0 ? void 0 : _nodeTypeMap$get2._component;
|
|
37
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
38
|
+
style: {
|
|
39
|
+
position: 'relative'
|
|
40
|
+
},
|
|
41
|
+
children: [/*#__PURE__*/_jsx(Connector, {
|
|
42
|
+
source: node,
|
|
43
|
+
direction: BloodlineDirection.upstream
|
|
44
|
+
}), NodeComponent ? /*#__PURE__*/_jsx(NodeComponent, _objectSpread(_objectSpread(_objectSpread({}, props), node), {}, {
|
|
45
|
+
data: {
|
|
46
|
+
direction: direction,
|
|
47
|
+
origin: node
|
|
48
|
+
}
|
|
49
|
+
})) : null, /*#__PURE__*/_jsx(Connector, {
|
|
50
|
+
source: node,
|
|
51
|
+
direction: BloodlineDirection.downstream
|
|
52
|
+
})]
|
|
53
|
+
}, node.id);
|
|
54
|
+
})]
|
|
55
|
+
});
|
|
56
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BloodlineDirection } from "../constants";
|
|
2
|
+
import { BaseBloodNode } from "../types";
|
|
3
|
+
export declare const Connector: ({ direction, source, disabled }: {
|
|
4
|
+
direction: BloodlineDirection;
|
|
5
|
+
source: BaseBloodNode;
|
|
6
|
+
disabled?: boolean | undefined;
|
|
7
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=Connector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Connector.d.ts","sourceRoot":"","sources":["Connector.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAC,kBAAkB,EAAoB,MAAM,cAAc,CAAC;AACnE,OAAO,EAAC,aAAa,EAAsC,MAAM,UAAU,CAAC;AAwC5E,eAAO,MAAM,SAAS;eAMP,kBAAkB;YACrB,aAAa;;6CAyFxB,CAAA"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
var _excluded = ["state", "list"];
|
|
3
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
7
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
8
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
9
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
10
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
11
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
12
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
13
|
+
/**
|
|
14
|
+
* @author: yanxianliang
|
|
15
|
+
* @date: 2025-07-05 15:19
|
|
16
|
+
* @desc: 连接器
|
|
17
|
+
*
|
|
18
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
19
|
+
*/
|
|
20
|
+
import { CollapseButton, HiddenHandle, useForceUpdate, useGetProps } from "@rxflow/base";
|
|
21
|
+
import { Position } from "@xyflow/react";
|
|
22
|
+
import { useMemoizedFn, useUpdate } from "ahooks";
|
|
23
|
+
import React, { useMemo } from "react";
|
|
24
|
+
import { BloodlineDirection, BloodlineNodeType } from "../constants";
|
|
25
|
+
import { getConnectorId } from "../utils/keys";
|
|
26
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
27
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
28
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
29
|
+
function collapseVersionsNode(direction, node) {
|
|
30
|
+
var _iterator = _createForOfIteratorHelper(node.versions),
|
|
31
|
+
_step;
|
|
32
|
+
try {
|
|
33
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
34
|
+
var version = _step.value;
|
|
35
|
+
version[direction] && (version[direction].state = 'collapsed');
|
|
36
|
+
}
|
|
37
|
+
} catch (err) {
|
|
38
|
+
_iterator.e(err);
|
|
39
|
+
} finally {
|
|
40
|
+
_iterator.f();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function collapseGroup(direction, node) {
|
|
44
|
+
var _node$state;
|
|
45
|
+
var list = (_node$state = node.state) === null || _node$state === void 0 ? void 0 : _node$state.list;
|
|
46
|
+
if (list) {
|
|
47
|
+
collapseSiblings(direction, list);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function collapseSiblings(direction, siblings) {
|
|
51
|
+
var _iterator2 = _createForOfIteratorHelper(siblings),
|
|
52
|
+
_step2;
|
|
53
|
+
try {
|
|
54
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
55
|
+
var sibling = _step2.value;
|
|
56
|
+
var type = sibling.type;
|
|
57
|
+
switch (type) {
|
|
58
|
+
case BloodlineNodeType.Service:
|
|
59
|
+
collapseVersionsNode(direction, sibling);
|
|
60
|
+
break;
|
|
61
|
+
case BloodlineNodeType.ServiceGroup:
|
|
62
|
+
collapseGroup(direction, sibling);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch (err) {
|
|
67
|
+
_iterator2.e(err);
|
|
68
|
+
} finally {
|
|
69
|
+
_iterator2.f();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function getStateWithDefault(config) {
|
|
73
|
+
var _ref = config || {},
|
|
74
|
+
_ref$state = _ref.state,
|
|
75
|
+
state = _ref$state === void 0 ? 'collapsed' : _ref$state,
|
|
76
|
+
list = _ref.list,
|
|
77
|
+
extra = _objectWithoutProperties(_ref, _excluded);
|
|
78
|
+
return _objectSpread(_objectSpread({}, extra), {}, {
|
|
79
|
+
state: state,
|
|
80
|
+
list: list
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
export var Connector = function Connector(_ref2) {
|
|
84
|
+
var direction = _ref2.direction,
|
|
85
|
+
source = _ref2.source,
|
|
86
|
+
_ref2$disabled = _ref2.disabled,
|
|
87
|
+
disabled = _ref2$disabled === void 0 ? false : _ref2$disabled;
|
|
88
|
+
var update = useUpdate();
|
|
89
|
+
var triggerLayout = useForceUpdate();
|
|
90
|
+
var getProps = useGetProps();
|
|
91
|
+
var config = source[direction];
|
|
92
|
+
var connectorState = useMemo(function () {
|
|
93
|
+
return getStateWithDefault(config);
|
|
94
|
+
}, [config === null || config === void 0 ? void 0 : config.state]);
|
|
95
|
+
var count = connectorState.count,
|
|
96
|
+
state = connectorState.state,
|
|
97
|
+
_connectorState$disab = connectorState.disableCollapse,
|
|
98
|
+
disableCollapse = _connectorState$disab === void 0 ? false : _connectorState$disab;
|
|
99
|
+
var notShow = !config || config.count === 0 || disabled;
|
|
100
|
+
var position = direction === BloodlineDirection.upstream ? Position.Left : Position.Right;
|
|
101
|
+
var onClick = useMemoizedFn(function () {
|
|
102
|
+
var state = connectorState.state,
|
|
103
|
+
list = connectorState.list;
|
|
104
|
+
var _getProps = getProps(),
|
|
105
|
+
getRelation = _getProps.getRelation;
|
|
106
|
+
if (state === 'loading') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (state === 'collapsed') {
|
|
110
|
+
if (list || !getRelation) {
|
|
111
|
+
// 数据已经缓存了,不需要再次加载
|
|
112
|
+
config.state = 'expanded'; // 展开状态,关联的节点需要显示,在布局函数中处理
|
|
113
|
+
triggerLayout();
|
|
114
|
+
} else {
|
|
115
|
+
config.state = 'loading';
|
|
116
|
+
update(); // 变成加载状态
|
|
117
|
+
getRelation(direction, source).then(function (_ref3) {
|
|
118
|
+
var count = _ref3.count,
|
|
119
|
+
list = _ref3.list;
|
|
120
|
+
// 执行互斥逻辑,将同级所有节点展开项全部关闭
|
|
121
|
+
if (config.state === 'loading') {
|
|
122
|
+
// 可能已经被收起来了
|
|
123
|
+
config.state = 'expanded';
|
|
124
|
+
config.count = count;
|
|
125
|
+
config.list = list;
|
|
126
|
+
triggerLayout();
|
|
127
|
+
} else {
|
|
128
|
+
config.count = count;
|
|
129
|
+
config.list = list;
|
|
130
|
+
update();
|
|
131
|
+
}
|
|
132
|
+
}).catch(function () {
|
|
133
|
+
// 异常兜底,
|
|
134
|
+
config.state = 'collapsed'; // 支持重试
|
|
135
|
+
update();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
config.state = 'collapsed';
|
|
140
|
+
triggerLayout();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
var handleType = direction === BloodlineDirection.upstream ? 'target' : 'source';
|
|
144
|
+
var handle = /*#__PURE__*/_jsx(HiddenHandle, {
|
|
145
|
+
type: handleType,
|
|
146
|
+
position: position,
|
|
147
|
+
id: getConnectorId(direction, source.id)
|
|
148
|
+
});
|
|
149
|
+
if (notShow) {
|
|
150
|
+
return handle;
|
|
151
|
+
}
|
|
152
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
153
|
+
children: [handle, disableCollapse ? null : /*#__PURE__*/_jsx(CollapseButton, {
|
|
154
|
+
direction: 'vertical',
|
|
155
|
+
collapsed: state === 'collapsed',
|
|
156
|
+
position: position,
|
|
157
|
+
loading: state === 'loading',
|
|
158
|
+
onCollapse: onClick,
|
|
159
|
+
count: count
|
|
160
|
+
})]
|
|
161
|
+
});
|
|
162
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author: yanxianliang
|
|
3
|
+
* @date: 2025-07-05 15:48
|
|
4
|
+
* @desc: 常量
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2025 by yanxianliang, All Rights Reserved.
|
|
7
|
+
*/
|
|
8
|
+
export declare enum BloodlineDirection {
|
|
9
|
+
upstream = "upstream",
|
|
10
|
+
downstream = "downstream"
|
|
11
|
+
}
|
|
12
|
+
export declare enum BloodlineNodeType {
|
|
13
|
+
Service = "service",// 服务节点,支持单版本和多版本。
|
|
14
|
+
ServiceGroup = "service-group"
|
|
15
|
+
}
|
|
16
|
+
export declare enum Align {
|
|
17
|
+
center = "center",
|
|
18
|
+
top = "top"
|
|
19
|
+
}
|
|
20
|
+
export declare const sideSymbol: unique symbol;
|
|
21
|
+
export declare const parentIdSymbol: unique symbol;
|
|
22
|
+
export declare enum SplitSide {
|
|
23
|
+
left = "left",
|
|
24
|
+
right = "right"
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oBAAY,kBAAkB;IAC5B,QAAQ,aAAa;IACrB,UAAU,eAAe;CAC1B;AAGD,oBAAY,iBAAiB;IAC3B,OAAO,YAAY,CAAE,kBAAkB;IACvC,YAAY,kBAAkB;CAC/B;AAGD,oBAAY,KAAK;IACf,MAAM,WAAW;IACjB,GAAG,QAAQ;CACZ;AAGD,eAAO,MAAM,UAAU,eAA8B,CAAC;AACtD,eAAO,MAAM,cAAc,eAA8B,CAAC;AAE1D,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,KAAK,UAAU;CAChB"}
|