@akiojin/gwt 4.2.0 → 4.3.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.
Files changed (119) hide show
  1. package/dist/claude.d.ts +2 -0
  2. package/dist/claude.d.ts.map +1 -1
  3. package/dist/claude.js +11 -1
  4. package/dist/claude.js.map +1 -1
  5. package/dist/cli/ui/components/App.d.ts.map +1 -1
  6. package/dist/cli/ui/components/App.js +68 -68
  7. package/dist/cli/ui/components/App.js.map +1 -1
  8. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  9. package/dist/cli/ui/components/screens/BranchListScreen.js +6 -1
  10. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  11. package/dist/client/assets/index-ChHC-Puh.css +1 -0
  12. package/dist/client/assets/index-PqK9jkug.js +78 -0
  13. package/dist/client/index.html +2 -2
  14. package/dist/config/builtin-tools.d.ts.map +1 -1
  15. package/dist/config/builtin-tools.js +3 -0
  16. package/dist/config/builtin-tools.js.map +1 -1
  17. package/dist/config/tools.d.ts.map +1 -1
  18. package/dist/config/tools.js +10 -1
  19. package/dist/config/tools.js.map +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/launcher.d.ts.map +1 -1
  24. package/dist/launcher.js +15 -0
  25. package/dist/launcher.js.map +1 -1
  26. package/dist/services/aiToolResolver.d.ts.map +1 -1
  27. package/dist/services/aiToolResolver.js +55 -8
  28. package/dist/services/aiToolResolver.js.map +1 -1
  29. package/dist/services/customToolResolver.d.ts.map +1 -1
  30. package/dist/services/customToolResolver.js +22 -17
  31. package/dist/services/customToolResolver.js.map +1 -1
  32. package/dist/utils/webui.js +1 -1
  33. package/dist/web/client/src/components/BranchGraph.d.ts +5 -0
  34. package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
  35. package/dist/web/client/src/components/BranchGraph.js +35 -108
  36. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  37. package/dist/web/client/src/components/graph/BranchDetailPanel.d.ts +15 -0
  38. package/dist/web/client/src/components/graph/BranchDetailPanel.d.ts.map +1 -0
  39. package/dist/web/client/src/components/graph/BranchDetailPanel.js +57 -0
  40. package/dist/web/client/src/components/graph/BranchDetailPanel.js.map +1 -0
  41. package/dist/web/client/src/components/graph/BranchNode.d.ts +13 -0
  42. package/dist/web/client/src/components/graph/BranchNode.d.ts.map +1 -0
  43. package/dist/web/client/src/components/graph/BranchNode.js +103 -0
  44. package/dist/web/client/src/components/graph/BranchNode.js.map +1 -0
  45. package/dist/web/client/src/components/graph/ClusterNode.d.ts +13 -0
  46. package/dist/web/client/src/components/graph/ClusterNode.d.ts.map +1 -0
  47. package/dist/web/client/src/components/graph/ClusterNode.js +109 -0
  48. package/dist/web/client/src/components/graph/ClusterNode.js.map +1 -0
  49. package/dist/web/client/src/components/graph/SynapticCanvas.d.ts +17 -0
  50. package/dist/web/client/src/components/graph/SynapticCanvas.d.ts.map +1 -0
  51. package/dist/web/client/src/components/graph/SynapticCanvas.js +94 -0
  52. package/dist/web/client/src/components/graph/SynapticCanvas.js.map +1 -0
  53. package/dist/web/client/src/components/graph/SynapticEdge.d.ts +13 -0
  54. package/dist/web/client/src/components/graph/SynapticEdge.d.ts.map +1 -0
  55. package/dist/web/client/src/components/graph/SynapticEdge.js +113 -0
  56. package/dist/web/client/src/components/graph/SynapticEdge.js.map +1 -0
  57. package/dist/web/client/src/components/graph/graphUtils.d.ts +67 -0
  58. package/dist/web/client/src/components/graph/graphUtils.d.ts.map +1 -0
  59. package/dist/web/client/src/components/graph/graphUtils.js +175 -0
  60. package/dist/web/client/src/components/graph/graphUtils.js.map +1 -0
  61. package/dist/web/client/src/components/graph/index.d.ts +10 -0
  62. package/dist/web/client/src/components/graph/index.d.ts.map +1 -0
  63. package/dist/web/client/src/components/graph/index.js +10 -0
  64. package/dist/web/client/src/components/graph/index.js.map +1 -0
  65. package/dist/web/client/src/lib/websocket.d.ts.map +1 -1
  66. package/dist/web/client/src/lib/websocket.js +2 -1
  67. package/dist/web/client/src/lib/websocket.js.map +1 -1
  68. package/dist/web/client/vite.config.js +1 -1
  69. package/dist/web/server/env/importer.d.ts.map +1 -1
  70. package/dist/web/server/env/importer.js +4 -0
  71. package/dist/web/server/env/importer.js.map +1 -1
  72. package/dist/web/server/index.d.ts.map +1 -1
  73. package/dist/web/server/index.js +9 -0
  74. package/dist/web/server/index.js.map +1 -1
  75. package/dist/web/server/pty/manager.d.ts.map +1 -1
  76. package/dist/web/server/pty/manager.js +24 -1
  77. package/dist/web/server/pty/manager.js.map +1 -1
  78. package/dist/web/server/routes/sessions.d.ts.map +1 -1
  79. package/dist/web/server/routes/sessions.js +7 -0
  80. package/dist/web/server/routes/sessions.js.map +1 -1
  81. package/dist/web/server/tray.d.ts +1 -1
  82. package/dist/web/server/tray.d.ts.map +1 -1
  83. package/dist/web/server/tray.js +52 -34
  84. package/dist/web/server/tray.js.map +1 -1
  85. package/dist/web/server/websocket/handler.d.ts.map +1 -1
  86. package/dist/web/server/websocket/handler.js +4 -0
  87. package/dist/web/server/websocket/handler.js.map +1 -1
  88. package/package.json +5 -2
  89. package/src/claude.ts +13 -1
  90. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +104 -0
  91. package/src/cli/ui/components/App.tsx +91 -81
  92. package/src/cli/ui/components/screens/BranchListScreen.tsx +6 -1
  93. package/src/cli/ui/types.ts +1 -1
  94. package/src/config/builtin-tools.ts +3 -0
  95. package/src/config/tools.ts +24 -1
  96. package/src/index.ts +3 -1
  97. package/src/launcher.ts +26 -0
  98. package/src/services/aiToolResolver.ts +75 -9
  99. package/src/services/customToolResolver.ts +32 -17
  100. package/src/utils/webui.ts +1 -1
  101. package/src/web/client/src/components/BranchGraph.tsx +51 -208
  102. package/src/web/client/src/components/graph/BranchDetailPanel.tsx +152 -0
  103. package/src/web/client/src/components/graph/BranchNode.tsx +200 -0
  104. package/src/web/client/src/components/graph/ClusterNode.tsx +211 -0
  105. package/src/web/client/src/components/graph/SynapticCanvas.tsx +171 -0
  106. package/src/web/client/src/components/graph/SynapticEdge.tsx +311 -0
  107. package/src/web/client/src/components/graph/graphUtils.ts +265 -0
  108. package/src/web/client/src/components/graph/index.ts +10 -0
  109. package/src/web/client/src/index.css +314 -29
  110. package/src/web/client/src/lib/websocket.ts +2 -1
  111. package/src/web/client/vite.config.ts +1 -1
  112. package/src/web/server/env/importer.ts +5 -0
  113. package/src/web/server/index.ts +10 -0
  114. package/src/web/server/pty/manager.ts +43 -1
  115. package/src/web/server/routes/sessions.ts +15 -0
  116. package/src/web/server/tray.ts +62 -46
  117. package/src/web/server/websocket/handler.ts +13 -0
  118. package/dist/client/assets/index-DsDNCy5f.css +0 -1
  119. package/dist/client/assets/index-v8smkNOL.js +0 -72
@@ -0,0 +1,171 @@
1
+ /**
2
+ * シナプティックキャンバス
3
+ *
4
+ * React Flowベースのブランチグラフ表示コンテナ
5
+ * パン/ズーム/ミニマップを提供
6
+ */
7
+
8
+ import React, { useCallback, useEffect, useState } from "react";
9
+ import {
10
+ ReactFlow,
11
+ Background,
12
+ Controls,
13
+ MiniMap,
14
+ useNodesState,
15
+ useEdgesState,
16
+ type NodeMouseHandler,
17
+ BackgroundVariant,
18
+ } from "@xyflow/react";
19
+ import "@xyflow/react/dist/style.css";
20
+
21
+ import type { Branch } from "../../../../../types/api.js";
22
+ import { BranchNode } from "./BranchNode";
23
+ import { ClusterNode } from "./ClusterNode";
24
+ import { SynapticEdge } from "./SynapticEdge";
25
+ import { branchesToGraph, type GraphNode, type GraphEdge } from "./graphUtils";
26
+
27
+ /** カスタムノードタイプ */
28
+ const nodeTypes = {
29
+ branch: BranchNode,
30
+ cluster: ClusterNode,
31
+ };
32
+
33
+ /** カスタムエッジタイプ */
34
+ const edgeTypes = {
35
+ synaptic: SynapticEdge,
36
+ };
37
+
38
+ interface SynapticCanvasProps {
39
+ branches: Branch[];
40
+ onNodeClick?: (branch: Branch | null) => void;
41
+ className?: string;
42
+ }
43
+
44
+ export function SynapticCanvas({
45
+ branches,
46
+ onNodeClick,
47
+ className,
48
+ }: SynapticCanvasProps) {
49
+ const [nodes, setNodes, onNodesChange] = useNodesState<GraphNode>([]);
50
+ const [edges, setEdges, onEdgesChange] = useEdgesState<GraphEdge>([]);
51
+ const [expandedClusters, setExpandedClusters] = useState<Set<string>>(
52
+ new Set(),
53
+ );
54
+ const [isLayouting, setIsLayouting] = useState(false);
55
+
56
+ // レイアウト計算
57
+ useEffect(() => {
58
+ if (branches.length === 0) return;
59
+
60
+ setIsLayouting(true);
61
+
62
+ // キャンバスサイズ(仮)
63
+ const width = 800;
64
+ const height = 600;
65
+
66
+ branchesToGraph(branches, expandedClusters, width, height)
67
+ .then(({ nodes: newNodes, edges: newEdges }) => {
68
+ setNodes(newNodes);
69
+ setEdges(newEdges);
70
+ })
71
+ .catch((error) => {
72
+ console.error("Failed to calculate graph layout:", error);
73
+ })
74
+ .finally(() => {
75
+ setIsLayouting(false);
76
+ });
77
+ }, [branches, expandedClusters, setNodes, setEdges]);
78
+
79
+ // ノードクリックハンドラ
80
+ const handleNodeClick: NodeMouseHandler<GraphNode> = useCallback(
81
+ (event, node) => {
82
+ if (node.data.isCluster) {
83
+ // クラスタノード: 展開/折りたたみ
84
+ setExpandedClusters((prev) => {
85
+ const next = new Set(prev);
86
+ if (next.has(node.id)) {
87
+ next.delete(node.id);
88
+ } else {
89
+ next.add(node.id);
90
+ }
91
+ return next;
92
+ });
93
+ } else {
94
+ // ブランチノード: 詳細パネル表示
95
+ onNodeClick?.(node.data.branch ?? null);
96
+ }
97
+ },
98
+ [onNodeClick],
99
+ );
100
+
101
+ // ミニマップのノードカラー
102
+ const minimapNodeColor = useCallback((node: GraphNode) => {
103
+ if (node.data.isCluster) {
104
+ return "hsl(var(--muted-foreground))";
105
+ }
106
+ if (node.data.branch?.worktreePath) {
107
+ return "hsl(var(--success))";
108
+ }
109
+ if (node.data.branch?.type === "local") {
110
+ return "hsl(var(--local))";
111
+ }
112
+ return "hsl(var(--remote))";
113
+ }, []);
114
+
115
+ return (
116
+ <div className={className} style={{ width: "100%", height: "100%" }}>
117
+ <ReactFlow
118
+ nodes={nodes}
119
+ edges={edges}
120
+ onNodesChange={onNodesChange}
121
+ onEdgesChange={onEdgesChange}
122
+ onNodeClick={handleNodeClick}
123
+ nodeTypes={nodeTypes}
124
+ edgeTypes={edgeTypes}
125
+ fitView
126
+ fitViewOptions={{
127
+ padding: 0.2,
128
+ maxZoom: 1.5,
129
+ }}
130
+ minZoom={0.1}
131
+ maxZoom={2}
132
+ attributionPosition="bottom-left"
133
+ proOptions={{ hideAttribution: true }}
134
+ className="bg-gradient-to-br from-background via-background to-muted/20"
135
+ >
136
+ {/* 背景グリッド */}
137
+ <Background
138
+ variant={BackgroundVariant.Dots}
139
+ gap={20}
140
+ size={1}
141
+ color="hsl(var(--muted-foreground) / 0.15)"
142
+ />
143
+
144
+ {/* コントロール */}
145
+ <Controls
146
+ showInteractive={false}
147
+ className="!bg-card !border !border-border !shadow-md"
148
+ />
149
+
150
+ {/* ミニマップ */}
151
+ <MiniMap
152
+ nodeColor={minimapNodeColor}
153
+ maskColor="hsl(var(--background) / 0.8)"
154
+ className="!bg-card !border !border-border !shadow-md"
155
+ />
156
+ </ReactFlow>
157
+
158
+ {/* ローディングオーバーレイ */}
159
+ {isLayouting && (
160
+ <div className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm">
161
+ <div className="flex items-center gap-2 rounded-lg bg-card px-4 py-2 shadow-lg">
162
+ <div className="h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" />
163
+ <span className="text-sm text-muted-foreground">
164
+ Calculating layout...
165
+ </span>
166
+ </div>
167
+ </div>
168
+ )}
169
+ </div>
170
+ );
171
+ }
@@ -0,0 +1,311 @@
1
+ /**
2
+ * シナプスエッジコンポーネント
3
+ *
4
+ * 神経細胞の軸索(アクソン)をイメージした脈動するエッジ
5
+ * 神経伝達物質の放出と伝播を表現するアニメーション
6
+ */
7
+
8
+ import React, { memo, useMemo } from "react";
9
+ import {
10
+ BaseEdge,
11
+ EdgeLabelRenderer,
12
+ getBezierPath,
13
+ type EdgeProps,
14
+ } from "@xyflow/react";
15
+ import type { GraphEdge } from "./graphUtils";
16
+
17
+ type SynapticEdgeProps = EdgeProps<GraphEdge>;
18
+
19
+ export const SynapticEdge = memo(function SynapticEdge({
20
+ id,
21
+ sourceX,
22
+ sourceY,
23
+ targetX,
24
+ targetY,
25
+ sourcePosition,
26
+ targetPosition,
27
+ style = {},
28
+ markerEnd,
29
+ }: SynapticEdgeProps) {
30
+ const [edgePath, labelX, labelY] = getBezierPath({
31
+ sourceX,
32
+ sourceY,
33
+ sourcePosition,
34
+ targetX,
35
+ targetY,
36
+ targetPosition,
37
+ curvature: 0.25,
38
+ });
39
+
40
+ // エッジの長さに基づいてパーティクル数を調整
41
+ const edgeLength = useMemo(() => {
42
+ const dx = targetX - sourceX;
43
+ const dy = targetY - sourceY;
44
+ return Math.sqrt(dx * dx + dy * dy);
45
+ }, [sourceX, sourceY, targetX, targetY]);
46
+
47
+ const particleCount = Math.max(2, Math.min(4, Math.floor(edgeLength / 100)));
48
+
49
+ return (
50
+ <>
51
+ {/* 外側グロー - 深い影 */}
52
+ <BaseEdge
53
+ id={`${id}-outer-glow`}
54
+ path={edgePath}
55
+ style={{
56
+ ...style,
57
+ strokeWidth: 12,
58
+ stroke: "hsl(185 100% 65% / 0.08)",
59
+ filter: "blur(8px)",
60
+ }}
61
+ />
62
+
63
+ {/* 中間グロー */}
64
+ <BaseEdge
65
+ id={`${id}-mid-glow`}
66
+ path={edgePath}
67
+ style={{
68
+ ...style,
69
+ strokeWidth: 6,
70
+ stroke: "hsl(185 100% 65% / 0.15)",
71
+ filter: "blur(4px)",
72
+ }}
73
+ />
74
+
75
+ {/* メインエッジ - 軸索 */}
76
+ <BaseEdge
77
+ id={id}
78
+ path={edgePath}
79
+ {...(markerEnd ? { markerEnd } : {})}
80
+ style={{
81
+ ...style,
82
+ strokeWidth: 2,
83
+ stroke: "hsl(185 100% 65% / 0.5)",
84
+ strokeLinecap: "round",
85
+ }}
86
+ />
87
+
88
+ {/* 内側の明るいコア */}
89
+ <BaseEdge
90
+ id={`${id}-core`}
91
+ path={edgePath}
92
+ style={{
93
+ ...style,
94
+ strokeWidth: 1,
95
+ stroke: "hsl(185 100% 75% / 0.6)",
96
+ strokeLinecap: "round",
97
+ }}
98
+ />
99
+
100
+ {/* SVGアニメーション定義 */}
101
+ <EdgeLabelRenderer>
102
+ <svg
103
+ style={{
104
+ position: "absolute",
105
+ left: 0,
106
+ top: 0,
107
+ width: "100%",
108
+ height: "100%",
109
+ pointerEvents: "none",
110
+ overflow: "visible",
111
+ }}
112
+ >
113
+ <defs>
114
+ {/* 神経伝達物質パルスグラデーション */}
115
+ <linearGradient
116
+ id={`vesicle-pulse-${id}`}
117
+ x1="0%"
118
+ y1="0%"
119
+ x2="100%"
120
+ y2="0%"
121
+ >
122
+ <stop offset="0%" stopColor="transparent">
123
+ <animate
124
+ attributeName="offset"
125
+ values="-0.3;1"
126
+ dur="2.5s"
127
+ repeatCount="indefinite"
128
+ />
129
+ </stop>
130
+ <stop offset="5%" stopColor="hsl(185 100% 70% / 0.3)">
131
+ <animate
132
+ attributeName="offset"
133
+ values="-0.25;1.05"
134
+ dur="2.5s"
135
+ repeatCount="indefinite"
136
+ />
137
+ </stop>
138
+ <stop offset="10%" stopColor="hsl(185 100% 80%)">
139
+ <animate
140
+ attributeName="offset"
141
+ values="-0.2;1.1"
142
+ dur="2.5s"
143
+ repeatCount="indefinite"
144
+ />
145
+ </stop>
146
+ <stop offset="15%" stopColor="hsl(185 100% 70% / 0.3)">
147
+ <animate
148
+ attributeName="offset"
149
+ values="-0.15;1.15"
150
+ dur="2.5s"
151
+ repeatCount="indefinite"
152
+ />
153
+ </stop>
154
+ <stop offset="20%" stopColor="transparent">
155
+ <animate
156
+ attributeName="offset"
157
+ values="-0.1;1.2"
158
+ dur="2.5s"
159
+ repeatCount="indefinite"
160
+ />
161
+ </stop>
162
+ </linearGradient>
163
+
164
+ {/* 二次パルス(シナプス間隙) */}
165
+ <linearGradient
166
+ id={`synapse-pulse-${id}`}
167
+ x1="0%"
168
+ y1="0%"
169
+ x2="100%"
170
+ y2="0%"
171
+ >
172
+ <stop offset="0%" stopColor="transparent">
173
+ <animate
174
+ attributeName="offset"
175
+ values="-0.4;1"
176
+ dur="3s"
177
+ begin="0.8s"
178
+ repeatCount="indefinite"
179
+ />
180
+ </stop>
181
+ <stop offset="8%" stopColor="hsl(310 85% 65% / 0.6)">
182
+ <animate
183
+ attributeName="offset"
184
+ values="-0.32;1.08"
185
+ dur="3s"
186
+ begin="0.8s"
187
+ repeatCount="indefinite"
188
+ />
189
+ </stop>
190
+ <stop offset="16%" stopColor="transparent">
191
+ <animate
192
+ attributeName="offset"
193
+ values="-0.24;1.16"
194
+ dur="3s"
195
+ begin="0.8s"
196
+ repeatCount="indefinite"
197
+ />
198
+ </stop>
199
+ </linearGradient>
200
+
201
+ {/* グロー効果フィルター */}
202
+ <filter
203
+ id={`glow-${id}`}
204
+ x="-50%"
205
+ y="-50%"
206
+ width="200%"
207
+ height="200%"
208
+ >
209
+ <feGaussianBlur stdDeviation="2" result="coloredBlur" />
210
+ <feMerge>
211
+ <feMergeNode in="coloredBlur" />
212
+ <feMergeNode in="SourceGraphic" />
213
+ </feMerge>
214
+ </filter>
215
+ </defs>
216
+
217
+ {/* メインパルス */}
218
+ <path
219
+ d={edgePath}
220
+ fill="none"
221
+ stroke={`url(#vesicle-pulse-${id})`}
222
+ strokeWidth={4}
223
+ strokeLinecap="round"
224
+ filter={`url(#glow-${id})`}
225
+ style={{ mixBlendMode: "screen" }}
226
+ />
227
+
228
+ {/* セカンダリパルス(マゼンタ) */}
229
+ <path
230
+ d={edgePath}
231
+ fill="none"
232
+ stroke={`url(#synapse-pulse-${id})`}
233
+ strokeWidth={3}
234
+ strokeLinecap="round"
235
+ style={{ mixBlendMode: "screen" }}
236
+ />
237
+ </svg>
238
+ </EdgeLabelRenderer>
239
+
240
+ {/* 流れるパーティクル(神経伝達物質) - SVG animateMotion使用 */}
241
+ <EdgeLabelRenderer>
242
+ <svg
243
+ style={{
244
+ position: "absolute",
245
+ left: 0,
246
+ top: 0,
247
+ width: "100%",
248
+ height: "100%",
249
+ pointerEvents: "none",
250
+ overflow: "visible",
251
+ }}
252
+ >
253
+ {Array.from({ length: particleCount }).map((_, i) => (
254
+ <circle
255
+ key={i}
256
+ r={3 - i * 0.3}
257
+ fill="hsl(185 100% 80%)"
258
+ opacity={0}
259
+ >
260
+ <animateMotion
261
+ dur={`${2 + i * 0.3}s`}
262
+ repeatCount="indefinite"
263
+ path={edgePath}
264
+ begin={`${i * 0.6}s`}
265
+ />
266
+ <animate
267
+ attributeName="opacity"
268
+ values="0;1;1;0"
269
+ keyTimes="0;0.1;0.9;1"
270
+ dur={`${2 + i * 0.3}s`}
271
+ repeatCount="indefinite"
272
+ begin={`${i * 0.6}s`}
273
+ />
274
+ </circle>
275
+ ))}
276
+ </svg>
277
+ </EdgeLabelRenderer>
278
+
279
+ {/* シナプス接合点グロー */}
280
+ <EdgeLabelRenderer>
281
+ <div
282
+ className="absolute"
283
+ style={{
284
+ transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
285
+ }}
286
+ >
287
+ {/* 外側の拡散グロー */}
288
+ <div
289
+ className="absolute -inset-3 rounded-full opacity-30"
290
+ style={{
291
+ background:
292
+ "radial-gradient(circle, hsl(185 100% 65%) 0%, transparent 70%)",
293
+ animation: "synapse-spark 3s ease-in-out infinite",
294
+ }}
295
+ />
296
+ {/* 中心核 */}
297
+ <div
298
+ className="h-2 w-2 rounded-full"
299
+ style={{
300
+ background:
301
+ "radial-gradient(circle at 30% 30%, hsl(185 100% 80%), hsl(185 100% 60%))",
302
+ boxShadow:
303
+ "0 0 10px hsl(185 100% 65% / 0.8), 0 0 20px hsl(185 100% 65% / 0.4)",
304
+ animation: "vesicle-release 2s ease-in-out infinite",
305
+ }}
306
+ />
307
+ </div>
308
+ </EdgeLabelRenderer>
309
+ </>
310
+ );
311
+ });