mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 23:38:00 +00:00
Bring the drop position into .NET and add the DOM hit test
This commit is contained in:
6 files changed
+128
-2
No files matched your search
@@ -286,4 +286,52 @@ window.localShortcut = {
|
||||
document.removeEventListener('keydown', handler, true)
|
||||
localShortcutHandlers.delete(id)
|
||||
}
|
||||
}
|
||||
|
||||
// What floats above the page without ever being a drop target. Two of these take part in hit testing as
|
||||
// MudBlazor 8.15 stands: an open .mud-popover -- a closed one already declines pointer events through
|
||||
// .mud-popover:not(.mud-popover-open) -- and .mud-snackbar, which asks for them explicitly with
|
||||
// pointer-events: auto even though its container declines them, and snackbars appear constantly in this
|
||||
// app. Without this list, a drag would be answered by whatever happens to float on screen rather than by
|
||||
// the page below it. The remaining three are named because they surround those two: .mud-tooltip is the
|
||||
// content of a popover, while #mud-snackbar-container and .mud-badge-wrapper carry pointer-events: none
|
||||
// today and therefore never reach a hit test at all. Should a MudBlazor version drop that, they are
|
||||
// covered here already. Children of all of them have to be skipped as well, which is why the test below
|
||||
// uses closest rather than matches.
|
||||
const skippedDropOverlays = '.mud-popover, .mud-tooltip, .mud-snackbar, #mud-snackbar-container, .mud-badge-wrapper'
|
||||
|
||||
// The drop zones of the app, addressed by the cursor position of a native drag and drop event.
|
||||
//
|
||||
// The arbitration between overlapping zones is left to the browser, and it can be: MudBlazor 8.15 gives
|
||||
// neither .mud-dialog-container nor .mud-overlay a pointer-events: none. Both fill the viewport while a
|
||||
// dialog is open, so a point beside the dialog box hits the container, and nothing there is a drop zone. A
|
||||
// drop, therefore, cannot reach through an open dialog into the page behind it -- the very thing the app
|
||||
// used to enforce by counting layers in C#. That single CSS property carries this whole design, so it
|
||||
// belongs on the checklist for every MudBlazor major version, starting with the move to 9.
|
||||
window.dropZones = {
|
||||
|
||||
// Names the drop zone at the given viewport position, or null when there is none.
|
||||
//
|
||||
// The stack of elements is walked from the top down rather than asking for the topmost one alone,
|
||||
// because the topmost one may be an overlay from the list above and skipping it has to reveal what
|
||||
// lies beneath. The first element which is not skipped ends the walk, whether it belongs to a drop
|
||||
// zone or not: anything unknown blocks on purpose, so a drop can never slip through something the
|
||||
// user sees as being in the way. Within that element, closest resolves from the inside out, so a
|
||||
// specific zone inside a page-wide one wins -- which is exactly the precedence we want.
|
||||
hitTest: function (x, y) {
|
||||
for (const element of document.elementsFromPoint(x, y)) {
|
||||
if (element.closest(skippedDropOverlays))
|
||||
continue
|
||||
|
||||
return element.closest('[data-drop-zone-id]')?.getAttribute('data-drop-zone-id') ?? null
|
||||
}
|
||||
|
||||
return null
|
||||
},
|
||||
|
||||
// Every drop zone currently in the DOM, in document order. This is for diagnostics only: when a drop
|
||||
// lands nowhere, it answers the question of which zones would have been available at that moment.
|
||||
list: function () {
|
||||
return Array.from(document.querySelectorAll('[data-drop-zone-id]'), zone => zone.getAttribute('data-drop-zone-id'))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user