수정
This commit is contained in:
@@ -2,6 +2,8 @@ import type { ReactFlowInstance } from '@xyflow/react';
|
||||
|
||||
type FlowProjector = Pick<ReactFlowInstance, 'screenToFlowPosition' | 'getViewport'>;
|
||||
|
||||
const DRAG_LAYER_SELECTOR = '.se-palette-drag-overlay, .se-palette-drag-ghost';
|
||||
|
||||
function manualProject(
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
@@ -20,6 +22,27 @@ function manualProject(
|
||||
};
|
||||
}
|
||||
|
||||
/** 드래그 overlay 아래 DOM 탐색 (overlay pointer-events 잠시 비활성) */
|
||||
export function elementsUnderDragPoint(clientX: number, clientY: number): Element[] {
|
||||
const overlays = document.querySelectorAll<HTMLElement>(DRAG_LAYER_SELECTOR);
|
||||
const prev: string[] = [];
|
||||
overlays.forEach(el => {
|
||||
prev.push(el.style.pointerEvents);
|
||||
el.style.pointerEvents = 'none';
|
||||
});
|
||||
try {
|
||||
if (typeof document.elementsFromPoint === 'function') {
|
||||
return document.elementsFromPoint(clientX, clientY);
|
||||
}
|
||||
const hit = document.elementFromPoint(clientX, clientY);
|
||||
return hit ? [hit] : [];
|
||||
} finally {
|
||||
overlays.forEach((el, i) => {
|
||||
el.style.pointerEvents = prev[i] ?? '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** screen(client) → React Flow 좌표 (Tauri WebView screenToFlowPosition 보정) */
|
||||
export function projectScreenToFlowPosition(
|
||||
clientX: number,
|
||||
@@ -31,7 +54,6 @@ export function projectScreenToFlowPosition(
|
||||
try {
|
||||
const pos = rf.screenToFlowPosition({ x: clientX, y: clientY });
|
||||
if (Number.isFinite(pos.x) && Number.isFinite(pos.y)) {
|
||||
// WebView 버그: 화면 픽셀을 그대로 반환하는 경우
|
||||
const looksLikeScreenPx =
|
||||
Math.abs(pos.x - clientX) < 2 && Math.abs(pos.y - clientY) < 2;
|
||||
if (!looksLikeScreenPx) return pos;
|
||||
@@ -50,26 +72,18 @@ export function projectScreenToFlowPosition(
|
||||
);
|
||||
}
|
||||
|
||||
/** 팔레트 드롭 — 전략 빌더 캔버스 위인지 (우측 팔레트 위 release 무시) */
|
||||
/** 팔레트 드롭 — 전략 빌더 캔버스 위인지 */
|
||||
export function isOverStrategyBuilder(clientX: number, clientY: number): boolean {
|
||||
const elements = typeof document.elementsFromPoint === 'function'
|
||||
? document.elementsFromPoint(clientX, clientY)
|
||||
: [document.elementFromPoint(clientX, clientY)].filter(Boolean) as Element[];
|
||||
|
||||
for (const el of elements) {
|
||||
if (el.closest('.se-palette-panel, .se-side-wrap--right, .se-palette-drag-ghost')) continue;
|
||||
if (el.closest('.se-canvas-wrap')) return true;
|
||||
for (const el of elementsUnderDragPoint(clientX, clientY)) {
|
||||
if (el.closest('.se-palette-panel, .se-side-wrap--right')) continue;
|
||||
if (el.closest('.se-canvas-wrap, .react-flow__pane, .react-flow__renderer')) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** DOM hit-test — elementsFromPoint 로 ghost·overlay 아래 노드까지 탐색 */
|
||||
/** DOM hit-test — overlay 아래 react-flow 노드 탐색 */
|
||||
export function findFlowNodeIdAtClientPoint(clientX: number, clientY: number): string | null {
|
||||
const elements = typeof document.elementsFromPoint === 'function'
|
||||
? document.elementsFromPoint(clientX, clientY)
|
||||
: [document.elementFromPoint(clientX, clientY)].filter(Boolean) as Element[];
|
||||
|
||||
for (const el of elements) {
|
||||
for (const el of elementsUnderDragPoint(clientX, clientY)) {
|
||||
const nodeEl = el.closest('.react-flow__node') as HTMLElement | null;
|
||||
if (nodeEl) {
|
||||
const id = nodeEl.getAttribute('data-id');
|
||||
@@ -109,10 +123,12 @@ export function resolvePaletteDropClientPoint(
|
||||
return { flowPos, anchorId: domId };
|
||||
}
|
||||
|
||||
// DOM hit-test 실패 시 START 노드 bounding rect 로 보조
|
||||
for (const node of nodes) {
|
||||
if (!isConnectTarget(node.id)) continue;
|
||||
const el = document.querySelector(`.react-flow__node[data-id="${CSS.escape(node.id)}"]`);
|
||||
const escaped = typeof CSS !== 'undefined' && CSS.escape
|
||||
? CSS.escape(node.id)
|
||||
: node.id.replace(/"/g, '\\"');
|
||||
const el = document.querySelector(`.react-flow__node[data-id="${escaped}"]`);
|
||||
if (!el) continue;
|
||||
const rect = el.getBoundingClientRect();
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user