@tldiagram/core-ui 1.92.0 → 1.94.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.d.ts +13 -1
- package/dist/components/ElementNode.d.ts +14 -1
- package/dist/components/ZUI/ZUICanvas.d.ts +1 -0
- package/dist/config/runtime-vscode.d.ts +1 -0
- package/dist/config/runtime.d.ts +1 -0
- package/dist/index.js +10875 -9550
- package/dist/pages/InfiniteZoom.d.ts +5 -2
- package/dist/pages/ViewEditor/hooks/useCanvasInteractions.d.ts +10 -3
- package/dist/pages/ViewEditor/hooks/useCanvasInteractions.test.d.ts +1 -0
- package/dist/pages/ViewEditor/hooks/useViewData.d.ts +27 -24
- package/dist/pages/ViewsGrid.d.ts +9 -1
- package/dist/shims/empty-node-module.d.ts +2 -0
- package/dist/store/useStore.d.ts +80 -0
- package/dist/store/useStore.test.d.ts +1 -0
- package/package.json +10 -7
- package/src/api/client.ts +39 -1
- package/src/components/ElementNode.tsx +21 -59
- package/src/components/ElementPanel.tsx +2 -3
- package/src/components/LayoutSection.tsx +95 -104
- package/src/components/ViewGridNode.tsx +1 -4
- package/src/components/ZUI/ZUICanvas.tsx +138 -1
- package/src/components/ZUI/renderer.ts +166 -66
- package/src/components/ZUI/useZUIInteraction.ts +235 -81
- package/src/config/runtime-vscode.ts +6 -0
- package/src/config/runtime.ts +4 -0
- package/src/main.tsx +26 -14
- package/src/pages/InfiniteZoom.tsx +14 -5
- package/src/pages/ViewEditor/context.tsx +14 -3
- package/src/pages/ViewEditor/hooks/useCanvasInteractions.test.ts +30 -0
- package/src/pages/ViewEditor/hooks/useCanvasInteractions.ts +294 -146
- package/src/pages/ViewEditor/hooks/useViewData.ts +459 -256
- package/src/pages/ViewEditor/index.tsx +67 -70
- package/src/pages/Views.tsx +552 -83
- package/src/pages/ViewsGrid.tsx +26 -337
- package/src/shims/empty-node-module.ts +1 -0
- package/src/store/useStore.test.ts +285 -0
- package/src/store/useStore.ts +327 -0
|
@@ -11,7 +11,6 @@ import ReactFlow, {
|
|
|
11
11
|
PanOnScrollMode,
|
|
12
12
|
ReactFlowProvider,
|
|
13
13
|
useReactFlow,
|
|
14
|
-
applyNodeChanges,
|
|
15
14
|
} from 'reactflow'
|
|
16
15
|
import type { Edge as RFEdge, EdgeMarker as RFEdgeMarker, Node as RFNode, NodeChange } from 'reactflow'
|
|
17
16
|
import 'reactflow/dist/style.css'
|
|
@@ -74,8 +73,8 @@ import type { ExtensionToWebviewMessage } from '../../types/vscode-messages'
|
|
|
74
73
|
import { ViewEditorContext } from './context'
|
|
75
74
|
import { useViewData } from './hooks/useViewData'
|
|
76
75
|
import { useDrawingEngine } from './hooks/useDrawingEngine'
|
|
77
|
-
import { useCanvasInteractions } from './hooks/useCanvasInteractions'
|
|
78
|
-
import { sanitizeExportFilename, triggerDownload } from './utils'
|
|
76
|
+
import { applyNodeChangesWithStructuralSharing, useCanvasInteractions } from './hooks/useCanvasInteractions'
|
|
77
|
+
import { connectorToConnector, findClosestHandles, sanitizeExportFilename, triggerDownload } from './utils'
|
|
79
78
|
import { pickUnusedColor } from '../../components/ViewExplorer/utils'
|
|
80
79
|
|
|
81
80
|
import { EmptyCanvasState } from './components/EmptyCanvasState'
|
|
@@ -86,6 +85,7 @@ import { useCrossBranchContextSettings } from '../../crossBranch/settings'
|
|
|
86
85
|
import { removeConnectorGraphSnapshot, upsertConnectorGraphSnapshot, useWorkspaceGraphSnapshot } from '../../crossBranch/store'
|
|
87
86
|
import type { ProxyConnectorDetails } from '../../crossBranch/types'
|
|
88
87
|
import { useDemoRevealViewport, type ViewEditorDemoOptions } from '../../demo/viewEditor'
|
|
88
|
+
import { buildElementLibraryItems, useStore } from '../../store/useStore'
|
|
89
89
|
|
|
90
90
|
const nodeTypes = {
|
|
91
91
|
elementNode: ElementNode,
|
|
@@ -99,6 +99,7 @@ const VIEW_EDITOR_EMPTY_EXTENT_RATIO = 0.75
|
|
|
99
99
|
const VIEW_EDITOR_PAN_MARGIN_RATIO = 0.25
|
|
100
100
|
const VIEW_EDITOR_PAN_MARGIN_MIN = 180
|
|
101
101
|
const VIEW_EDITOR_PAN_MARGIN_MAX = 720
|
|
102
|
+
const SNAP_GRID: [number, number] = [30, 30]
|
|
102
103
|
|
|
103
104
|
function alphaColor(color: string, opacity: number): string {
|
|
104
105
|
if (opacity >= 1) return color
|
|
@@ -200,10 +201,8 @@ function ViewEditorInner({
|
|
|
200
201
|
const closeImportModalRef = useRef(importModal.onClose)
|
|
201
202
|
closeImportModalRef.current = importModal.onClose
|
|
202
203
|
|
|
203
|
-
|
|
204
204
|
const [selectedElement, setSelectedElement] = useState<WorkspaceElement | null>(null)
|
|
205
205
|
const [selectedEdge, setSelectedEdge] = useState<Connector | null>(null)
|
|
206
|
-
const [selectedEdgeId, setSelectedEdgeId] = useState<number | null>(null)
|
|
207
206
|
const [selectedProxyConnectorDetails, setSelectedProxyConnectorDetails] = useState<ProxyConnectorDetails | null>(null)
|
|
208
207
|
const [previewElement, setPreviewElement] = useState<PlacedElement | null>(null)
|
|
209
208
|
const [libraryOpen, setLibraryOpen] = useState(() => {
|
|
@@ -222,11 +221,34 @@ function ViewEditorInner({
|
|
|
222
221
|
const [extrasOpen, setExtrasOpen] = useState(false)
|
|
223
222
|
const [isImporting, setIsImporting] = useState(false)
|
|
224
223
|
const [isExporting, setIsExporting] = useState(false)
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
224
|
+
const setViewEditorUi = useStore((state) => state.setViewEditorUi)
|
|
225
|
+
const snapToGrid = useStore((state) => state.snapToGrid)
|
|
226
|
+
const setStoreSnapToGrid = useStore((state) => state.setSnapToGrid)
|
|
227
|
+
const upsertStoreConnector = useStore((state) => state.upsertConnector)
|
|
228
|
+
const removeStoreConnector = useStore((state) => state.removeConnector)
|
|
229
|
+
const refreshElementsRef = useRef<() => Promise<void>>(async () => {})
|
|
230
|
+
const setSnapToGrid = useCallback((snap: boolean) => {
|
|
231
|
+
setStoreSnapToGrid(snap)
|
|
232
|
+
if (typeof window !== 'undefined') localStorage.setItem('diag:snapToGrid', String(snap))
|
|
233
|
+
}, [setStoreSnapToGrid])
|
|
234
|
+
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
if (typeof window === 'undefined') return
|
|
237
|
+
setStoreSnapToGrid(localStorage.getItem('diag:snapToGrid') === 'true')
|
|
238
|
+
}, [setStoreSnapToGrid])
|
|
239
|
+
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
setViewEditorUi({
|
|
242
|
+
viewId,
|
|
243
|
+
canEdit,
|
|
244
|
+
isOwner,
|
|
245
|
+
isFreePlan,
|
|
246
|
+
snapToGrid,
|
|
247
|
+
selectedElement,
|
|
248
|
+
selectedConnector: selectedEdge,
|
|
249
|
+
})
|
|
250
|
+
}, [canEdit, isFreePlan, isOwner, selectedEdge, selectedElement, setViewEditorUi, snapToGrid, viewId])
|
|
251
|
+
|
|
230
252
|
useEffect(() => { localStorage.setItem('diag:snapToGrid', String(snapToGrid)) }, [snapToGrid])
|
|
231
253
|
const [, setHoveredZoom] = useState<{ elementId: number | null; type: 'in' | 'out' | null } | null>(null)
|
|
232
254
|
const hoveredZoomRef = useRef<{ elementId: number | null; type: 'in' | 'out' | null } | null>(null)
|
|
@@ -325,6 +347,7 @@ function ViewEditorInner({
|
|
|
325
347
|
|
|
326
348
|
// stableOnConnectTo is wired after canvasInteractions is declared
|
|
327
349
|
const stableOnConnectToRef = useRef<(targetElementId: number) => Promise<void>>(async () => { })
|
|
350
|
+
const stableOnInteractionStartRef = useRef<(elementId: number, options?: { sourceHandle?: string; clientX?: number; clientY?: number }) => void>(() => { })
|
|
328
351
|
const stableOnStartHandleReconnectRef = useRef<(args: { edgeId: string; endpoint: 'source' | 'target'; handleId: string; clientX: number; clientY: number }) => void>(() => { })
|
|
329
352
|
|
|
330
353
|
// ── Drawing engine ────────────────────────────────────────────────────────
|
|
@@ -347,7 +370,7 @@ function ViewEditorInner({
|
|
|
347
370
|
viewId,
|
|
348
371
|
interactionSourceId: interactionSourceIdRef.current,
|
|
349
372
|
clickConnectMode: null, // wired after canvasInteractions
|
|
350
|
-
|
|
373
|
+
selectedConnector: selectedEdge,
|
|
351
374
|
activeTags,
|
|
352
375
|
hiddenLayerTags,
|
|
353
376
|
hoveredLayerTags,
|
|
@@ -358,7 +381,6 @@ function ViewEditorInner({
|
|
|
358
381
|
stableOnNavigateToView: useCallback((id: number) => { stableOnNavigateToViewRef.current(id) }, []),
|
|
359
382
|
stableOnSelect: useCallback((obj: PlacedElement) => {
|
|
360
383
|
setSelectedEdge(null)
|
|
361
|
-
setSelectedEdgeId(null)
|
|
362
384
|
setSelectedProxyConnectorDetails(null)
|
|
363
385
|
closeProxyConnectorPanelRef.current()
|
|
364
386
|
closeConnectorPanelRef.current()
|
|
@@ -378,10 +400,9 @@ function ViewEditorInner({
|
|
|
378
400
|
openCodePreviewRef.current()
|
|
379
401
|
}
|
|
380
402
|
}, []),
|
|
381
|
-
stableOnInteractionStart: useCallback((elementId: number) => {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}, [canEdit]),
|
|
403
|
+
stableOnInteractionStart: useCallback((elementId: number, options?: { sourceHandle?: string; clientX?: number; clientY?: number }) => {
|
|
404
|
+
stableOnInteractionStartRef.current(elementId, options)
|
|
405
|
+
}, []),
|
|
385
406
|
stableOnConnectTo: useCallback(async (targetElementId: number) => {
|
|
386
407
|
await stableOnConnectToRef.current(targetElementId)
|
|
387
408
|
}, []),
|
|
@@ -409,6 +430,7 @@ function ViewEditorInner({
|
|
|
409
430
|
handleElementDeleted, handleElementPermanentlyDeleted, handleElementSaved,
|
|
410
431
|
setAllElements: _setAllElements,
|
|
411
432
|
} = data
|
|
433
|
+
refreshElementsRef.current = refreshElements
|
|
412
434
|
|
|
413
435
|
const tagCounts = useMemo(() => {
|
|
414
436
|
const counts: Record<string, number> = {}
|
|
@@ -476,27 +498,7 @@ function ViewEditorInner({
|
|
|
476
498
|
return unsub
|
|
477
499
|
}, [fitView, viewId, refreshElements])
|
|
478
500
|
|
|
479
|
-
const existingElements = useMemo(() =>
|
|
480
|
-
return viewElements.map(obj => ({
|
|
481
|
-
id: obj.element_id,
|
|
482
|
-
name: obj.name,
|
|
483
|
-
kind: obj.kind,
|
|
484
|
-
description: obj.description,
|
|
485
|
-
technology: obj.technology,
|
|
486
|
-
url: obj.url,
|
|
487
|
-
logo_url: obj.logo_url,
|
|
488
|
-
technology_connectors: obj.technology_connectors,
|
|
489
|
-
tags: obj.tags,
|
|
490
|
-
repo: obj.repo,
|
|
491
|
-
branch: obj.branch,
|
|
492
|
-
file_path: obj.file_path,
|
|
493
|
-
language: obj.language,
|
|
494
|
-
created_at: '',
|
|
495
|
-
updated_at: '',
|
|
496
|
-
has_view: false,
|
|
497
|
-
view_label: null,
|
|
498
|
-
} as WorkspaceElement))
|
|
499
|
-
}, [viewElements])
|
|
501
|
+
const existingElements = useMemo(() => buildElementLibraryItems(allElements, viewElements), [allElements, viewElements])
|
|
500
502
|
|
|
501
503
|
const availableTags = useMemo(() => {
|
|
502
504
|
const tags = new Set<string>()
|
|
@@ -528,7 +530,6 @@ function ViewEditorInner({
|
|
|
528
530
|
const match = viewElements.find((element) => element.element_id === requestedElementId)
|
|
529
531
|
if (!match) return
|
|
530
532
|
setSelectedEdge(null)
|
|
531
|
-
setSelectedEdgeId(null)
|
|
532
533
|
setSelectedProxyConnectorDetails(null)
|
|
533
534
|
closeConnectorPanelRef.current()
|
|
534
535
|
closeProxyConnectorPanelRef.current()
|
|
@@ -613,7 +614,7 @@ function ViewEditorInner({
|
|
|
613
614
|
const targetNode = rfNodesRef.current.find((n) => n.id === String(targetElementId))
|
|
614
615
|
let finalSourceHandle = 'right'; let finalTargetHandle = 'left'
|
|
615
616
|
if (sourceNode && targetNode) {
|
|
616
|
-
const h =
|
|
617
|
+
const h = findClosestHandles(sourceNode, targetNode)
|
|
617
618
|
finalSourceHandle = h.sourceHandle; finalTargetHandle = h.targetHandle
|
|
618
619
|
}
|
|
619
620
|
try {
|
|
@@ -621,9 +622,9 @@ function ViewEditorInner({
|
|
|
621
622
|
source_element_id: sourceId, target_element_id: targetElementId,
|
|
622
623
|
source_handle: finalSourceHandle, target_handle: finalTargetHandle, direction: 'forward',
|
|
623
624
|
})
|
|
624
|
-
const connector =
|
|
625
|
+
const connector = connectorToConnector(newConnector)
|
|
625
626
|
upsertConnectorGraphSnapshot(connector)
|
|
626
|
-
|
|
627
|
+
upsertStoreConnector(connector)
|
|
627
628
|
} catch { /* intentionally empty */ }
|
|
628
629
|
},
|
|
629
630
|
existingElementIds, linksMapRef, parentLinksMapRef,
|
|
@@ -631,33 +632,22 @@ function ViewEditorInner({
|
|
|
631
632
|
closeElementPanel: useCallback(() => closeElementPanelRef.current(), []),
|
|
632
633
|
openConnectorPanel: useCallback(() => openConnectorPanelRef.current(), []),
|
|
633
634
|
closeConnectorPanel: useCallback(() => closeConnectorPanelRef.current(), []),
|
|
634
|
-
selectedElement,
|
|
635
|
+
selectedElement, selectedConnector: selectedEdge, connectors,
|
|
635
636
|
layers,
|
|
636
637
|
setSelectedElement,
|
|
637
|
-
setSelectedEdge,
|
|
638
|
+
setSelectedEdge,
|
|
638
639
|
setSelectedProxyConnectorDetails,
|
|
639
640
|
openProxyConnectorPanel: useCallback(() => openProxyConnectorPanelRef.current(), []),
|
|
640
641
|
closeProxyConnectorPanel: useCallback(() => closeProxyConnectorPanelRef.current(), []),
|
|
641
642
|
handleElementDeleted, handleElementPermanentlyDeleted,
|
|
642
643
|
handleConnectorDeleted: useCallback((edgeId: number) => {
|
|
643
644
|
if (viewId != null) removeConnectorGraphSnapshot(viewId, edgeId)
|
|
644
|
-
|
|
645
|
-
|
|
645
|
+
removeStoreConnector(edgeId)
|
|
646
|
+
void refreshElementsRef.current()
|
|
647
|
+
}, [removeStoreConnector, viewId]),
|
|
646
648
|
handleUpdateTags,
|
|
647
649
|
drawingCanvasRef,
|
|
648
650
|
snapToGrid,
|
|
649
|
-
onMoveStateChange: useCallback((moving: boolean) => {
|
|
650
|
-
setLiveContextNodes((nds) => {
|
|
651
|
-
let changed = false
|
|
652
|
-
const nextNodes = nds.map((node) => {
|
|
653
|
-
const currentMoving = Boolean((node.data as { isCanvasMoving?: boolean }).isCanvasMoving)
|
|
654
|
-
if (currentMoving === moving) return node
|
|
655
|
-
changed = true
|
|
656
|
-
return { ...node, data: { ...node.data, isCanvasMoving: moving } }
|
|
657
|
-
})
|
|
658
|
-
return changed ? nextNodes : nds
|
|
659
|
-
})
|
|
660
|
-
}, []),
|
|
661
651
|
})
|
|
662
652
|
|
|
663
653
|
// Wire stable placeholders to the real implementations from canvas hook
|
|
@@ -667,8 +657,9 @@ function ViewEditorInner({
|
|
|
667
657
|
stableOnNavigateToViewRef.current = canvas.stableOnNavigateToView
|
|
668
658
|
stableOnRemoveElementRef.current = canvas.stableOnRemoveElement
|
|
669
659
|
stableOnConnectToRef.current = canvas.stableOnConnectTo
|
|
660
|
+
stableOnInteractionStartRef.current = canvas.stableOnInteractionStart
|
|
670
661
|
stableOnStartHandleReconnectRef.current = canvas.stableOnStartHandleReconnect
|
|
671
|
-
}, [canvas.stableOnZoomIn, canvas.stableOnZoomOut, canvas.stableOnNavigateToView, canvas.stableOnRemoveElement, canvas.stableOnConnectTo, canvas.stableOnStartHandleReconnect])
|
|
662
|
+
}, [canvas.stableOnZoomIn, canvas.stableOnZoomOut, canvas.stableOnNavigateToView, canvas.stableOnRemoveElement, canvas.stableOnConnectTo, canvas.stableOnInteractionStart, canvas.stableOnStartHandleReconnect])
|
|
672
663
|
const viewName = view?.name ?? null
|
|
673
664
|
|
|
674
665
|
const [expandedAncestorGroups, setExpandedAncestorGroups] = useState<Set<string>>(new Set())
|
|
@@ -691,7 +682,6 @@ function ViewEditorInner({
|
|
|
691
682
|
onSelectProxyDetails: useCallback((details: ProxyConnectorDetails) => {
|
|
692
683
|
setSelectedElement(null)
|
|
693
684
|
setSelectedEdge(null)
|
|
694
|
-
setSelectedEdgeId(null)
|
|
695
685
|
closeConnectorPanelRef.current()
|
|
696
686
|
closeElementPanelRef.current()
|
|
697
687
|
setSelectedProxyConnectorDetails(details)
|
|
@@ -826,7 +816,7 @@ function ViewEditorInner({
|
|
|
826
816
|
const ctxChanges = changes.filter((c) => 'id' in c && contextNodeIdsRef.current.has((c as { id: string }).id))
|
|
827
817
|
const mainChanges = changes.filter((c) => !('id' in c) || !contextNodeIdsRef.current.has((c as { id: string }).id))
|
|
828
818
|
if (ctxChanges.length > 0) {
|
|
829
|
-
setLiveContextNodes((nds) =>
|
|
819
|
+
setLiveContextNodes((nds) => applyNodeChangesWithStructuralSharing(ctxChanges, nds))
|
|
830
820
|
}
|
|
831
821
|
if (mainChanges.length > 0) {
|
|
832
822
|
canvasOnNodesChange(mainChanges)
|
|
@@ -904,7 +894,7 @@ function ViewEditorInner({
|
|
|
904
894
|
return () => observer.disconnect()
|
|
905
895
|
}, [maybeFitView])
|
|
906
896
|
|
|
907
|
-
useEffect(() => {
|
|
897
|
+
useEffect(() => { needsFitView.current = true }, [viewId])
|
|
908
898
|
|
|
909
899
|
// ── Dynamic viewport bounds ────────────────────────────────────────────────
|
|
910
900
|
useEffect(() => {
|
|
@@ -1010,12 +1000,17 @@ function ViewEditorInner({
|
|
|
1010
1000
|
const handleOpenExport = useCallback(() => exportModal.onOpen(), [exportModal])
|
|
1011
1001
|
const handleConnectorSave = useCallback((updated: Connector) => {
|
|
1012
1002
|
upsertConnectorGraphSnapshot(updated)
|
|
1013
|
-
|
|
1014
|
-
}, [
|
|
1015
|
-
const
|
|
1003
|
+
upsertStoreConnector(updated)
|
|
1004
|
+
}, [upsertStoreConnector])
|
|
1005
|
+
const handleConnectorDeleted = useCallback((edgeId: number) => {
|
|
1016
1006
|
if (viewId != null) removeConnectorGraphSnapshot(viewId, edgeId)
|
|
1017
|
-
|
|
1018
|
-
|
|
1007
|
+
removeStoreConnector(edgeId)
|
|
1008
|
+
void refreshElements()
|
|
1009
|
+
}, [refreshElements, removeStoreConnector, viewId])
|
|
1010
|
+
const handleConnectorDeleteInPanel = useCallback((edgeId: number) => {
|
|
1011
|
+
handleConnectorDeleted(edgeId)
|
|
1012
|
+
setSelectedEdge(null)
|
|
1013
|
+
}, [handleConnectorDeleted, setSelectedEdge])
|
|
1019
1014
|
const handleViewSave = useCallback((updated: ViewTreeNode) => setView(updated), [setView])
|
|
1020
1015
|
|
|
1021
1016
|
// ── Library helpers ────────────────────────────────────────────────────────
|
|
@@ -1224,8 +1219,10 @@ function ViewEditorInner({
|
|
|
1224
1219
|
nodesDraggable={canEdit} connectionMode={ConnectionMode.Loose} connectionRadius={25}
|
|
1225
1220
|
edgesUpdatable={canEdit} reconnectRadius={0}
|
|
1226
1221
|
snapToGrid={snapToGrid}
|
|
1227
|
-
snapGrid={
|
|
1222
|
+
snapGrid={SNAP_GRID}
|
|
1228
1223
|
deleteKeyCode={null}
|
|
1224
|
+
onlyRenderVisibleElements
|
|
1225
|
+
autoPanOnNodeDrag={false}
|
|
1229
1226
|
panOnDrag={!drawingMode}
|
|
1230
1227
|
panOnScroll={!isMobileLayout} panOnScrollSpeed={1.2} panOnScrollMode={PanOnScrollMode.Free}
|
|
1231
1228
|
zoomOnScroll={false} zoomOnPinch
|
|
@@ -1308,7 +1305,7 @@ function ViewEditorInner({
|
|
|
1308
1305
|
try {
|
|
1309
1306
|
await api.workspace.connectors.delete('', edgeId)
|
|
1310
1307
|
removeConnectorGraphSnapshot(viewId, edgeId)
|
|
1311
|
-
|
|
1308
|
+
removeStoreConnector(edgeId)
|
|
1312
1309
|
} catch { /* intentionally empty */ }
|
|
1313
1310
|
}}
|
|
1314
1311
|
/>
|
|
@@ -1406,8 +1403,8 @@ function ViewEditorInner({
|
|
|
1406
1403
|
onSave={handleConnectorSave} autoSave
|
|
1407
1404
|
onDelete={handleConnectorDeleteInPanel}
|
|
1408
1405
|
hasBackdrop={isMobileLayout}
|
|
1409
|
-
|
|
1410
|
-
|
|
1406
|
+
connectorPanelAfterContentSlot={connectorPanelAfterContentSlot}
|
|
1407
|
+
/>
|
|
1411
1408
|
<ProxyConnectorPanel
|
|
1412
1409
|
isOpen={proxyConnectorPanel.isOpen}
|
|
1413
1410
|
onClose={proxyConnectorPanel.onClose}
|