Skip to content

Commit 6b5b251

Browse files
committed
feat: when element from point fails find the closest target and drop there
1 parent 3f18d58 commit 6b5b251

File tree

1 file changed

+57
-18
lines changed

1 file changed

+57
-18
lines changed

src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,52 @@ function RemoteFunctions(config = {}) {
876876
}
877877
}
878878

879+
/**
880+
* Find the nearest valid drop target when direct elementFromPoint fails
881+
* @param {number} clientX - x coordinate
882+
* @param {number} clientY - y coordinate
883+
* @returns {Element|null} - nearest valid target or null
884+
*/
885+
function _findNearestValidTarget(clientX, clientY) {
886+
const searchRadius = 500;
887+
const step = 10; // pixel step for search
888+
889+
// Search in expanding squares around the cursor position
890+
for (let radius = step; radius <= searchRadius; radius += step) {
891+
// Check points in a square pattern around the cursor
892+
const points = [
893+
[clientX + radius, clientY],
894+
[clientX - radius, clientY],
895+
[clientX, clientY + radius],
896+
[clientX, clientY - radius],
897+
[clientX + radius, clientY + radius],
898+
[clientX - radius, clientY - radius],
899+
[clientX + radius, clientY - radius],
900+
[clientX - radius, clientY + radius]
901+
];
902+
903+
for (let point of points) {
904+
const [x, y] = point;
905+
let target = document.elementFromPoint(x, y);
906+
907+
if (!target || target === window._currentDraggedElement) {
908+
continue;
909+
}
910+
911+
// Find closest element with data-brackets-id
912+
while (target && !target.hasAttribute("data-brackets-id")) {
913+
target = target.parentElement;
914+
}
915+
916+
// Check if target is valid (not BODY, HTML or inside HEAD)
917+
if (isElementEditable(target) && target !== window._currentDraggedElement) {
918+
return target;
919+
}
920+
}
921+
}
922+
return null;
923+
}
924+
879925
/**
880926
* Handle dragover events on the document (throttled version)
881927
* Shows drop markers on valid drop targets
@@ -900,14 +946,12 @@ function RemoteFunctions(config = {}) {
900946
target = target.parentElement;
901947
}
902948

903-
// skip if no valid target found or if it's the dragged element
904-
if (!target || target === window._currentDraggedElement) {
905-
return;
906-
}
907-
908-
// Skip BODY, HTML tags and elements inside HEAD
909-
if (target.tagName === "BODY" || target.tagName === "HTML" || _isInsideHeadTag(target)) {
910-
return;
949+
if (!isElementEditable(target) || target === window._currentDraggedElement) {
950+
// if direct detection fails, we try to find a nearby valid target
951+
target = _findNearestValidTarget(event.clientX, event.clientY);
952+
if (!target) {
953+
return;
954+
}
911955
}
912956

913957
// Store original styles before modifying them
@@ -966,18 +1010,13 @@ function RemoteFunctions(config = {}) {
9661010
target = target.parentElement;
9671011
}
9681012

969-
// skip if no valid target found or if it's the dragged element
970-
if (!target || target === window._currentDraggedElement) {
971-
_clearDropMarkers();
972-
_stopAutoScroll();
973-
_dragEndChores(window._currentDraggedElement);
974-
dismissUIAndCleanupState();
975-
delete window._currentDraggedElement;
976-
return;
1013+
if (!isElementEditable(target) || target === window._currentDraggedElement) {
1014+
// if direct detection fails, we try to find a nearby valid target
1015+
target = _findNearestValidTarget(event.clientX, event.clientY);
9771016
}
9781017

979-
// Skip BODY, HTML tags and elements inside HEAD
980-
if (target.tagName === "BODY" || target.tagName === "HTML" || _isInsideHeadTag(target)) {
1018+
// skip if no valid target found or if it's the dragged element
1019+
if (!isElementEditable(target) || target === window._currentDraggedElement) {
9811020
_clearDropMarkers();
9821021
_stopAutoScroll();
9831022
_dragEndChores(window._currentDraggedElement);

0 commit comments

Comments
 (0)