diff --git a/packages/ui/src/components/Popup.svelte b/packages/ui/src/components/Popup.svelte index ba29b77db7..68d15a1790 100644 --- a/packages/ui/src/components/Popup.svelte +++ b/packages/ui/src/components/Popup.svelte @@ -30,20 +30,18 @@ {#if $modal.length > 0} <slot name="popup-header" /> {/if} -{#each $modal as popup, i} - {#key popup.id} - <PopupInstance - bind:this={instances[i]} - is={popup.is} - props={popup.props} - element={popup.element} - onClose={popup.onClose} - onUpdate={popup.onUpdate} - zIndex={(i + 1) * 500} - top={$modal.length - 1 === i} - close={popup.close} - {contentPanel} - overlay={popup.options.overlay} - /> - {/key} +{#each $modal as popup, i (popup.id)} + <PopupInstance + bind:this={instances[i]} + is={popup.is} + props={popup.props} + element={popup.element} + onClose={popup.onClose} + onUpdate={popup.onUpdate} + zIndex={(i + 1) * 500} + top={$modal.length - 1 === i} + close={popup.close} + {contentPanel} + overlay={popup.options.overlay} + /> {/each} diff --git a/packages/ui/src/components/PopupInstance.svelte b/packages/ui/src/components/PopupInstance.svelte index 524dfc562b..83c50607c7 100644 --- a/packages/ui/src/components/PopupInstance.svelte +++ b/packages/ui/src/components/PopupInstance.svelte @@ -83,7 +83,9 @@ options.props.maxHeight = '100vh' if (!modalHTML.classList.contains('fullsize')) modalHTML.classList.add('fullsize') } else { - options = fitPopupElement(modalHTML, device, element, contentPanel, clientWidth, clientHeight) + if (element !== 'float' || options?.props?.top === undefined || options?.props?.top === '') { + options = fitPopupElement(modalHTML, device, element, contentPanel, clientWidth, clientHeight) + } if (modalHTML.classList.contains('fullsize')) modalHTML.classList.remove('fullsize') } options.fullSize = fullSize @@ -126,6 +128,16 @@ ) } + let drag: boolean = false + + const dragParams: { + x: number + y: number + } = { + x: 0, + y: 0 + } + export function fitPopupInstance (): void { if (modalHTML) { fitPopup(modalHTML, element, contentPanel) @@ -148,7 +160,7 @@ <div class="popup {testing ? 'endShow' : showing === undefined ? 'endShow' : !showing ? 'preShow' : 'startShow'}" class:testing - class:anim={(element === 'float' || element === 'centered') && !testing} + class:anim={(element === 'float' || element === 'centered') && !testing && !drag} bind:this={modalHTML} style={`z-index: ${zIndex + 1};`} style:top={options?.props?.top} @@ -167,6 +179,22 @@ clientHeight = element.clientHeight fitPopupInstance() }} + on:mousedown={(e) => { + if (element === 'float') { + dragParams.x = e.offsetX + dragParams.y = e.offsetY + drag = true + } + }} + on:mouseup={() => { + drag = false + }} + on:mousemove={(e) => { + if (element === 'float' && drag) { + options.props.top = `${e.clientY - dragParams.y}px` + options.props.left = `${e.clientX - dragParams.x}px` + } + }} > <svelte:component this={is} @@ -189,15 +217,24 @@ /> </div> -{#if overlay} +{#if overlay || drag} <!-- svelte-ignore a11y-no-static-element-interactions --> <div class="modal-overlay" class:testing - class:antiOverlay={options?.showOverlay} + class:antiOverlay={options?.showOverlay && !drag} style={`z-index: ${zIndex};`} on:click={handleOverlayClick} on:keydown|stopPropagation|preventDefault={() => {}} + on:mouseup={() => { + drag = false + }} + on:mousemove={(e) => { + if (element === 'float' && drag) { + options.props.top = `${e.clientY - dragParams.y}px` + options.props.left = `${e.clientX - dragParams.x}px` + } + }} /> {/if} diff --git a/packages/ui/src/popups.ts b/packages/ui/src/popups.ts index 279b40e6c4..227c8c383d 100644 --- a/packages/ui/src/popups.ts +++ b/packages/ui/src/popups.ts @@ -228,10 +228,14 @@ export function fitPopupElement ( newProps.maxHeight = fullHeight ? 'calc(100vh - 2rem)' : '75vh' show = true } else if (element === 'float') { - newProps.top = 'calc(var(--status-bar-height) + 4px)' - newProps.bottom = '4px' - newProps.left = '60%' - newProps.right = '4px' + if (clientWidth !== undefined && clientHeight !== undefined) { + newProps.top = `calc(50% - ${clientHeight / 2}px` + newProps.left = `calc(50% - ${clientWidth / 2}px` + } else { + newProps.top = '50%' + newProps.left = '50%' + newProps.transform = 'translate(-50%, -50%)' + } show = true } else if (element === 'center') { if (clientWidth !== undefined && clientHeight !== undefined) {