diff --git a/packages/base/src/util/dragAndDrop/DragRegistry.ts b/packages/base/src/util/dragAndDrop/DragRegistry.ts index 721769c2e1a3..6a7e177800c0 100644 --- a/packages/base/src/util/dragAndDrop/DragRegistry.ts +++ b/packages/base/src/util/dragAndDrop/DragRegistry.ts @@ -11,19 +11,17 @@ import { const MIN_MULTI_DRAG_COUNT = 2; let customDragElementPromise: Promise | null = null; -let draggedElement: HTMLElement | null = null; let globalHandlersAttached = false; const subscribers = new Set(); const selfManagedDragAreas = new Set(); +let draggedElements: Array = []; const ondragstart = (e: DragEvent) => { if (!e.dataTransfer || !(e.target instanceof HTMLElement)) { return; } - if (!selfManagedDragAreas.has(e.target)) { - draggedElement = e.target; - } + draggedElements = e.composedPath(); handleMultipleDrag(e); }; @@ -45,22 +43,29 @@ const handleMultipleDrag = async (e: DragEvent) => { }; const ondragend = () => { - draggedElement = null; + draggedElements = []; customDragElementPromise = null; }; const ondrop = () => { - draggedElement = null; + draggedElements = []; customDragElementPromise = null; }; -const setDraggedElement = (element: HTMLElement | null) => { - draggedElement = element; -}; -type SetDraggedElementFunction = typeof setDraggedElement; +const getDraggedElement = (rootNode: Node) => { + // get only elements that are part of the current rootNode + const _draggedElements = draggedElements.filter((el): el is HTMLElement => el instanceof HTMLElement && el.getRootNode() === rootNode); + + if (_draggedElements.length === 0) { + return null; + } + + // special handling for TabContainer. Maybe add generic method to UI5Element and override it in TabContainer + if (_draggedElements[0].hasAttribute("ui5-tabcontainer")) { + return ((_draggedElements[0] as unknown) as { _getDraggedElement: () => HTMLElement | null })._getDraggedElement(); + } -const getDraggedElement = () => { - return draggedElement; + return _draggedElements[0]; }; const createDefaultMultiDragElement = async (count: number): Promise => { @@ -130,16 +135,6 @@ const unsubscribe = (subscriber: UI5Element) => { } }; -const addSelfManagedArea = (area: HTMLElement | ShadowRoot) => { - selfManagedDragAreas.add(area); - - return setDraggedElement; -}; - -const removeSelfManagedArea = (area: HTMLElement | ShadowRoot) => { - selfManagedDragAreas.delete(area); -}; - type DragAndDropSettings = { /** * Allow cross-browser and file drag and drop. @@ -165,8 +160,6 @@ type MoveEventDetail = { const DragRegistry = { subscribe, unsubscribe, - addSelfManagedArea, - removeSelfManagedArea, getDraggedElement, startMultipleDrag, }; @@ -176,7 +169,6 @@ export { startMultipleDrag, }; export type { - SetDraggedElementFunction, DragAndDropSettings, MoveEventDetail, }; diff --git a/packages/base/src/util/dragAndDrop/handleDragOver.ts b/packages/base/src/util/dragAndDrop/handleDragOver.ts index ff36314cfafa..8a1acb480de5 100644 --- a/packages/base/src/util/dragAndDrop/handleDragOver.ts +++ b/packages/base/src/util/dragAndDrop/handleDragOver.ts @@ -17,7 +17,7 @@ type DragPosition = { * Handles the dragover event. */ function handleDragOver(e: DragEvent, component: T, position: DragPosition, target: HTMLElement, settings: DragAndDropSettings = {}): DragOverResult { - const draggedElement = DragRegistry.getDraggedElement(); + const draggedElement = DragRegistry.getDraggedElement(component.getRootNode()); const dragOverResult: DragOverResult = { targetReference: null, placement: null, diff --git a/packages/base/src/util/dragAndDrop/handleDrop.ts b/packages/base/src/util/dragAndDrop/handleDrop.ts index b7bc8bdc8ba2..a0292f951469 100644 --- a/packages/base/src/util/dragAndDrop/handleDrop.ts +++ b/packages/base/src/util/dragAndDrop/handleDrop.ts @@ -5,7 +5,7 @@ import DragRegistry from "./DragRegistry.js"; function handleDrop(e: DragEvent, component: T, target: HTMLElement, placement: `${MovePlacement}`, settings: DragAndDropSettings = {}): void { e.preventDefault(); - const draggedElement = DragRegistry.getDraggedElement(); + const draggedElement = DragRegistry.getDraggedElement(component.getRootNode()); if (!draggedElement && settings?.crossDnD) { return; diff --git a/packages/main/src/TabContainer.ts b/packages/main/src/TabContainer.ts index c337944204e1..85454f277a6d 100644 --- a/packages/main/src/TabContainer.ts +++ b/packages/main/src/TabContainer.ts @@ -34,7 +34,6 @@ import Orientation from "@ui5/webcomponents-base/dist/types/Orientation.js"; import DragRegistry from "@ui5/webcomponents-base/dist/util/dragAndDrop/DragRegistry.js"; import handleDragOver from "@ui5/webcomponents-base/dist/util/dragAndDrop/handleDragOver.js"; import handleDrop from "@ui5/webcomponents-base/dist/util/dragAndDrop/handleDrop.js"; -import type { SetDraggedElementFunction } from "@ui5/webcomponents-base/dist/util/dragAndDrop/DragRegistry.js"; import longDragOverHandler from "@ui5/webcomponents-base/dist/util/dragAndDrop/longDragOverHandler.js"; import MovePlacement from "@ui5/webcomponents-base/dist/types/MovePlacement.js"; import { @@ -354,7 +353,6 @@ class TabContainer extends UI5Element { responsivePopover?: ResponsivePopover; _hasScheduledPopoverOpen = false; _handleResizeBound: () => void; - _setDraggedElement?: SetDraggedElementFunction; static registerTabStyles(styles: string) { tabStyles.push(styles); @@ -434,7 +432,7 @@ class TabContainer extends UI5Element { onEnterDOM() { ResizeHandler.register(this._getHeader(), this._handleResizeBound); DragRegistry.subscribe(this); - this._setDraggedElement = DragRegistry.addSelfManagedArea(this); + if (isDesktop()) { this.setAttribute("desktop", ""); } @@ -443,8 +441,6 @@ class TabContainer extends UI5Element { onExitDOM() { ResizeHandler.deregister(this._getHeader(), this._handleResizeBound); DragRegistry.unsubscribe(this); - DragRegistry.removeSelfManagedArea(this); - this._setDraggedElement = undefined; } _handleResize() { @@ -495,6 +491,11 @@ class TabContainer extends UI5Element { } } + _getDraggedElement() { + return this.shadowRoot?.querySelector("[data-moving]")?.realTabReference + || this.shadowRoot?.querySelector(`#${this._id}-overflowMenu [data-moving]`); + } + _onDragStart(e: DragEvent) { if (!e.dataTransfer || !(e.target instanceof HTMLElement)) { return; @@ -502,8 +503,6 @@ class TabContainer extends UI5Element { e.dataTransfer.dropEffect = "move"; e.dataTransfer.effectAllowed = "move"; - - this._setDraggedElement!((e.target as TabInStrip).realTabReference); } _onHeaderDragEnter(e: DragEvent) { @@ -517,7 +516,7 @@ class TabContainer extends UI5Element { return; } - const draggedElement = DragRegistry.getDraggedElement(); + const draggedElement = DragRegistry.getDraggedElement(this.getRootNode()); const closestPosition = findClosestPosition( [...this._getTabStrip().querySelectorAll(`[role="tab"]:not([hidden])`)], e.clientX, @@ -625,7 +624,7 @@ class TabContainer extends UI5Element { _onPopoverListMoveOver(e: CustomEvent) { const { destination, source } = e.detail; - const draggedElement = DragRegistry.getDraggedElement()!; + const draggedElement = DragRegistry.getDraggedElement(this.getRootNode())!; let destinationElement: HTMLElement = (destination.element as TabInStrip | TabSeparatorInStrip).realTabReference; // workaround to simulate tree behavior @@ -675,7 +674,7 @@ class TabContainer extends UI5Element { _onPopoverListMove(e: CustomEvent) { const { destination, source } = e.detail; - const draggedElement = DragRegistry.getDraggedElement()!; + const draggedElement = DragRegistry.getDraggedElement(this.getRootNode())!; let destinationElement: HTMLElement = (destination.element as TabInStrip).realTabReference; // Workaround to simulate tree behavior @@ -715,9 +714,7 @@ class TabContainer extends UI5Element { } _onPopoverListKeyDown(e: KeyboardEvent) { - if (isCtrl(e)) { - this._setDraggedElement!((e.target as TabInOverflow).realTabReference); - } + // TODO } async _onTabStripClick(e: Event) { diff --git a/packages/main/src/delegate/DragAndDropHandler.ts b/packages/main/src/delegate/DragAndDropHandler.ts index ea776bd6190a..8ea9704ba4cd 100644 --- a/packages/main/src/delegate/DragAndDropHandler.ts +++ b/packages/main/src/delegate/DragAndDropHandler.ts @@ -51,7 +51,7 @@ class DragAndDropHandler { return; } - const draggedElement = DragRegistry.getDraggedElement()!; + const draggedElement = DragRegistry.getDraggedElement(this.component.getRootNode())!; const dropIndicator = this.config.getDropIndicator()!; const closestPosition = this._findClosestPosition(e); @@ -98,7 +98,7 @@ class DragAndDropHandler { return false; } - const draggedElement = DragRegistry.getDraggedElement(); + const draggedElement = DragRegistry.getDraggedElement(this.component.getRootNode()); const dropIndicator = this.config.getDropIndicator(); return !!(draggedElement && dropIndicator); diff --git a/packages/main/test/pages/DragAndDropInShadowDom.html b/packages/main/test/pages/DragAndDropInShadowDom.html new file mode 100644 index 000000000000..1d6f166d4890 --- /dev/null +++ b/packages/main/test/pages/DragAndDropInShadowDom.html @@ -0,0 +1,107 @@ + + + + + + + Drag and Drop in Shadow DOM + + + + + +
+
+ +
+
+ + + + + \ No newline at end of file