bug: popup within floating panel

This commit is contained in:
mathuo 2025-04-15 19:37:28 +01:00
parent 22deb851dc
commit d1239a5ee5
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
3 changed files with 61 additions and 47 deletions

View File

@ -1,3 +1,4 @@
import { shiftAbsoluteElementIntoView } from '../../dom';
import { addDisposableListener } from '../../events';
import {
CompositeDisposable,
@ -5,48 +6,6 @@ import {
MutableDisposable,
} from '../../lifecycle';
function shiftAbsoluteElementIntoView(element: HTMLElement, root: HTMLElement) {
const rect = element.getBoundingClientRect();
const rootRect = element.getBoundingClientRect();
const viewportWidth = root.clientWidth;
const viewportHeight = root.clientHeight;
// const viewportWidth =
// window.innerWidth || document.documentElement.clientWidth;
// const viewportHeight =
// window.innerHeight || document.documentElement.clientHeight;
const buffer = 10; // 10px buffer
let translateX = 0;
let translateY = 0;
const left = rect.left - rootRect.left;
const top = rect.top - rootRect.top;
const bottom = rect.bottom - rootRect.bottom;
const right = rect.right - rootRect.right;
// Check horizontal overflow
if (left < buffer) {
translateX = buffer - left;
} else if (right > viewportWidth - buffer) {
translateX = viewportWidth - right - buffer;
}
// Check vertical overflow
if (top < buffer) {
translateY = buffer - top;
} else if (bottom > viewportHeight - buffer) {
translateY = viewportHeight - bottom - buffer;
}
// Apply the translation if needed
if (translateX !== 0 || translateY !== 0) {
element.style.transform = `translate(${translateX}px, ${translateY}px)`;
}
}
export class PopupService extends CompositeDisposable {
private readonly _element: HTMLElement;
private _active: HTMLElement | null = null;
@ -71,13 +30,13 @@ export class PopupService extends CompositeDisposable {
openPopover(
element: HTMLElement,
position: { x: number; y: number }
position: { x: number; y: number; zIndex?: string }
): void {
this.close();
const wrapper = document.createElement('div');
wrapper.style.position = 'absolute';
wrapper.style.zIndex = '99';
wrapper.style.zIndex = position.zIndex ?? 'var(--dv-overlay-z-index)';
wrapper.appendChild(element);
const anchorBox = this._element.getBoundingClientRect();
@ -92,7 +51,7 @@ export class PopupService extends CompositeDisposable {
this._active = wrapper;
this._activeDisposable.value = new CompositeDisposable(
addDisposableListener(window, 'pointerdown', (event) => {
addDisposableListener(window, 'pointerdown', (event) => {
const target = event.target;
if (!(target instanceof HTMLElement)) {

View File

@ -8,7 +8,7 @@ import { addDisposableListener, Emitter, Event } from '../../../events';
import { Tab } from '../tab/tab';
import { DockviewGroupPanel } from '../../dockviewGroupPanel';
import { VoidContainer } from './voidContainer';
import { toggleClass } from '../../../dom';
import { findRelativeZIndexParent, toggleClass } from '../../../dom';
import { IDockviewPanel } from '../../dockviewPanel';
import { DockviewComponent } from '../../dockviewComponent';
import { WillShowOverlayLocationEvent } from '../../dockviewGroupPanelModel';
@ -378,7 +378,7 @@ export class TabsContainer
!panelObject.api.isActive
);
wrapper.addEventListener('mousedown', () => {
wrapper.addEventListener('pointerdown', () => {
this.accessor.popupService.close();
tab.element.scrollIntoView();
tab.panel.api.setActive();
@ -388,9 +388,14 @@ export class TabsContainer
el.appendChild(wrapper);
}
const relativeParent = findRelativeZIndexParent(root);
this.accessor.popupService.openPopover(el, {
x: event.clientX,
y: event.clientY,
zIndex: relativeParent?.style.zIndex
? `calc(${relativeParent.style.zIndex} * 2)`
: undefined,
});
})
);

View File

@ -451,3 +451,53 @@ export function onDidWindowResizeEnd(element: Window, cb: () => void) {
return disposable;
}
export function shiftAbsoluteElementIntoView(
element: HTMLElement,
root: HTMLElement,
options: { buffer: number } = { buffer: 10 }
) {
const buffer = options.buffer;
const rect = element.getBoundingClientRect();
const rootRect = element.getBoundingClientRect();
const viewportWidth = root.clientWidth;
const viewportHeight = root.clientHeight;
let translateX = 0;
let translateY = 0;
const left = rect.left - rootRect.left;
const top = rect.top - rootRect.top;
const bottom = rect.bottom - rootRect.bottom;
const right = rect.right - rootRect.right;
// Check horizontal overflow
if (left < buffer) {
translateX = buffer - left;
} else if (right > viewportWidth - buffer) {
translateX = viewportWidth - right - buffer;
}
// Check vertical overflow
if (top < buffer) {
translateY = buffer - top;
} else if (bottom > viewportHeight - buffer) {
translateY = viewportHeight - bottom - buffer;
}
// Apply the translation if needed
if (translateX !== 0 || translateY !== 0) {
element.style.transform = `translate(${translateX}px, ${translateY}px)`;
}
}
export function findRelativeZIndexParent(el: HTMLElement): HTMLElement | null {
let tmp: HTMLElement | null = el;
while (tmp && (tmp.style.zIndex === 'auto' || tmp.style.zIndex === '')) {
tmp = tmp.parentElement;
}
return tmp;
}