SYNC: slightly better dropdownmanu-layout algorithm

This commit is contained in:
SPRINX0\prochazka
2025-03-26 16:13:01 +01:00
committed by Diflow
parent c1da8321ac
commit bd571dc93d
5 changed files with 54 additions and 35 deletions

View File

@@ -433,7 +433,10 @@ describe('Data browser data', () => {
cy.contains('Album').click(); cy.contains('Album').click();
cy.testid('DataFilterControl_input_ArtistId').type('22{enter}'); cy.testid('DataFilterControl_input_ArtistId').type('22{enter}');
// cy.contains('Presence').rightclick(); // cy.contains('Presence').rightclick();
// cy.contains('Coda').rightclick();
// cy.testid('DropDownMenu-container-0').contains('Export').click();
cy.contains('Export').click(); cy.contains('Export').click();
// cy.wait(1000);
cy.themeshot('data-browser-export-menu'); cy.themeshot('data-browser-export-menu');
}); });

View File

@@ -1 +0,0 @@
Folder with screenshots

View File

@@ -14,8 +14,9 @@
function handleClick(e) { function handleClick(e) {
const rect = e.detail.target.getBoundingClientRect(); const rect = e.detail.target.getBoundingClientRect();
const left = rect.left; const left = rect.left;
const top = rect.bottom; const top = rect.top;
currentDropDownMenu.set({ left, top, items: menu }); // const top = rect.bottom;
currentDropDownMenu.set({ left, bottom: window.innerHeight - top, items: menu });
} }
</script> </script>

View File

@@ -8,6 +8,7 @@
<DropDownMenu <DropDownMenu
left={$currentDropDownMenu.left} left={$currentDropDownMenu.left}
top={$currentDropDownMenu.top} top={$currentDropDownMenu.top}
bottom={$currentDropDownMenu.bottom}
items={$currentDropDownMenu.items} items={$currentDropDownMenu.items}
targetElement={$currentDropDownMenu.targetElement} targetElement={$currentDropDownMenu.targetElement}
on:close={() => ($currentDropDownMenu = null)} on:close={() => ($currentDropDownMenu = null)}

View File

@@ -7,29 +7,6 @@
if (side == 'right') return { top: top, left: left + box.width }; if (side == 'right') return { top: top, left: left + box.width };
return { top: top, left: left }; return { top: top, left: left };
} }
function fixPopupPlacement(element) {
const { width, height } = element.getBoundingClientRect();
let offset = getElementOffset(element);
let newLeft = null;
let newTop = null;
if (offset.left + width > window.innerWidth) {
newLeft = offset.left - width;
if (newLeft < 0) newLeft = 0;
}
if (offset.top + height > window.innerHeight) {
newTop = offset.top - height;
if (newTop < 0) newTop = 0;
}
if (newLeft != null) element.style.left = `${newLeft}px`;
if (newTop != null) element.style.top = `${newTop}px`;
}
</script> </script>
<script> <script>
@@ -43,12 +20,17 @@
export let items; export let items;
export let top; export let top;
export let bottom;
export let left; export let left;
export let onCloseParent; export let onCloseParent;
export let targetElement; export let targetElement;
export let submenuLevel = 0;
let element; let element;
let newLeft = undefined;
let newTop = undefined;
let hoverItem; let hoverItem;
let hoverOffset; let hoverOffset;
@@ -57,6 +39,8 @@
let switchIndex = 0; let switchIndex = 0;
let submenuKey = 0;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let closeHandlers = []; let closeHandlers = [];
@@ -68,6 +52,25 @@
closeHandlers = []; closeHandlers = [];
} }
function fixPopupPlacement(element) {
const { width, height } = element.getBoundingClientRect();
let offset = getElementOffset(element);
if (offset.left + width > window.innerWidth) {
newLeft = offset.left - width;
if (newLeft < 0) newLeft = 0;
}
if (offset.top < 0) {
newTop = 0;
} else if (offset.top + height > window.innerHeight) {
newTop = offset.top - height;
if (newTop < 0) newTop = 0;
}
}
function registerCloseHandler(handler) { function registerCloseHandler(handler) {
closeHandlers.push(handler); closeHandlers.push(handler);
} }
@@ -80,6 +83,7 @@
submenuItem = item; submenuItem = item;
submenuOffset = hoverOffset; submenuOffset = hoverOffset;
submenuKey += 1;
return; return;
} }
if (item.switchStore && item.switchValue) { if (item.switchStore && item.switchValue) {
@@ -109,6 +113,7 @@
const changeActiveSubmenu = _.throttle(() => { const changeActiveSubmenu = _.throttle(() => {
submenuItem = hoverItem; submenuItem = hoverItem;
submenuOffset = hoverOffset; submenuOffset = hoverOffset;
submenuKey += 1;
}, 500); }, 500);
$: preparedItems = prepareMenuItems(items, { targetElement, registerCloseHandler }, $commandsCustomized); $: preparedItems = prepareMenuItems(items, { targetElement, registerCloseHandler }, $commandsCustomized);
@@ -128,7 +133,14 @@
}); });
</script> </script>
<ul class="dropDownMenuMarker" style={`left: ${left}px; top: ${top}px`} bind:this={element}> <ul
class="dropDownMenuMarker"
style:top={(newTop ?? top) != null ? `${newTop ?? top}px` : undefined}
style:bottom={newTop == null && bottom != null ? `${bottom}px` : undefined}
style:left={(newLeft ?? left) != null ? `${newLeft ?? left}px` : undefined}
bind:this={element}
data-testid={`DropDownMenu-container-${submenuLevel}`}
>
{#each preparedItems as item} {#each preparedItems as item}
{#if item.divider} {#if item.divider}
<li class="divider" /> <li class="divider" />
@@ -172,14 +184,17 @@
{/each} {/each}
</ul> </ul>
{#if submenuItem?.submenu} {#if submenuItem?.submenu}
<svelte:self {#key submenuKey}
items={submenuItem?.submenu} <svelte:self
{...submenuOffset} items={submenuItem?.submenu}
onCloseParent={() => { {...submenuOffset}
if (onCloseParent) onCloseParent(); onCloseParent={() => {
dispatchClose(); if (onCloseParent) onCloseParent();
}} dispatchClose();
/> }}
submenuLevel={submenuLevel + 1}
/>
{/key}
{/if} {/if}
<style> <style>