@falkordb/canvas 0.0.3 → 0.0.7
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/dist/canvas-types.d.ts +81 -0
- package/dist/canvas-types.d.ts.map +1 -0
- package/dist/canvas-types.js +2 -0
- package/dist/canvas-types.js.map +1 -0
- package/dist/canvas-utils.d.ts +18 -0
- package/dist/canvas-utils.d.ts.map +1 -0
- package/dist/canvas-utils.js +143 -0
- package/dist/canvas-utils.js.map +1 -0
- package/dist/canvas.d.ts +45 -0
- package/dist/canvas.d.ts.map +1 -0
- package/dist/canvas.js +653 -0
- package/dist/canvas.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/package.json +10 -2
- package/src/{falkordb-canvas-types.ts → canvas-types.ts} +4 -0
- package/src/{falkordb-canvas-utils.ts → canvas-utils.ts} +1 -1
- package/src/{falkordb-canvas.ts → canvas.ts} +25 -4
- package/src/index.ts +3 -3
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { NodeObject } from "force-graph";
|
|
2
|
+
export interface ForceGraphConfig {
|
|
3
|
+
width?: number;
|
|
4
|
+
height?: number;
|
|
5
|
+
backgroundColor?: string;
|
|
6
|
+
foregroundColor?: string;
|
|
7
|
+
displayTextPriority?: TextPriority[];
|
|
8
|
+
onNodeClick?: (node: GraphNode, event: MouseEvent) => void;
|
|
9
|
+
onLinkClick?: (link: GraphLink, event: MouseEvent) => void;
|
|
10
|
+
onNodeRightClick?: (node: GraphNode, event: MouseEvent) => void;
|
|
11
|
+
onLinkRightClick?: (link: GraphLink, event: MouseEvent) => void;
|
|
12
|
+
onNodeHover?: (node: GraphNode | null) => void;
|
|
13
|
+
onLinkHover?: (link: GraphLink | null) => void;
|
|
14
|
+
onBackgroundClick?: (event: MouseEvent) => void;
|
|
15
|
+
onBackgroundRightClick?: (event: MouseEvent) => void;
|
|
16
|
+
onZoom?: (transform: Transform) => void;
|
|
17
|
+
onEngineStop?: () => void;
|
|
18
|
+
onLoadingChange?: (loading: boolean) => void;
|
|
19
|
+
cooldownTicks?: number | undefined;
|
|
20
|
+
cooldownTime?: number;
|
|
21
|
+
isLinkSelected?: (link: GraphLink) => boolean;
|
|
22
|
+
isNodeSelected?: (node: GraphNode) => boolean;
|
|
23
|
+
isLoading?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type GraphNode = NodeObject & {
|
|
26
|
+
id: number;
|
|
27
|
+
labels: string[];
|
|
28
|
+
color: string;
|
|
29
|
+
visible: boolean;
|
|
30
|
+
displayName: [string, string];
|
|
31
|
+
data: {
|
|
32
|
+
[key: string]: any;
|
|
33
|
+
};
|
|
34
|
+
x?: number;
|
|
35
|
+
y?: number;
|
|
36
|
+
vx?: number;
|
|
37
|
+
vy?: number;
|
|
38
|
+
fx?: number;
|
|
39
|
+
fy?: number;
|
|
40
|
+
};
|
|
41
|
+
export type GraphLink = {
|
|
42
|
+
id: number;
|
|
43
|
+
relationship: string;
|
|
44
|
+
color: string;
|
|
45
|
+
source: GraphNode;
|
|
46
|
+
target: GraphNode;
|
|
47
|
+
visible: boolean;
|
|
48
|
+
curve: number;
|
|
49
|
+
data: {
|
|
50
|
+
[key: string]: any;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
export interface GraphData {
|
|
54
|
+
nodes: GraphNode[];
|
|
55
|
+
links: GraphLink[];
|
|
56
|
+
}
|
|
57
|
+
export type Node = Omit<GraphNode, "x" | "y" | "vx" | "vy" | "fx" | "fy" | "displayName">;
|
|
58
|
+
export type Link = Omit<GraphLink, "curve" | "source" | "target"> & {
|
|
59
|
+
source: number;
|
|
60
|
+
target: number;
|
|
61
|
+
};
|
|
62
|
+
export interface Data {
|
|
63
|
+
nodes: Node[];
|
|
64
|
+
links: Link[];
|
|
65
|
+
}
|
|
66
|
+
export type TextPriority = {
|
|
67
|
+
name: string;
|
|
68
|
+
ignore: boolean;
|
|
69
|
+
};
|
|
70
|
+
export type ViewportState = {
|
|
71
|
+
zoom: number;
|
|
72
|
+
centerX: number;
|
|
73
|
+
centerY: number;
|
|
74
|
+
} | undefined;
|
|
75
|
+
export type Transform = {
|
|
76
|
+
k: number;
|
|
77
|
+
x: number;
|
|
78
|
+
y: number;
|
|
79
|
+
};
|
|
80
|
+
export type ForceGraphInstance = import("force-graph").default<GraphNode, GraphLink> | undefined;
|
|
81
|
+
//# sourceMappingURL=canvas-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-types.d.ts","sourceRoot":"","sources":["../src/canvas-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-types.js","sourceRoot":"","sources":["../src/canvas-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Data, GraphData, Node, TextPriority } from "./canvas-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Converts Data format to GraphData format
|
|
4
|
+
* Adds runtime properties (x, y, vx, vy, fx, fy, displayName, curve)
|
|
5
|
+
*/
|
|
6
|
+
export declare function dataToGraphData(data: Data): GraphData;
|
|
7
|
+
/**
|
|
8
|
+
* Converts GraphData format to Data format
|
|
9
|
+
* Removes runtime properties (x, y, vx, vy, fx, fy, displayName, curve)
|
|
10
|
+
*/
|
|
11
|
+
export declare function graphDataToData(graphData: GraphData): Data;
|
|
12
|
+
export declare const getNodeDisplayText: (node: Node, displayTextPriority: TextPriority[]) => string;
|
|
13
|
+
export declare const getNodeDisplayKey: (node: Node, displayTextPriority: TextPriority[]) => string;
|
|
14
|
+
/**
|
|
15
|
+
* Wraps text into two lines with ellipsis handling for circular nodes
|
|
16
|
+
*/
|
|
17
|
+
export declare const wrapTextForCircularNode: (ctx: CanvasRenderingContext2D, text: string, maxRadius: number) => [string, string];
|
|
18
|
+
//# sourceMappingURL=canvas-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-utils.d.ts","sourceRoot":"","sources":["../src/canvas-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,SAAS,EACT,IAAI,EAIJ,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CA+BrD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAkB1D;AAED,eAAO,MAAM,kBAAkB,GAC7B,MAAM,IAAI,EACV,qBAAqB,YAAY,EAAE,WA+BpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM,IAAI,EACV,qBAAqB,YAAY,EAAE,WA+BpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,wBAAwB,EAC7B,MAAM,MAAM,EACZ,WAAW,MAAM,KAChB,CAAC,MAAM,EAAE,MAAM,CAoDjB,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts Data format to GraphData format
|
|
3
|
+
* Adds runtime properties (x, y, vx, vy, fx, fy, displayName, curve)
|
|
4
|
+
*/
|
|
5
|
+
export function dataToGraphData(data) {
|
|
6
|
+
const nodes = data.nodes.map((node) => ({
|
|
7
|
+
...node,
|
|
8
|
+
displayName: ["", ""],
|
|
9
|
+
x: undefined,
|
|
10
|
+
y: undefined,
|
|
11
|
+
vx: undefined,
|
|
12
|
+
vy: undefined,
|
|
13
|
+
fx: undefined,
|
|
14
|
+
fy: undefined,
|
|
15
|
+
}));
|
|
16
|
+
// Create a Map for O(1) node lookups by id
|
|
17
|
+
const nodeMap = new Map();
|
|
18
|
+
nodes.forEach((node) => {
|
|
19
|
+
nodeMap.set(node.id, node);
|
|
20
|
+
});
|
|
21
|
+
const links = data.links.map((link) => {
|
|
22
|
+
const sourceNode = nodeMap.get(link.source);
|
|
23
|
+
const targetNode = nodeMap.get(link.target);
|
|
24
|
+
return {
|
|
25
|
+
...link,
|
|
26
|
+
source: sourceNode,
|
|
27
|
+
target: targetNode,
|
|
28
|
+
curve: 0,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
return { nodes, links };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Converts GraphData format to Data format
|
|
35
|
+
* Removes runtime properties (x, y, vx, vy, fx, fy, displayName, curve)
|
|
36
|
+
*/
|
|
37
|
+
export function graphDataToData(graphData) {
|
|
38
|
+
const nodes = graphData.nodes.map((node) => {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
40
|
+
const { x, y, vx, vy, fx, fy, displayName, ...rest } = node;
|
|
41
|
+
return rest;
|
|
42
|
+
});
|
|
43
|
+
const links = graphData.links.map((link) => {
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
45
|
+
const { curve, source, target, ...rest } = link;
|
|
46
|
+
return {
|
|
47
|
+
...rest,
|
|
48
|
+
source: source.id,
|
|
49
|
+
target: target.id,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
return { nodes, links };
|
|
53
|
+
}
|
|
54
|
+
export const getNodeDisplayText = (node, displayTextPriority) => {
|
|
55
|
+
const { data: nodeData } = node;
|
|
56
|
+
const displayText = displayTextPriority.find(({ name, ignore }) => {
|
|
57
|
+
const key = ignore
|
|
58
|
+
? Object.keys(nodeData).find((k) => k.toLowerCase() === name.toLowerCase())
|
|
59
|
+
: name;
|
|
60
|
+
return (key &&
|
|
61
|
+
nodeData[key] &&
|
|
62
|
+
typeof nodeData[key] === "string" &&
|
|
63
|
+
nodeData[key].trim().length > 0);
|
|
64
|
+
});
|
|
65
|
+
if (displayText) {
|
|
66
|
+
const key = displayText.ignore
|
|
67
|
+
? Object.keys(nodeData).find((k) => k.toLowerCase() === displayText.name.toLowerCase())
|
|
68
|
+
: displayText.name;
|
|
69
|
+
if (key) {
|
|
70
|
+
return String(nodeData[key]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return String(node.id);
|
|
74
|
+
};
|
|
75
|
+
export const getNodeDisplayKey = (node, displayTextPriority) => {
|
|
76
|
+
const { data: nodeData } = node;
|
|
77
|
+
const displayText = displayTextPriority.find(({ name, ignore }) => {
|
|
78
|
+
const key = ignore
|
|
79
|
+
? Object.keys(nodeData).find((k) => k.toLowerCase() === name.toLowerCase())
|
|
80
|
+
: name;
|
|
81
|
+
return (key &&
|
|
82
|
+
nodeData[key] &&
|
|
83
|
+
typeof nodeData[key] === "string" &&
|
|
84
|
+
nodeData[key].trim().length > 0);
|
|
85
|
+
});
|
|
86
|
+
if (displayText) {
|
|
87
|
+
const key = displayText.ignore
|
|
88
|
+
? Object.keys(nodeData).find((k) => k.toLowerCase() === displayText.name.toLowerCase())
|
|
89
|
+
: displayText.name;
|
|
90
|
+
if (key) {
|
|
91
|
+
return key;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return String(node.id);
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Wraps text into two lines with ellipsis handling for circular nodes
|
|
98
|
+
*/
|
|
99
|
+
export const wrapTextForCircularNode = (ctx, text, maxRadius) => {
|
|
100
|
+
const ellipsis = "...";
|
|
101
|
+
const ellipsisWidth = ctx.measureText(ellipsis).width;
|
|
102
|
+
const halfTextHeight = 1.125;
|
|
103
|
+
const availableRadius = Math.sqrt(Math.max(0, maxRadius * maxRadius - halfTextHeight * halfTextHeight));
|
|
104
|
+
const lineWidth = availableRadius * 2;
|
|
105
|
+
const words = text.split(/\s+/);
|
|
106
|
+
let line1 = "";
|
|
107
|
+
let line2 = "";
|
|
108
|
+
for (let i = 0; i < words.length; i += 1) {
|
|
109
|
+
const word = words[i];
|
|
110
|
+
const testLine = line1 ? `${line1} ${word}` : word;
|
|
111
|
+
const testWidth = ctx.measureText(testLine).width;
|
|
112
|
+
if (testWidth <= lineWidth) {
|
|
113
|
+
line1 = testLine;
|
|
114
|
+
}
|
|
115
|
+
else if (!line1) {
|
|
116
|
+
let partialWord = word;
|
|
117
|
+
while (partialWord.length > 0 &&
|
|
118
|
+
ctx.measureText(partialWord).width > lineWidth) {
|
|
119
|
+
partialWord = partialWord.slice(0, -1);
|
|
120
|
+
}
|
|
121
|
+
line1 = partialWord;
|
|
122
|
+
const remainingWords = [
|
|
123
|
+
word.slice(partialWord.length),
|
|
124
|
+
...words.slice(i + 1),
|
|
125
|
+
];
|
|
126
|
+
line2 = remainingWords.join(" ");
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
line2 = words.slice(i).join(" ");
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (line2 && ctx.measureText(line2).width > lineWidth) {
|
|
135
|
+
while (line2.length > 0 &&
|
|
136
|
+
ctx.measureText(line2).width + ellipsisWidth > lineWidth) {
|
|
137
|
+
line2 = line2.slice(0, -1);
|
|
138
|
+
}
|
|
139
|
+
line2 += ellipsis;
|
|
140
|
+
}
|
|
141
|
+
return [line1, line2 || ""];
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=canvas-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-utils.js","sourceRoot":"","sources":["../src/canvas-utils.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAU;IACxC,MAAM,KAAK,GAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnD,GAAG,IAAI;QACP,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAAqB;QACzC,CAAC,EAAE,SAAS;QACZ,CAAC,EAAE,SAAS;QACZ,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,SAAS;KACd,CAAC,CAAC,CAAC;IAEJ,2CAA2C;IAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC7C,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE5C,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,UAAW;YACnB,MAAM,EAAE,UAAW;YACnB,KAAK,EAAE,CAAC;SACT,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAoB;IAClD,MAAM,KAAK,GAAW,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjD,6DAA6D;QAC7D,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAW,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjD,6DAA6D;QAC7D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QAChD,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,MAAM,CAAC,EAAE;YACjB,MAAM,EAAE,MAAM,CAAC,EAAE;SAClB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,IAAU,EACV,mBAAmC,EACnC,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAChE,MAAM,GAAG,GAAG,MAAM;YAChB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAC9C;YACD,CAAC,CAAC,IAAI,CAAC;QAET,OAAO,CACL,GAAG;YACH,QAAQ,CAAC,GAAG,CAAC;YACb,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,QAAQ;YACjC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAChC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM;YAC5B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,CAC1D;YACD,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC;QAErB,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAU,EACV,mBAAmC,EACnC,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAChE,MAAM,GAAG,GAAG,MAAM;YAChB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAC9C;YACD,CAAC,CAAC,IAAI,CAAC;QAET,OAAO,CACL,GAAG;YACH,QAAQ,CAAC,GAAG,CAAC;YACb,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,QAAQ;YACjC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAChC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM;YAC5B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,CAC1D;YACD,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC;QAErB,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,GAA6B,EAC7B,IAAY,EACZ,SAAiB,EACC,EAAE;IACpB,MAAM,QAAQ,GAAG,KAAK,CAAC;IACvB,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC;IACtD,MAAM,cAAc,GAAG,KAAK,CAAC;IAC7B,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAC/B,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,cAAc,GAAG,cAAc,CAAC,CACrE,CAAC;IACF,MAAM,SAAS,GAAG,eAAe,GAAG,CAAC,CAAC;IAEtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,KAAK,GAAG,EAAE,CAAC;IAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC;QAElD,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;YAC3B,KAAK,GAAG,QAAQ,CAAC;QACnB,CAAC;aAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,WAAW,GAAG,IAAI,CAAC;YACvB,OACE,WAAW,CAAC,MAAM,GAAG,CAAC;gBACtB,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,KAAK,GAAG,SAAS,EAC9C,CAAC;gBACD,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACzC,CAAC;YACD,KAAK,GAAG,WAAW,CAAC;YACpB,MAAM,cAAc,GAAG;gBACrB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;gBAC9B,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;aACtB,CAAC;YACF,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM;QACR,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,KAAK,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,SAAS,EAAE,CAAC;QACtD,OACE,KAAK,CAAC,MAAM,GAAG,CAAC;YAChB,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,EACxD,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,KAAK,IAAI,QAAQ,CAAC;IACpB,CAAC;IAED,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC,CAAC"}
|
package/dist/canvas.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Data, ForceGraphInstance, GraphData, GraphNode, ForceGraphConfig, ViewportState } from "./canvas-types.js";
|
|
2
|
+
declare class FalkorDBCanvas extends HTMLElement {
|
|
3
|
+
private graph;
|
|
4
|
+
private container;
|
|
5
|
+
private loadingOverlay;
|
|
6
|
+
private data;
|
|
7
|
+
private config;
|
|
8
|
+
private nodeDegreeMap;
|
|
9
|
+
private relationshipsTextCache;
|
|
10
|
+
private viewport;
|
|
11
|
+
constructor();
|
|
12
|
+
connectedCallback(): void;
|
|
13
|
+
disconnectedCallback(): void;
|
|
14
|
+
setConfig(config: Partial<ForceGraphConfig>): void;
|
|
15
|
+
setWidth(width: number): void;
|
|
16
|
+
setHeight(height: number): void;
|
|
17
|
+
setBackgroundColor(color: string): void;
|
|
18
|
+
setForegroundColor(color: string): void;
|
|
19
|
+
setIsLoading(isLoading: boolean): void;
|
|
20
|
+
setCooldownTicks(ticks: number | undefined): void;
|
|
21
|
+
setDisplayTextPriority(priority: ForceGraphConfig['displayTextPriority']): void;
|
|
22
|
+
getData(): Data;
|
|
23
|
+
setData(data: Data): void;
|
|
24
|
+
getViewport(): ViewportState;
|
|
25
|
+
setViewport(viewport: ViewportState): void;
|
|
26
|
+
getGraphData(): GraphData;
|
|
27
|
+
setGraphData(data: GraphData): void;
|
|
28
|
+
getGraph(): ForceGraphInstance | undefined;
|
|
29
|
+
getZoom(): number;
|
|
30
|
+
zoom(zoomLevel: number): ForceGraphInstance | undefined;
|
|
31
|
+
zoomToFit(paddingMultiplier?: number, filter?: (node: GraphNode) => boolean): void;
|
|
32
|
+
private triggerRender;
|
|
33
|
+
private calculateNodeDegree;
|
|
34
|
+
private createLoadingOverlay;
|
|
35
|
+
private render;
|
|
36
|
+
private initGraph;
|
|
37
|
+
private setupForces;
|
|
38
|
+
private drawNode;
|
|
39
|
+
private drawLink;
|
|
40
|
+
private updateLoadingState;
|
|
41
|
+
private handleEngineStop;
|
|
42
|
+
private updateEventHandlers;
|
|
43
|
+
}
|
|
44
|
+
export default FalkorDBCanvas;
|
|
45
|
+
//# sourceMappingURL=canvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,IAAI,EACJ,kBAAkB,EAClB,SAAS,EAET,SAAS,EACT,gBAAgB,EAChB,aAAa,EAEd,MAAM,mBAAmB,CAAC;AA6C3B,cAAM,cAAe,SAAQ,WAAW;IACtC,OAAO,CAAC,KAAK,CAAqB;IAElC,OAAO,CAAC,SAAS,CAA+B;IAEhD,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO,CAAC,IAAI,CAAuC;IAEnD,OAAO,CAAC,MAAM,CAAwB;IAEtC,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,sBAAsB,CAQhB;IAEd,OAAO,CAAC,QAAQ,CAAgB;;IAOhC,iBAAiB;IAIjB,oBAAoB;IAOpB,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC;IAW3C,QAAQ,CAAC,KAAK,EAAE,MAAM;IAQtB,SAAS,CAAC,MAAM,EAAE,MAAM;IAQxB,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAWhC,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAMhC,YAAY,CAAC,SAAS,EAAE,OAAO;IAM/B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;IAQ1C,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC;IAKxE,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,IAAI,EAAE,IAAI;IAwBlB,WAAW,IAAI,aAAa;IAa5B,WAAW,CAAC,QAAQ,EAAE,aAAa;IAInC,YAAY,IAAI,SAAS;IAIzB,YAAY,CAAC,IAAI,EAAE,SAAS;IAuB5B,QAAQ,IAAI,kBAAkB,GAAG,SAAS;IAInC,OAAO,IAAI,MAAM;IAIjB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAMvD,SAAS,CAAC,iBAAiB,SAAI,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO;IAiB7E,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,oBAAoB;IAmE5B,OAAO,CAAC,MAAM;IAqBd,OAAO,CAAC,SAAS;IAmGjB,OAAO,CAAC,WAAW;IA2EnB,OAAO,CAAC,QAAQ;IA+ChB,OAAO,CAAC,QAAQ;IAqGhB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,mBAAmB;CA8D5B;AAOD,eAAe,cAAc,CAAC"}
|
package/dist/canvas.js
ADDED
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
import ForceGraph from "force-graph";
|
|
3
|
+
import * as d3 from "d3";
|
|
4
|
+
import { dataToGraphData, getNodeDisplayText, graphDataToData, wrapTextForCircularNode, } from "./canvas-utils.js";
|
|
5
|
+
const NODE_SIZE = 6;
|
|
6
|
+
const PADDING = 2;
|
|
7
|
+
// Force constants
|
|
8
|
+
const LINK_DISTANCE = 50;
|
|
9
|
+
const MAX_LINK_DISTANCE = 80;
|
|
10
|
+
const LINK_STRENGTH = 0.5;
|
|
11
|
+
const MIN_LINK_STRENGTH = 0.3;
|
|
12
|
+
const COLLISION_STRENGTH = 1.35;
|
|
13
|
+
const CHARGE_STRENGTH = -5;
|
|
14
|
+
const CENTER_STRENGTH = 0.4;
|
|
15
|
+
const COLLISION_BASE_RADIUS = NODE_SIZE * 2;
|
|
16
|
+
const HIGH_DEGREE_PADDING = 1.25;
|
|
17
|
+
const DEGREE_STRENGTH_DECAY = 15;
|
|
18
|
+
const CROWDING_THRESHOLD = 20;
|
|
19
|
+
// Create styles for the web component
|
|
20
|
+
function createStyles() {
|
|
21
|
+
const style = document.createElement("style");
|
|
22
|
+
style.textContent = `
|
|
23
|
+
:host {
|
|
24
|
+
display: block;
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: 100%;
|
|
27
|
+
}
|
|
28
|
+
@keyframes pulse {
|
|
29
|
+
0%, 100% {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
}
|
|
32
|
+
50% {
|
|
33
|
+
opacity: 0.5;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
return style;
|
|
38
|
+
}
|
|
39
|
+
class FalkorDBCanvas extends HTMLElement {
|
|
40
|
+
constructor() {
|
|
41
|
+
super();
|
|
42
|
+
this.container = null;
|
|
43
|
+
this.loadingOverlay = null;
|
|
44
|
+
this.data = { nodes: [], links: [] };
|
|
45
|
+
this.config = {};
|
|
46
|
+
this.nodeDegreeMap = new Map();
|
|
47
|
+
this.relationshipsTextCache = new Map();
|
|
48
|
+
this.attachShadow({ mode: "open" });
|
|
49
|
+
}
|
|
50
|
+
connectedCallback() {
|
|
51
|
+
this.render();
|
|
52
|
+
}
|
|
53
|
+
disconnectedCallback() {
|
|
54
|
+
if (this.graph) {
|
|
55
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
56
|
+
this.graph._destructor();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
setConfig(config) {
|
|
60
|
+
Object.assign(this.config, config);
|
|
61
|
+
// Update event handlers if they were provided
|
|
62
|
+
if (config.onNodeClick || config.onLinkClick || config.onNodeRightClick || config.onLinkRightClick ||
|
|
63
|
+
config.onNodeHover || config.onLinkHover || config.onBackgroundClick || config.onBackgroundRightClick || config.onZoom ||
|
|
64
|
+
config.onEngineStop || config.isNodeSelected || config.isLinkSelected) {
|
|
65
|
+
this.updateEventHandlers();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
setWidth(width) {
|
|
69
|
+
if (this.config.width === width)
|
|
70
|
+
return;
|
|
71
|
+
this.config.width = width;
|
|
72
|
+
if (this.graph) {
|
|
73
|
+
this.graph.width(width);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
setHeight(height) {
|
|
77
|
+
if (this.config.height === height)
|
|
78
|
+
return;
|
|
79
|
+
this.config.height = height;
|
|
80
|
+
if (this.graph) {
|
|
81
|
+
this.graph.height(height);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
setBackgroundColor(color) {
|
|
85
|
+
if (this.config.backgroundColor === color)
|
|
86
|
+
return;
|
|
87
|
+
this.config.backgroundColor = color;
|
|
88
|
+
if (this.graph) {
|
|
89
|
+
this.graph.backgroundColor(color);
|
|
90
|
+
}
|
|
91
|
+
if (this.loadingOverlay) {
|
|
92
|
+
this.loadingOverlay.style.background = color;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
setForegroundColor(color) {
|
|
96
|
+
if (this.config.foregroundColor === color)
|
|
97
|
+
return;
|
|
98
|
+
this.config.foregroundColor = color;
|
|
99
|
+
this.triggerRender();
|
|
100
|
+
}
|
|
101
|
+
setIsLoading(isLoading) {
|
|
102
|
+
if (this.config.isLoading === isLoading)
|
|
103
|
+
return;
|
|
104
|
+
this.config.isLoading = isLoading;
|
|
105
|
+
this.updateLoadingState();
|
|
106
|
+
}
|
|
107
|
+
setCooldownTicks(ticks) {
|
|
108
|
+
if (this.config.cooldownTicks === ticks)
|
|
109
|
+
return;
|
|
110
|
+
this.config.cooldownTicks = ticks;
|
|
111
|
+
if (this.graph) {
|
|
112
|
+
this.graph.cooldownTicks(ticks ?? Infinity);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
setDisplayTextPriority(priority) {
|
|
116
|
+
this.config.displayTextPriority = priority;
|
|
117
|
+
this.triggerRender();
|
|
118
|
+
}
|
|
119
|
+
getData() {
|
|
120
|
+
return graphDataToData(this.data);
|
|
121
|
+
}
|
|
122
|
+
setData(data) {
|
|
123
|
+
this.data = dataToGraphData(data);
|
|
124
|
+
this.config.cooldownTicks = this.data.nodes.length > 0 ? undefined : 0;
|
|
125
|
+
this.config.isLoading = this.data.nodes.length > 0;
|
|
126
|
+
this.config.onLoadingChange?.(this.config.isLoading);
|
|
127
|
+
// Initialize graph if it hasn't been initialized yet
|
|
128
|
+
if (!this.graph && this.container) {
|
|
129
|
+
this.initGraph();
|
|
130
|
+
}
|
|
131
|
+
if (!this.graph)
|
|
132
|
+
return;
|
|
133
|
+
this.calculateNodeDegree();
|
|
134
|
+
// Update graph data and properties
|
|
135
|
+
this.graph
|
|
136
|
+
.graphData(this.data)
|
|
137
|
+
.cooldownTicks(this.config.cooldownTicks ?? Infinity);
|
|
138
|
+
this.updateLoadingState();
|
|
139
|
+
this.setupForces();
|
|
140
|
+
}
|
|
141
|
+
getViewport() {
|
|
142
|
+
if (!this.graph)
|
|
143
|
+
return undefined;
|
|
144
|
+
const { x: centerX, y: centerY } = this.graph.centerAt();
|
|
145
|
+
const zoom = this.graph.zoom();
|
|
146
|
+
return {
|
|
147
|
+
zoom,
|
|
148
|
+
centerX,
|
|
149
|
+
centerY,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
setViewport(viewport) {
|
|
153
|
+
this.viewport = viewport;
|
|
154
|
+
}
|
|
155
|
+
getGraphData() {
|
|
156
|
+
return this.data;
|
|
157
|
+
}
|
|
158
|
+
setGraphData(data) {
|
|
159
|
+
this.data = data;
|
|
160
|
+
this.config.cooldownTicks = 0;
|
|
161
|
+
this.config.isLoading = false;
|
|
162
|
+
if (!this.graph)
|
|
163
|
+
return;
|
|
164
|
+
this.calculateNodeDegree();
|
|
165
|
+
this.graph
|
|
166
|
+
.graphData(this.data)
|
|
167
|
+
.cooldownTicks(this.config.cooldownTicks ?? Infinity);
|
|
168
|
+
if (this.viewport) {
|
|
169
|
+
this.graph.zoom(this.viewport.zoom, 0);
|
|
170
|
+
this.graph.centerAt(this.viewport.centerX, this.viewport.centerY, 0);
|
|
171
|
+
this.viewport = undefined;
|
|
172
|
+
}
|
|
173
|
+
this.updateLoadingState();
|
|
174
|
+
this.setupForces();
|
|
175
|
+
}
|
|
176
|
+
getGraph() {
|
|
177
|
+
return this.graph;
|
|
178
|
+
}
|
|
179
|
+
getZoom() {
|
|
180
|
+
return this.graph?.zoom() || 0;
|
|
181
|
+
}
|
|
182
|
+
zoom(zoomLevel) {
|
|
183
|
+
if (!this.graph)
|
|
184
|
+
return;
|
|
185
|
+
return this.graph.zoom(zoomLevel);
|
|
186
|
+
}
|
|
187
|
+
zoomToFit(paddingMultiplier = 1, filter) {
|
|
188
|
+
if (!this.graph || !this.shadowRoot)
|
|
189
|
+
return;
|
|
190
|
+
// Get canvas from shadow DOM
|
|
191
|
+
const canvas = this.shadowRoot.querySelector("canvas");
|
|
192
|
+
if (!canvas)
|
|
193
|
+
return;
|
|
194
|
+
const rect = canvas.getBoundingClientRect();
|
|
195
|
+
// Calculate padding as 10% of the smallest canvas dimension
|
|
196
|
+
const minDimension = Math.min(rect.width, rect.height);
|
|
197
|
+
const padding = minDimension * 0.1;
|
|
198
|
+
// Use the force-graph's built-in zoomToFit method
|
|
199
|
+
this.graph.zoomToFit(500, padding * paddingMultiplier, filter);
|
|
200
|
+
}
|
|
201
|
+
triggerRender() {
|
|
202
|
+
if (!this.graph || this.graph.cooldownTicks() !== 0)
|
|
203
|
+
return;
|
|
204
|
+
// If simulation is stopped (0), trigger one tick to re-render
|
|
205
|
+
this.graph.cooldownTicks(1);
|
|
206
|
+
}
|
|
207
|
+
calculateNodeDegree() {
|
|
208
|
+
this.nodeDegreeMap.clear();
|
|
209
|
+
const { nodes, links } = this.data;
|
|
210
|
+
nodes.forEach((node) => this.nodeDegreeMap.set(node.id, 0));
|
|
211
|
+
links.forEach((link) => {
|
|
212
|
+
const sourceId = link.source.id;
|
|
213
|
+
const targetId = link.target.id;
|
|
214
|
+
this.nodeDegreeMap.set(sourceId, (this.nodeDegreeMap.get(sourceId) || 0) + 1);
|
|
215
|
+
this.nodeDegreeMap.set(targetId, (this.nodeDegreeMap.get(targetId) || 0) + 1);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
createLoadingOverlay() {
|
|
219
|
+
const overlay = document.createElement("div");
|
|
220
|
+
overlay.style.cssText = `
|
|
221
|
+
position: absolute;
|
|
222
|
+
inset: 0;
|
|
223
|
+
display: none;
|
|
224
|
+
align-items: center;
|
|
225
|
+
justify-content: center;
|
|
226
|
+
background: ${this.config.backgroundColor || "#FFFFFF"};
|
|
227
|
+
z-index: 10;
|
|
228
|
+
`;
|
|
229
|
+
// Create skeleton loading structure (matching Spinning component pattern)
|
|
230
|
+
const skeletonContainer = document.createElement("div");
|
|
231
|
+
skeletonContainer.style.cssText = `
|
|
232
|
+
display: flex;
|
|
233
|
+
align-items: center;
|
|
234
|
+
gap: 1rem;
|
|
235
|
+
`;
|
|
236
|
+
// Create circular skeleton (matching h-12 w-12 rounded-full)
|
|
237
|
+
const circle = document.createElement("div");
|
|
238
|
+
circle.style.cssText = `
|
|
239
|
+
height: 3rem;
|
|
240
|
+
width: 3rem;
|
|
241
|
+
border-radius: 9999px;
|
|
242
|
+
background-color: #CCCCCC;
|
|
243
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
244
|
+
`;
|
|
245
|
+
// Create lines container (matching space-y-2)
|
|
246
|
+
const linesContainer = document.createElement("div");
|
|
247
|
+
linesContainer.style.cssText = `
|
|
248
|
+
display: flex;
|
|
249
|
+
flex-direction: column;
|
|
250
|
+
gap: 0.5rem;
|
|
251
|
+
`;
|
|
252
|
+
// Create first line (matching h-4 w-[250px])
|
|
253
|
+
const line1 = document.createElement("div");
|
|
254
|
+
line1.style.cssText = `
|
|
255
|
+
height: 1rem;
|
|
256
|
+
width: 250px;
|
|
257
|
+
border-radius: 0.375rem;
|
|
258
|
+
background-color: #CCCCCC;
|
|
259
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
260
|
+
`;
|
|
261
|
+
// Create second line (matching h-4 w-[200px])
|
|
262
|
+
const line2 = document.createElement("div");
|
|
263
|
+
line2.style.cssText = `
|
|
264
|
+
height: 1rem;
|
|
265
|
+
width: 200px;
|
|
266
|
+
border-radius: 0.375rem;
|
|
267
|
+
background-color: #CCCCCC;
|
|
268
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
269
|
+
`;
|
|
270
|
+
linesContainer.appendChild(line1);
|
|
271
|
+
linesContainer.appendChild(line2);
|
|
272
|
+
skeletonContainer.appendChild(circle);
|
|
273
|
+
skeletonContainer.appendChild(linesContainer);
|
|
274
|
+
overlay.appendChild(skeletonContainer);
|
|
275
|
+
return overlay;
|
|
276
|
+
}
|
|
277
|
+
render() {
|
|
278
|
+
if (!this.shadowRoot)
|
|
279
|
+
return;
|
|
280
|
+
// Create container
|
|
281
|
+
this.container = document.createElement("div");
|
|
282
|
+
this.container.style.width = "100%";
|
|
283
|
+
this.container.style.height = "100%";
|
|
284
|
+
this.container.style.position = "relative";
|
|
285
|
+
// Create loading overlay
|
|
286
|
+
this.loadingOverlay = this.createLoadingOverlay();
|
|
287
|
+
// Add styles using standalone function
|
|
288
|
+
const style = createStyles();
|
|
289
|
+
this.shadowRoot.appendChild(style);
|
|
290
|
+
this.shadowRoot.appendChild(this.container);
|
|
291
|
+
this.initGraph();
|
|
292
|
+
this.container.appendChild(this.loadingOverlay);
|
|
293
|
+
}
|
|
294
|
+
initGraph() {
|
|
295
|
+
if (!this.container)
|
|
296
|
+
return;
|
|
297
|
+
this.calculateNodeDegree();
|
|
298
|
+
// Initialize force-graph
|
|
299
|
+
// Cast to any for the factory call pattern, result is properly typed as ForceGraphInstance
|
|
300
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
301
|
+
this.graph = ForceGraph()(this.container)
|
|
302
|
+
.width(this.config.width || 800)
|
|
303
|
+
.height(this.config.height || 600)
|
|
304
|
+
.backgroundColor(this.config.backgroundColor || "#FFFFFF")
|
|
305
|
+
.graphData(this.data)
|
|
306
|
+
.nodeRelSize(NODE_SIZE)
|
|
307
|
+
.nodeCanvasObjectMode(() => "after")
|
|
308
|
+
.linkCanvasObjectMode(() => "after")
|
|
309
|
+
.nodeLabel((node) => getNodeDisplayText(node, this.config.displayTextPriority || []))
|
|
310
|
+
.linkLabel((link) => link.relationship)
|
|
311
|
+
.linkDirectionalArrowRelPos(1)
|
|
312
|
+
.linkDirectionalArrowLength((link) => {
|
|
313
|
+
if (link.source === link.target)
|
|
314
|
+
return 0;
|
|
315
|
+
return this.config.isLinkSelected?.(link) ? 4 : 2;
|
|
316
|
+
})
|
|
317
|
+
.linkDirectionalArrowColor((link) => link.color)
|
|
318
|
+
.linkWidth((link) => this.config.isLinkSelected?.(link) ? 2 : 1)
|
|
319
|
+
.linkCurvature("curve")
|
|
320
|
+
.linkVisibility("visible")
|
|
321
|
+
.nodeVisibility("visible")
|
|
322
|
+
.cooldownTicks(this.config.cooldownTicks ?? Infinity) // undefined = infinite
|
|
323
|
+
.cooldownTime(this.config.cooldownTime ?? 1000)
|
|
324
|
+
.enableNodeDrag(true)
|
|
325
|
+
.enableZoomInteraction(true)
|
|
326
|
+
.enablePanInteraction(true)
|
|
327
|
+
.onNodeClick((node, event) => {
|
|
328
|
+
if (this.config.onNodeClick) {
|
|
329
|
+
this.config.onNodeClick(node, event);
|
|
330
|
+
}
|
|
331
|
+
})
|
|
332
|
+
.onLinkClick((link, event) => {
|
|
333
|
+
if (this.config.onLinkClick) {
|
|
334
|
+
this.config.onLinkClick(link, event);
|
|
335
|
+
}
|
|
336
|
+
})
|
|
337
|
+
.onNodeRightClick((node, event) => {
|
|
338
|
+
if (this.config.onNodeRightClick) {
|
|
339
|
+
this.config.onNodeRightClick(node, event);
|
|
340
|
+
}
|
|
341
|
+
})
|
|
342
|
+
.onLinkRightClick((link, event) => {
|
|
343
|
+
if (this.config.onLinkRightClick) {
|
|
344
|
+
this.config.onLinkRightClick(link, event);
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
.onNodeHover((node) => {
|
|
348
|
+
if (this.config.onNodeHover) {
|
|
349
|
+
this.config.onNodeHover(node);
|
|
350
|
+
}
|
|
351
|
+
})
|
|
352
|
+
.onLinkHover((link) => {
|
|
353
|
+
if (this.config.onLinkHover) {
|
|
354
|
+
this.config.onLinkHover(link);
|
|
355
|
+
}
|
|
356
|
+
})
|
|
357
|
+
.onBackgroundClick((event) => {
|
|
358
|
+
if (this.config.onBackgroundClick) {
|
|
359
|
+
this.config.onBackgroundClick(event);
|
|
360
|
+
}
|
|
361
|
+
})
|
|
362
|
+
.onBackgroundRightClick((event) => {
|
|
363
|
+
if (this.config.onBackgroundRightClick) {
|
|
364
|
+
this.config.onBackgroundRightClick(event);
|
|
365
|
+
}
|
|
366
|
+
})
|
|
367
|
+
.onZoom((transform) => {
|
|
368
|
+
if (this.config.onZoom) {
|
|
369
|
+
this.config.onZoom(transform);
|
|
370
|
+
}
|
|
371
|
+
})
|
|
372
|
+
.onEngineStop(() => {
|
|
373
|
+
this.handleEngineStop();
|
|
374
|
+
if (this.config.onEngineStop) {
|
|
375
|
+
this.config.onEngineStop();
|
|
376
|
+
}
|
|
377
|
+
})
|
|
378
|
+
.nodeCanvasObject((node, ctx) => {
|
|
379
|
+
this.drawNode(node, ctx);
|
|
380
|
+
})
|
|
381
|
+
.linkCanvasObject((link, ctx) => {
|
|
382
|
+
this.drawLink(link, ctx);
|
|
383
|
+
});
|
|
384
|
+
// Setup forces
|
|
385
|
+
this.setupForces();
|
|
386
|
+
}
|
|
387
|
+
setupForces() {
|
|
388
|
+
const linkForce = this.graph?.d3Force("link");
|
|
389
|
+
if (!linkForce)
|
|
390
|
+
return;
|
|
391
|
+
if (!this.graph)
|
|
392
|
+
return;
|
|
393
|
+
// Link force with dynamic distance and strength
|
|
394
|
+
linkForce
|
|
395
|
+
.distance((link) => {
|
|
396
|
+
const sourceId = link.source.id;
|
|
397
|
+
const targetId = link.target.id;
|
|
398
|
+
const sourceDegree = this.nodeDegreeMap.get(sourceId) || 0;
|
|
399
|
+
const targetDegree = this.nodeDegreeMap.get(targetId) || 0;
|
|
400
|
+
const maxDegree = Math.max(sourceDegree, targetDegree);
|
|
401
|
+
if (maxDegree >= CROWDING_THRESHOLD) {
|
|
402
|
+
const extraDistance = Math.min(MAX_LINK_DISTANCE - LINK_DISTANCE, (maxDegree - CROWDING_THRESHOLD) * 1.5);
|
|
403
|
+
return LINK_DISTANCE + extraDistance;
|
|
404
|
+
}
|
|
405
|
+
return LINK_DISTANCE;
|
|
406
|
+
})
|
|
407
|
+
.strength((link) => {
|
|
408
|
+
const sourceId = link.source.id;
|
|
409
|
+
const targetId = link.target.id;
|
|
410
|
+
const sourceDegree = this.nodeDegreeMap.get(sourceId) || 0;
|
|
411
|
+
const targetDegree = this.nodeDegreeMap.get(targetId) || 0;
|
|
412
|
+
const maxDegree = Math.max(sourceDegree, targetDegree);
|
|
413
|
+
if (maxDegree <= DEGREE_STRENGTH_DECAY) {
|
|
414
|
+
return LINK_STRENGTH;
|
|
415
|
+
}
|
|
416
|
+
const strengthReduction = Math.max(0, (maxDegree - DEGREE_STRENGTH_DECAY) / DEGREE_STRENGTH_DECAY);
|
|
417
|
+
const scaledStrength = MIN_LINK_STRENGTH +
|
|
418
|
+
(LINK_STRENGTH - MIN_LINK_STRENGTH) * Math.exp(-strengthReduction);
|
|
419
|
+
return Math.max(MIN_LINK_STRENGTH, scaledStrength);
|
|
420
|
+
});
|
|
421
|
+
// Collision force
|
|
422
|
+
this.graph.d3Force("collision", d3
|
|
423
|
+
.forceCollide((node) => {
|
|
424
|
+
const degree = this.nodeDegreeMap.get(node.id) || 0;
|
|
425
|
+
return (COLLISION_BASE_RADIUS + Math.sqrt(degree) * HIGH_DEGREE_PADDING);
|
|
426
|
+
})
|
|
427
|
+
.strength(COLLISION_STRENGTH)
|
|
428
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
429
|
+
.iterations(2));
|
|
430
|
+
// Center force
|
|
431
|
+
const centerForce = this.graph.d3Force("center");
|
|
432
|
+
if (centerForce) {
|
|
433
|
+
centerForce.strength(CENTER_STRENGTH);
|
|
434
|
+
}
|
|
435
|
+
// Charge force
|
|
436
|
+
const chargeForce = this.graph.d3Force("charge");
|
|
437
|
+
if (chargeForce) {
|
|
438
|
+
chargeForce.strength(CHARGE_STRENGTH).distanceMax(300);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
drawNode(node, ctx) {
|
|
442
|
+
if (!node.x || !node.y) {
|
|
443
|
+
node.x = 0;
|
|
444
|
+
node.y = 0;
|
|
445
|
+
}
|
|
446
|
+
ctx.lineWidth = this.config.isNodeSelected?.(node) ? 1.5 : 0.5;
|
|
447
|
+
ctx.strokeStyle = this.config.foregroundColor || "#1A1A1A";
|
|
448
|
+
ctx.beginPath();
|
|
449
|
+
ctx.arc(node.x, node.y, NODE_SIZE, 0, 2 * Math.PI, false);
|
|
450
|
+
ctx.fillStyle = node.color;
|
|
451
|
+
ctx.fill();
|
|
452
|
+
ctx.stroke();
|
|
453
|
+
// Draw text
|
|
454
|
+
ctx.fillStyle = "black";
|
|
455
|
+
ctx.textAlign = "center";
|
|
456
|
+
ctx.textBaseline = "middle";
|
|
457
|
+
ctx.font = "400 2px SofiaSans";
|
|
458
|
+
let [line1, line2] = node.displayName || ["", ""];
|
|
459
|
+
if (!line1 && !line2) {
|
|
460
|
+
const text = getNodeDisplayText(node, this.config.displayTextPriority || []);
|
|
461
|
+
const textRadius = NODE_SIZE - PADDING / 2;
|
|
462
|
+
[line1, line2] = wrapTextForCircularNode(ctx, text, textRadius);
|
|
463
|
+
node.displayName = [line1, line2];
|
|
464
|
+
}
|
|
465
|
+
const textMetrics = ctx.measureText(line1);
|
|
466
|
+
const textHeight = textMetrics.actualBoundingBoxAscent +
|
|
467
|
+
textMetrics.actualBoundingBoxDescent;
|
|
468
|
+
const halfTextHeight = (textHeight / 2) * 1.5;
|
|
469
|
+
if (line1) {
|
|
470
|
+
ctx.fillText(line1, node.x, line2 ? node.y - halfTextHeight : node.y);
|
|
471
|
+
}
|
|
472
|
+
if (line2) {
|
|
473
|
+
ctx.fillText(line2, node.x, node.y + halfTextHeight);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
drawLink(link, ctx) {
|
|
477
|
+
const start = link.source;
|
|
478
|
+
const end = link.target;
|
|
479
|
+
if (!start.x || !start.y || !end.x || !end.y) {
|
|
480
|
+
start.x = 0;
|
|
481
|
+
start.y = 0;
|
|
482
|
+
end.x = 0;
|
|
483
|
+
end.y = 0;
|
|
484
|
+
}
|
|
485
|
+
let textX;
|
|
486
|
+
let textY;
|
|
487
|
+
let angle;
|
|
488
|
+
if (start.id === end.id) {
|
|
489
|
+
const radius = NODE_SIZE * (link.curve || 0) * 6.2;
|
|
490
|
+
const angleOffset = -Math.PI / 4;
|
|
491
|
+
textX = start.x + radius * Math.cos(angleOffset);
|
|
492
|
+
textY = start.y + radius * Math.sin(angleOffset);
|
|
493
|
+
angle = -angleOffset;
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
const dx = end.x - start.x;
|
|
497
|
+
const dy = end.y - start.y;
|
|
498
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
499
|
+
const perpX = dy / distance;
|
|
500
|
+
const perpY = -dx / distance;
|
|
501
|
+
const curvature = link.curve || 0;
|
|
502
|
+
const controlX = (start.x + end.x) / 2 + perpX * curvature * distance * 1.0;
|
|
503
|
+
const controlY = (start.y + end.y) / 2 + perpY * curvature * distance * 1.0;
|
|
504
|
+
const t = 0.5;
|
|
505
|
+
const oneMinusT = 1 - t;
|
|
506
|
+
textX =
|
|
507
|
+
oneMinusT * oneMinusT * start.x +
|
|
508
|
+
2 * oneMinusT * t * controlX +
|
|
509
|
+
t * t * end.x;
|
|
510
|
+
textY =
|
|
511
|
+
oneMinusT * oneMinusT * start.y +
|
|
512
|
+
2 * oneMinusT * t * controlY +
|
|
513
|
+
t * t * end.y;
|
|
514
|
+
const tangentX = 2 * oneMinusT * (controlX - start.x) + 2 * t * (end.x - controlX);
|
|
515
|
+
const tangentY = 2 * oneMinusT * (controlY - start.y) + 2 * t * (end.y - controlY);
|
|
516
|
+
angle = Math.atan2(tangentY, tangentX);
|
|
517
|
+
if (angle > Math.PI / 2)
|
|
518
|
+
angle = -(Math.PI - angle);
|
|
519
|
+
if (angle < -Math.PI / 2)
|
|
520
|
+
angle = -(-Math.PI - angle);
|
|
521
|
+
}
|
|
522
|
+
ctx.font = "400 2px SofiaSans";
|
|
523
|
+
ctx.textAlign = "center";
|
|
524
|
+
ctx.textBaseline = "middle";
|
|
525
|
+
let cached = this.relationshipsTextCache.get(link.relationship);
|
|
526
|
+
if (!cached) {
|
|
527
|
+
const { width, actualBoundingBoxAscent, actualBoundingBoxDescent } = ctx.measureText(link.relationship);
|
|
528
|
+
cached = {
|
|
529
|
+
textWidth: width,
|
|
530
|
+
textHeight: actualBoundingBoxAscent + actualBoundingBoxDescent,
|
|
531
|
+
textAscent: actualBoundingBoxAscent,
|
|
532
|
+
textDescent: actualBoundingBoxDescent,
|
|
533
|
+
};
|
|
534
|
+
this.relationshipsTextCache.set(link.relationship, cached);
|
|
535
|
+
}
|
|
536
|
+
const { textWidth, textHeight, textAscent, textDescent } = cached;
|
|
537
|
+
ctx.save();
|
|
538
|
+
ctx.translate(textX, textY);
|
|
539
|
+
ctx.rotate(angle);
|
|
540
|
+
// Draw background
|
|
541
|
+
ctx.fillStyle = this.config.backgroundColor || "#FFFFFF";
|
|
542
|
+
const backgroundHeight = textHeight * 0.7;
|
|
543
|
+
// Move background up to align with text that appears at top of bg
|
|
544
|
+
// Use the actual text metrics to calculate proper vertical offset
|
|
545
|
+
const bgOffsetY = -(textAscent - textDescent) - 0.18;
|
|
546
|
+
ctx.fillRect(-textWidth / 2, -backgroundHeight / 2 + bgOffsetY, textWidth, backgroundHeight);
|
|
547
|
+
// Draw text
|
|
548
|
+
ctx.fillStyle = this.config.foregroundColor || "#1A1A1A";
|
|
549
|
+
ctx.textBaseline = "middle";
|
|
550
|
+
ctx.fillText(link.relationship, 0, 0);
|
|
551
|
+
ctx.restore();
|
|
552
|
+
}
|
|
553
|
+
updateLoadingState() {
|
|
554
|
+
if (!this.loadingOverlay)
|
|
555
|
+
return;
|
|
556
|
+
if (this.config.isLoading) {
|
|
557
|
+
this.loadingOverlay.style.display = "flex";
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
this.loadingOverlay.style.display = "none";
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
handleEngineStop() {
|
|
564
|
+
if (!this.graph)
|
|
565
|
+
return;
|
|
566
|
+
// If already stopped, don't do anything
|
|
567
|
+
if (this.config.cooldownTicks === 0)
|
|
568
|
+
return;
|
|
569
|
+
// Zoom to fit using the same logic as handleZoomToFit from utils
|
|
570
|
+
const nodeCount = this.data.nodes.length;
|
|
571
|
+
const paddingMultiplier = nodeCount < 2 ? 4 : 1;
|
|
572
|
+
this.zoomToFit(paddingMultiplier);
|
|
573
|
+
// Stop the force simulation after centering (like it was in ForceGraph.tsx)
|
|
574
|
+
setTimeout(() => {
|
|
575
|
+
if (!this.graph)
|
|
576
|
+
return;
|
|
577
|
+
// Stop loading
|
|
578
|
+
this.config.isLoading = false;
|
|
579
|
+
this.config.onLoadingChange?.(this.config.isLoading);
|
|
580
|
+
this.updateLoadingState();
|
|
581
|
+
this.config.cooldownTicks = 0;
|
|
582
|
+
this.graph.cooldownTicks(0);
|
|
583
|
+
}, 1000);
|
|
584
|
+
}
|
|
585
|
+
updateEventHandlers() {
|
|
586
|
+
if (!this.graph)
|
|
587
|
+
return;
|
|
588
|
+
this.graph
|
|
589
|
+
.onNodeClick((node, event) => {
|
|
590
|
+
if (this.config.onNodeClick) {
|
|
591
|
+
this.config.onNodeClick(node, event);
|
|
592
|
+
}
|
|
593
|
+
})
|
|
594
|
+
.onLinkClick((link, event) => {
|
|
595
|
+
if (this.config.onLinkClick) {
|
|
596
|
+
this.config.onLinkClick(link, event);
|
|
597
|
+
}
|
|
598
|
+
})
|
|
599
|
+
.onNodeRightClick((node, event) => {
|
|
600
|
+
if (this.config.onNodeRightClick) {
|
|
601
|
+
this.config.onNodeRightClick(node, event);
|
|
602
|
+
}
|
|
603
|
+
})
|
|
604
|
+
.onLinkRightClick((link, event) => {
|
|
605
|
+
if (this.config.onLinkRightClick) {
|
|
606
|
+
this.config.onLinkRightClick(link, event);
|
|
607
|
+
}
|
|
608
|
+
})
|
|
609
|
+
.onNodeHover((node) => {
|
|
610
|
+
if (this.config.onNodeHover) {
|
|
611
|
+
this.config.onNodeHover(node);
|
|
612
|
+
}
|
|
613
|
+
})
|
|
614
|
+
.onLinkHover((link) => {
|
|
615
|
+
if (this.config.onLinkHover) {
|
|
616
|
+
this.config.onLinkHover(link);
|
|
617
|
+
}
|
|
618
|
+
})
|
|
619
|
+
.onBackgroundClick((event) => {
|
|
620
|
+
if (this.config.onBackgroundClick) {
|
|
621
|
+
this.config.onBackgroundClick(event);
|
|
622
|
+
}
|
|
623
|
+
})
|
|
624
|
+
.onBackgroundRightClick((event) => {
|
|
625
|
+
if (this.config.onBackgroundRightClick) {
|
|
626
|
+
this.config.onBackgroundRightClick(event);
|
|
627
|
+
}
|
|
628
|
+
})
|
|
629
|
+
.onZoom((transform) => {
|
|
630
|
+
if (this.config.onZoom) {
|
|
631
|
+
this.config.onZoom(transform);
|
|
632
|
+
}
|
|
633
|
+
})
|
|
634
|
+
.onEngineStop(() => {
|
|
635
|
+
this.handleEngineStop();
|
|
636
|
+
if (this.config.onEngineStop) {
|
|
637
|
+
this.config.onEngineStop();
|
|
638
|
+
}
|
|
639
|
+
})
|
|
640
|
+
.nodeCanvasObject((node, ctx) => {
|
|
641
|
+
this.drawNode(node, ctx);
|
|
642
|
+
})
|
|
643
|
+
.linkCanvasObject((link, ctx) => {
|
|
644
|
+
this.drawLink(link, ctx);
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
// Define the custom element
|
|
649
|
+
if (typeof window !== "undefined" && !customElements.get("falkordb-canvas")) {
|
|
650
|
+
customElements.define("falkordb-canvas", FalkorDBCanvas);
|
|
651
|
+
}
|
|
652
|
+
export default FalkorDBCanvas;
|
|
653
|
+
//# sourceMappingURL=canvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas.js","sourceRoot":"","sources":["../src/canvas.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAWzB,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,OAAO,GAAG,CAAC,CAAC;AAElB,kBAAkB;AAClB,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,eAAe,GAAG,CAAC,CAAC,CAAC;AAC3B,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,qBAAqB,GAAG,SAAS,GAAG,CAAC,CAAC;AAC5C,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,sCAAsC;AACtC,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,WAAW,GAAG;;;;;;;;;;;;;;GAcnB,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,cAAe,SAAQ,WAAW;IAyBtC;QACE,KAAK,EAAE,CAAC;QAvBF,cAAS,GAA0B,IAAI,CAAC;QAExC,mBAAc,GAA0B,IAAI,CAAC;QAE7C,SAAI,GAAc,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAE3C,WAAM,GAAqB,EAAE,CAAC;QAE9B,kBAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;QAE/C,2BAAsB,GAQ1B,IAAI,GAAG,EAAE,CAAC;QAMZ,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,oBAAoB;QAClB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,gDAAgD;YAChD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,SAAS,CAAC,MAAiC;QACzC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEnC,8CAA8C;QAC9C,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,gBAAgB,IAAI,MAAM,CAAC,gBAAgB;YAChG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,sBAAsB,IAAI,MAAM,CAAC,MAAM;YACtH,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YACxE,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,KAAa;QACpB,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK;YAAE,OAAO;QACxC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QAC1B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO;QAC1C,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QAC5B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,kBAAkB,CAAC,KAAa;QAC9B,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,KAAK,KAAK;YAAE,OAAO;QAClD,IAAI,CAAC,MAAM,CAAC,eAAe,GAAG,KAAK,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,kBAAkB,CAAC,KAAa;QAC9B,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,KAAK,KAAK;YAAE,OAAO;QAClD,IAAI,CAAC,MAAM,CAAC,eAAe,GAAG,KAAK,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,YAAY,CAAC,SAAkB;QAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS;YAAE,OAAO;QAChD,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAED,gBAAgB,CAAC,KAAyB;QACxC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,KAAK;YAAE,OAAO;QAChD,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC;QAClC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,sBAAsB,CAAC,QAAiD;QACtE,IAAI,CAAC,MAAM,CAAC,mBAAmB,GAAG,QAAQ,CAAC;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,OAAO;QACL,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAGD,OAAO,CAAC,IAAU;QAChB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAErD,qDAAqD;QACrD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QAExB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE3B,mCAAmC;QACnC,IAAI,CAAC,KAAK;aACP,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;aACpB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC;QAExD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAElC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAE/B,OAAO;YACL,IAAI;YACJ,OAAO;YACP,OAAO;SACR,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,QAAuB;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,YAAY,CAAC,IAAe;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAEjB,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;QAE9B,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QAExB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK;aACP,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;aACpB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC;QAExD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAEM,IAAI,CAAC,SAAiB;QAC3B,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QAExB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAEM,SAAS,CAAC,iBAAiB,GAAG,CAAC,EAAE,MAAqC;QAC3E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE5C,6BAA6B;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAsB,CAAC;QAC5E,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;QAE5C,4DAA4D;QAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,YAAY,GAAG,GAAG,CAAC;QAEnC,kDAAkD;QAClD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC;YAAE,OAAO;QAE5D,8DAA8D;QAC9D,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAE5D,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAEhC,IAAI,CAAC,aAAa,CAAC,GAAG,CACpB,QAAQ,EACR,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAC5C,CAAC;YACF,IAAI,CAAC,aAAa,CAAC,GAAG,CACpB,QAAQ,EACR,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAC5C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,oBAAoB;QAC1B,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG;;;;;;oBAMR,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,SAAS;;KAEvD,CAAC;QAEF,0EAA0E;QAC1E,MAAM,iBAAiB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACxD,iBAAiB,CAAC,KAAK,CAAC,OAAO,GAAG;;;;KAIjC,CAAC;QAEF,6DAA6D;QAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG;;;;;;KAMtB,CAAC;QAEF,8CAA8C;QAC9C,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG;;;;KAI9B,CAAC;QAEF,6CAA6C;QAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC5C,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG;;;;;;KAMrB,CAAC;QAEF,8CAA8C;QAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC5C,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG;;;;;;KAMrB,CAAC;QAEF,cAAc,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,cAAc,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACtC,iBAAiB,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC9C,OAAO,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEvC,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,mBAAmB;QACnB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QACrC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;QAE3C,yBAAyB;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAElD,uCAAuC;QACvC,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAE7B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAClD,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAE5B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE3B,yBAAyB;QACzB,2FAA2F;QAC3F,8DAA8D;QAC9D,IAAI,CAAC,KAAK,GAAI,UAAkB,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;aAC/C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC;aAC/B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC;aACjC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;aACzD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;aACpB,WAAW,CAAC,SAAS,CAAC;aACtB,oBAAoB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;aACnC,oBAAoB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;aACnC,SAAS,CAAC,CAAC,IAAe,EAAE,EAAE,CAC7B,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAChE;aACA,SAAS,CAAC,CAAC,IAAe,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;aACjD,0BAA0B,CAAC,CAAC,CAAC;aAC7B,0BAA0B,CAAC,CAAC,IAAe,EAAE,EAAE;YAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;gBAAE,OAAO,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC;aACD,yBAAyB,CAAC,CAAC,IAAe,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;aAC1D,SAAS,CAAC,CAAC,IAAe,EAAE,EAAE,CAC7B,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3C;aACA,aAAa,CAAC,OAAO,CAAC;aACtB,cAAc,CAAC,SAAS,CAAC;aACzB,cAAc,CAAC,SAAS,CAAC;aACzB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,QAAQ,CAAC,CAAC,uBAAuB;aAC5E,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;aAC9C,cAAc,CAAC,IAAI,CAAC;aACpB,qBAAqB,CAAC,IAAI,CAAC;aAC3B,oBAAoB,CAAC,IAAI,CAAC;aAC1B,WAAW,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;aACD,WAAW,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YACvD,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YACvD,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;aACD,WAAW,CAAC,CAAC,IAAsB,EAAE,EAAE;YACtC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;aACD,WAAW,CAAC,CAAC,IAAsB,EAAE,EAAE;YACtC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;aACD,iBAAiB,CAAC,CAAC,KAAiB,EAAE,EAAE;YACvC,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAClC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;aACD,sBAAsB,CAAC,CAAC,KAAiB,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;gBACvC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,SAAoB,EAAE,EAAE;YAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;aACD,YAAY,CAAC,GAAG,EAAE;YACjB,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;gBAC7B,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,GAA6B,EAAE,EAAE;YACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,GAA6B,EAAE,EAAE;YACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEL,eAAe;QACf,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE9C,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QAExB,gDAAgD;QAChD,SAAS;aACN,QAAQ,CAAC,CAAC,IAAe,EAAE,EAAE;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAEvD,IAAI,SAAS,IAAI,kBAAkB,EAAE,CAAC;gBACpC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC5B,iBAAiB,GAAG,aAAa,EACjC,CAAC,SAAS,GAAG,kBAAkB,CAAC,GAAG,GAAG,CACvC,CAAC;gBACF,OAAO,aAAa,GAAG,aAAa,CAAC;YACvC,CAAC;YAED,OAAO,aAAa,CAAC;QACvB,CAAC,CAAC;aACD,QAAQ,CAAC,CAAC,IAAe,EAAE,EAAE;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAEvD,IAAI,SAAS,IAAI,qBAAqB,EAAE,CAAC;gBACvC,OAAO,aAAa,CAAC;YACvB,CAAC;YAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAChC,CAAC,EACD,CAAC,SAAS,GAAG,qBAAqB,CAAC,GAAG,qBAAqB,CAC5D,CAAC;YACF,MAAM,cAAc,GAClB,iBAAiB;gBACjB,CAAC,aAAa,GAAG,iBAAiB,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;YAErE,OAAO,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEL,kBAAkB;QAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAChB,WAAW,EACX,EAAE;aACC,YAAY,CAAC,CAAC,IAAe,EAAE,EAAE;YAChC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACpD,OAAO,CACL,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,mBAAmB,CAChE,CAAC;QACJ,CAAC,CAAC;aACD,QAAQ,CAAC,kBAAkB,CAAC;YAC7B,8DAA8D;aAC7D,UAAU,CAAC,CAAC,CAAQ,CACxB,CAAC;QAEF,eAAe;QACf,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACxC,CAAC;QAED,eAAe;QACf,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,IAAe,EAAE,GAA6B;QAC7D,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACX,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QAED,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/D,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;QAE3D,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3B,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,EAAE,CAAC;QAEb,YAAY;QACZ,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC;QACxB,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC;QACzB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC;QAC5B,GAAG,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAE/B,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,kBAAkB,CAC7B,IAAI,EACJ,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CACtC,CAAC;YACF,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,CAAC,CAAC;YAC3C,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,uBAAuB,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YAChE,IAAI,CAAC,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,UAAU,GACd,WAAW,CAAC,uBAAuB;YACnC,WAAW,CAAC,wBAAwB,CAAC;QACvC,MAAM,cAAc,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;QAE9C,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,IAAe,EAAE,GAA6B;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;QAExB,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7C,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;YACZ,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;YACZ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACV,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC;QAED,IAAI,KAAK,CAAC;QACV,IAAI,KAAK,CAAC;QACV,IAAI,KAAK,CAAC;QAEV,IAAI,KAAK,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;YACnD,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;YACjC,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACjD,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACjD,KAAK,GAAG,CAAC,WAAW,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;YAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;YAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YAE9C,MAAM,KAAK,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,EAAE,GAAG,QAAQ,CAAC;YAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;YAClC,MAAM,QAAQ,GACZ,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,GAAG,CAAC;YAC7D,MAAM,QAAQ,GACZ,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,GAAG,CAAC;YAE7D,MAAM,CAAC,GAAG,GAAG,CAAC;YACd,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;YACxB,KAAK;gBACH,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;oBAC/B,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,QAAQ;oBAC5B,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAChB,KAAK;gBACH,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;oBAC/B,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,QAAQ;oBAC5B,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAEhB,MAAM,QAAQ,GACZ,CAAC,GAAG,SAAS,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;YACpE,MAAM,QAAQ,GACZ,CAAC,GAAG,SAAS,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;YACpE,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAEvC,IAAI,KAAK,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC;gBAAE,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;YACpD,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC;gBAAE,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;QACxD,CAAC;QAED,GAAG,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAC/B,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC;QACzB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC;QAE5B,IAAI,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEhE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,EAAE,KAAK,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,GAChE,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACrC,MAAM,GAAG;gBACP,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,uBAAuB,GAAG,wBAAwB;gBAC9D,UAAU,EAAE,uBAAuB;gBACnC,WAAW,EAAE,wBAAwB;aACtC,CAAC;YACF,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;QAElE,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5B,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAElB,kBAAkB;QAClB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;QACzD,MAAM,gBAAgB,GAAG,UAAU,GAAG,GAAG,CAAC;QAE1C,kEAAkE;QAClE,kEAAkE;QAClE,MAAM,SAAS,GAAG,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC;QACrD,GAAG,CAAC,QAAQ,CACV,CAAC,SAAS,GAAG,CAAC,EACd,CAAC,gBAAgB,GAAG,CAAC,GAAG,SAAS,EACjC,SAAS,EACT,gBAAgB,CACjB,CAAC;QAEF,YAAY;QACZ,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;QACzD,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC;QAC5B,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,GAAG,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAO;QAEjC,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC7C,CAAC;IACH,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QAExB,wCAAwC;QACxC,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,CAAC;YAAE,OAAO;QAE5C,iEAAiE;QACjE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QACzC,MAAM,iBAAiB,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAElC,4EAA4E;QAC5E,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,IAAI,CAAC,KAAK;gBAAE,OAAO;YACxB,eAAe;YACf,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QAExB,IAAI,CAAC,KAAK;aACP,WAAW,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;aACD,WAAW,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YACvD,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,KAAiB,EAAE,EAAE;YACvD,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;aACD,WAAW,CAAC,CAAC,IAAsB,EAAE,EAAE;YACtC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;aACD,WAAW,CAAC,CAAC,IAAsB,EAAE,EAAE;YACtC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;aACD,iBAAiB,CAAC,CAAC,KAAiB,EAAE,EAAE;YACvC,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAClC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;aACD,sBAAsB,CAAC,CAAC,KAAiB,EAAE,EAAE;YAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;gBACvC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,SAAoB,EAAE,EAAE;YAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;aACD,YAAY,CAAC,GAAG,EAAE;YACjB,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;gBAC7B,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,GAA6B,EAAE,EAAE;YACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC;aACD,gBAAgB,CAAC,CAAC,IAAe,EAAE,GAA6B,EAAE,EAAE;YACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACP,CAAC;CACF;AAED,4BAA4B;AAC5B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAC5E,cAAc,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,eAAe,cAAc,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import FalkorDBCanvas from "./canvas";
|
|
2
|
+
import type React from "react";
|
|
3
|
+
declare global {
|
|
4
|
+
interface HTMLElementTagNameMap {
|
|
5
|
+
"falkordb-canvas": FalkorDBCanvas;
|
|
6
|
+
}
|
|
7
|
+
namespace JSX {
|
|
8
|
+
interface IntrinsicElements {
|
|
9
|
+
"falkordb-canvas": React.DetailedHTMLProps<React.HTMLAttributes<FalkorDBCanvas>, FalkorDBCanvas>;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export { FalkorDBCanvas as default, FalkorDBCanvas };
|
|
14
|
+
export type { ForceGraphConfig, GraphNode, GraphLink, GraphData, Node, Link, Data, TextPriority, ViewportState, ForceGraphInstance, } from "./canvas-types";
|
|
15
|
+
export { dataToGraphData, graphDataToData, getNodeDisplayText, getNodeDisplayKey, wrapTextForCircularNode, } from "./canvas-utils";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,cAAc,CAAC;KACnC;IAED,UAAU,GAAG,CAAC;QACZ,UAAU,iBAAiB;YACzB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,CACxC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EACpC,cAAc,CACf,CAAC;SACH;KACF;CACF;AAGD,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,cAAc,EAAE,CAAC;AAGrD,YAAY,EACV,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,aAAa,EACb,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import FalkorDBCanvas from "./canvas";
|
|
2
|
+
// Main canvas class
|
|
3
|
+
export { FalkorDBCanvas as default, FalkorDBCanvas };
|
|
4
|
+
// Utils
|
|
5
|
+
export { dataToGraphData, graphDataToData, getNodeDisplayText, getNodeDisplayKey, wrapTextForCircularNode, } from "./canvas-utils";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,UAAU,CAAC;AAkBtC,oBAAoB;AACpB,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,cAAc,EAAE,CAAC;AAgBrD,QAAQ;AACR,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@falkordb/canvas",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "A standalone web component for visualizing FalkorDB graphs using force-directed layouts",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -25,6 +25,14 @@
|
|
|
25
25
|
"clean": "rm -rf dist",
|
|
26
26
|
"lint": "eslint ."
|
|
27
27
|
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/FalkorDB/falkordb-canvas"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/FalkorDB/falkordb-canvas/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/FalkorDB/falkordb-canvas",
|
|
28
36
|
"keywords": [
|
|
29
37
|
"falkordb",
|
|
30
38
|
"graph",
|
|
@@ -36,12 +44,12 @@
|
|
|
36
44
|
"author": "FalkorDB",
|
|
37
45
|
"license": "MIT",
|
|
38
46
|
"dependencies": {
|
|
39
|
-
"@types/react": "^19.2.7",
|
|
40
47
|
"d3": "^7.9.0",
|
|
41
48
|
"force-graph": "^1.44.4",
|
|
42
49
|
"react": "^19.2.3"
|
|
43
50
|
},
|
|
44
51
|
"devDependencies": {
|
|
52
|
+
"@types/react": "^19.2.7",
|
|
45
53
|
"@types/d3": "^7.4.3",
|
|
46
54
|
"@typescript-eslint/eslint-plugin": "^8.18.2",
|
|
47
55
|
"@typescript-eslint/parser": "^8.18.2",
|
|
@@ -13,6 +13,8 @@ export interface ForceGraphConfig {
|
|
|
13
13
|
onNodeHover?: (node: GraphNode | null) => void;
|
|
14
14
|
onLinkHover?: (link: GraphLink | null) => void;
|
|
15
15
|
onBackgroundClick?: (event: MouseEvent) => void;
|
|
16
|
+
onBackgroundRightClick?: (event: MouseEvent) => void;
|
|
17
|
+
onZoom?: (transform: Transform) => void;
|
|
16
18
|
onEngineStop?: () => void;
|
|
17
19
|
onLoadingChange?: (loading: boolean) => void;
|
|
18
20
|
cooldownTicks?: number | undefined;
|
|
@@ -85,6 +87,8 @@ export type ViewportState = {
|
|
|
85
87
|
centerY: number;
|
|
86
88
|
} | undefined;
|
|
87
89
|
|
|
90
|
+
export type Transform = { k: number, x: number, y: number };
|
|
91
|
+
|
|
88
92
|
// Force graph instance type from force-graph library
|
|
89
93
|
// The instance is created by calling ForceGraph as a function with a container element
|
|
90
94
|
export type ForceGraphInstance = import("force-graph").default<GraphNode, GraphLink> | undefined;
|
|
@@ -10,13 +10,14 @@ import {
|
|
|
10
10
|
GraphNode,
|
|
11
11
|
ForceGraphConfig,
|
|
12
12
|
ViewportState,
|
|
13
|
-
|
|
13
|
+
Transform,
|
|
14
|
+
} from "./canvas-types.js";
|
|
14
15
|
import {
|
|
15
16
|
dataToGraphData,
|
|
16
17
|
getNodeDisplayText,
|
|
17
18
|
graphDataToData,
|
|
18
19
|
wrapTextForCircularNode,
|
|
19
|
-
} from "./
|
|
20
|
+
} from "./canvas-utils.js";
|
|
20
21
|
|
|
21
22
|
const NODE_SIZE = 6;
|
|
22
23
|
const PADDING = 2;
|
|
@@ -100,8 +101,8 @@ class FalkorDBCanvas extends HTMLElement {
|
|
|
100
101
|
Object.assign(this.config, config);
|
|
101
102
|
|
|
102
103
|
// Update event handlers if they were provided
|
|
103
|
-
if (config.onNodeClick || config.onNodeRightClick || config.onLinkRightClick ||
|
|
104
|
-
config.onNodeHover || config.onLinkHover || config.onBackgroundClick ||
|
|
104
|
+
if (config.onNodeClick || config.onLinkClick || config.onNodeRightClick || config.onLinkRightClick ||
|
|
105
|
+
config.onNodeHover || config.onLinkHover || config.onBackgroundClick || config.onBackgroundRightClick || config.onZoom ||
|
|
105
106
|
config.onEngineStop || config.isNodeSelected || config.isLinkSelected) {
|
|
106
107
|
this.updateEventHandlers();
|
|
107
108
|
}
|
|
@@ -451,6 +452,16 @@ class FalkorDBCanvas extends HTMLElement {
|
|
|
451
452
|
this.config.onBackgroundClick(event);
|
|
452
453
|
}
|
|
453
454
|
})
|
|
455
|
+
.onBackgroundRightClick((event: MouseEvent) => {
|
|
456
|
+
if (this.config.onBackgroundRightClick) {
|
|
457
|
+
this.config.onBackgroundRightClick(event);
|
|
458
|
+
}
|
|
459
|
+
})
|
|
460
|
+
.onZoom((transform: Transform) => {
|
|
461
|
+
if (this.config.onZoom) {
|
|
462
|
+
this.config.onZoom(transform);
|
|
463
|
+
}
|
|
464
|
+
})
|
|
454
465
|
.onEngineStop(() => {
|
|
455
466
|
this.handleEngineStop();
|
|
456
467
|
if (this.config.onEngineStop) {
|
|
@@ -763,6 +774,16 @@ class FalkorDBCanvas extends HTMLElement {
|
|
|
763
774
|
this.config.onBackgroundClick(event);
|
|
764
775
|
}
|
|
765
776
|
})
|
|
777
|
+
.onBackgroundRightClick((event: MouseEvent) => {
|
|
778
|
+
if (this.config.onBackgroundRightClick) {
|
|
779
|
+
this.config.onBackgroundRightClick(event);
|
|
780
|
+
}
|
|
781
|
+
})
|
|
782
|
+
.onZoom((transform: Transform) => {
|
|
783
|
+
if (this.config.onZoom) {
|
|
784
|
+
this.config.onZoom(transform);
|
|
785
|
+
}
|
|
786
|
+
})
|
|
766
787
|
.onEngineStop(() => {
|
|
767
788
|
this.handleEngineStop();
|
|
768
789
|
if (this.config.onEngineStop) {
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import FalkorDBCanvas from "./
|
|
1
|
+
import FalkorDBCanvas from "./canvas";
|
|
2
2
|
import type React from "react";
|
|
3
3
|
|
|
4
4
|
declare global {
|
|
@@ -31,7 +31,7 @@ export type {
|
|
|
31
31
|
TextPriority,
|
|
32
32
|
ViewportState,
|
|
33
33
|
ForceGraphInstance,
|
|
34
|
-
} from "./
|
|
34
|
+
} from "./canvas-types";
|
|
35
35
|
|
|
36
36
|
// Utils
|
|
37
37
|
export {
|
|
@@ -40,4 +40,4 @@ export {
|
|
|
40
40
|
getNodeDisplayText,
|
|
41
41
|
getNodeDisplayKey,
|
|
42
42
|
wrapTextForCircularNode,
|
|
43
|
-
} from "./
|
|
43
|
+
} from "./canvas-utils";
|