|
2 | 2 |
|
3 | 3 | import React from "react" |
4 | 4 | import dynamic from "next/dynamic" |
5 | | -import { useState, useRef, useEffect, useCallback } from "react" |
| 5 | +import { useState, useRef, useEffect, useCallback, useMemo } from "react" |
6 | 6 | import { Toolbar } from "./toolbar" |
7 | 7 | import { PropertiesPanel } from "./properties-panel" |
8 | 8 | import { ThemeToggle } from "@/components/theme-toggle" |
@@ -166,6 +166,41 @@ export function Canvas({ previewElements }: { previewElements?: PreviewState | n |
166 | 166 | elementsRef.current = elements |
167 | 167 | selectedConnectionIdRef.current = selectedConnectionId |
168 | 168 |
|
| 169 | + const selectedElementIds = useMemo(() => new Set(appState.selection), [appState.selection]) |
| 170 | + const selectedElements = useMemo( |
| 171 | + () => elements.filter((el) => selectedElementIds.has(el.id)), |
| 172 | + [elements, selectedElementIds], |
| 173 | + ) |
| 174 | + const elementById = useMemo(() => { |
| 175 | + const map = new Map<string, CanvasElement>() |
| 176 | + for (const el of elements) { |
| 177 | + map.set(el.id, el) |
| 178 | + } |
| 179 | + return map |
| 180 | + }, [elements]) |
| 181 | + const connectorPreviewAnchor = useMemo(() => { |
| 182 | + if (!connectorSource) return null |
| 183 | + |
| 184 | + const element = elementById.get(connectorSource.elementId) |
| 185 | + if (!element) return null |
| 186 | + |
| 187 | + const centerX = element.x + element.width / 2 |
| 188 | + const centerY = element.y + element.height / 2 |
| 189 | + |
| 190 | + switch (connectorSource.handle) { |
| 191 | + case "left": |
| 192 | + return { x: element.x, y: centerY } |
| 193 | + case "right": |
| 194 | + return { x: element.x + element.width, y: centerY } |
| 195 | + case "top": |
| 196 | + return { x: centerX, y: element.y } |
| 197 | + case "bottom": |
| 198 | + return { x: centerX, y: element.y + element.height } |
| 199 | + default: |
| 200 | + return { x: centerX, y: centerY } |
| 201 | + } |
| 202 | + }, [connectorSource, elementById]) |
| 203 | + |
169 | 204 | const centerViewportOnElements = useCallback(() => { |
170 | 205 | if (elements.length === 0) return |
171 | 206 |
|
@@ -2042,15 +2077,15 @@ export function Canvas({ previewElements }: { previewElements?: PreviewState | n |
2042 | 2077 | {/* Fixed properties panel */} |
2043 | 2078 | <PropertiesPanel |
2044 | 2079 | appState={appState} |
2045 | | - selectedElements={elements.filter((el) => appState.selection.includes(el.id))} |
| 2080 | + selectedElements={selectedElements} |
2046 | 2081 | selectedConnectionId={selectedConnectionId} // Pass selected connection ID |
2047 | 2082 | connections={connections} // Pass connections |
2048 | 2083 | onChange={(updates) => handleAppStateChange(updates)} |
2049 | 2084 | onAction={handleAction} |
2050 | 2085 | /> |
2051 | 2086 |
|
2052 | 2087 | <ActionsMenu |
2053 | | - selectedElements={elements.filter((el) => appState.selection.includes(el.id))} |
| 2088 | + selectedElements={selectedElements} |
2054 | 2089 | onAction={handleAction} |
2055 | 2090 | /> |
2056 | 2091 |
|
@@ -2110,32 +2145,8 @@ export function Canvas({ previewElements }: { previewElements?: PreviewState | n |
2110 | 2145 | { |
2111 | 2146 | connectorSource && connectorPreview && ( |
2112 | 2147 | <line |
2113 | | - x1={(() => { |
2114 | | - const el = elements.find((e) => e.id === connectorSource.elementId) |
2115 | | - if (!el) return 0 |
2116 | | - const cx = el.x + el.width / 2 |
2117 | | - switch (connectorSource.handle) { |
2118 | | - case "left": |
2119 | | - return el.x |
2120 | | - case "right": |
2121 | | - return el.x + el.width |
2122 | | - default: |
2123 | | - return cx |
2124 | | - } |
2125 | | - })()} |
2126 | | - y1={(() => { |
2127 | | - const el = elements.find((e) => e.id === connectorSource.elementId) |
2128 | | - if (!el) return 0 |
2129 | | - const cy = el.y + el.height / 2 |
2130 | | - switch (connectorSource.handle) { |
2131 | | - case "top": |
2132 | | - return el.y |
2133 | | - case "bottom": |
2134 | | - return el.y + el.height |
2135 | | - default: |
2136 | | - return cy |
2137 | | - } |
2138 | | - })()} |
| 2148 | + x1={connectorPreviewAnchor?.x ?? 0} |
| 2149 | + y1={connectorPreviewAnchor?.y ?? 0} |
2139 | 2150 | x2={connectorPreview.x} |
2140 | 2151 | y2={connectorPreview.y} |
2141 | 2152 | stroke={getSolidStrokeColor(appState.currentItemStrokeColor)} |
|
0 commit comments