mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00:00 
			
		
		
		
	enhance(client): tweak contextmenu position calculation
This commit is contained in:
		
							parent
							
								
									3c01c0cbf2
								
							
						
					
					
						commit
						e7a1046b87
					
				
					 3 changed files with 45 additions and 23 deletions
				
			
		| 
						 | 
				
			
			@ -32,6 +32,8 @@ let rootEl = $shallowRef<HTMLDivElement>();
 | 
			
		|||
 | 
			
		||||
let zIndex = $ref<number>(os.claimZIndex('high'));
 | 
			
		||||
 | 
			
		||||
const SCROLLBAR_THICKNESS = 16;
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	let left = props.ev.pageX + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1
 | 
			
		||||
	let top = props.ev.pageY + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1
 | 
			
		||||
| 
						 | 
				
			
			@ -39,12 +41,12 @@ onMounted(() => {
 | 
			
		|||
	const width = rootEl.offsetWidth;
 | 
			
		||||
	const height = rootEl.offsetHeight;
 | 
			
		||||
 | 
			
		||||
	if (left + width - window.pageXOffset > window.innerWidth) {
 | 
			
		||||
		left = window.innerWidth - width + window.pageXOffset;
 | 
			
		||||
	if (left + width - window.pageXOffset >= (window.innerWidth - SCROLLBAR_THICKNESS)) {
 | 
			
		||||
		left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (top + height - window.pageYOffset > window.innerHeight) {
 | 
			
		||||
		top = window.innerHeight - height + window.pageYOffset;
 | 
			
		||||
	if (top + height - window.pageYOffset >= (window.innerHeight - SCROLLBAR_THICKNESS)) {
 | 
			
		||||
		top = (window.innerHeight - SCROLLBAR_THICKNESS) - height + window.pageYOffset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (top < 0) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
<template>
 | 
			
		||||
<div ref="el" class="sfhdhdhr">
 | 
			
		||||
	<MkMenu ref="menu" :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/>
 | 
			
		||||
<div ref="el" :class="$style.root">
 | 
			
		||||
	<MkMenu :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { nextTick, onMounted, shallowRef, watch } from 'vue';
 | 
			
		||||
import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue';
 | 
			
		||||
import MkMenu from './MkMenu.vue';
 | 
			
		||||
import { MenuItem } from '@/types/menu';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,11 +25,21 @@ const emit = defineEmits<{
 | 
			
		|||
const el = shallowRef<HTMLElement>();
 | 
			
		||||
const align = 'left';
 | 
			
		||||
 | 
			
		||||
const SCROLLBAR_THICKNESS = 16;
 | 
			
		||||
 | 
			
		||||
function setPosition() {
 | 
			
		||||
	const rootRect = props.rootElement.getBoundingClientRect();
 | 
			
		||||
	const rect = props.targetElement.getBoundingClientRect();
 | 
			
		||||
	const left = props.targetElement.offsetWidth;
 | 
			
		||||
	const top = (rect.top - rootRect.top) - 8;
 | 
			
		||||
	const parentRect = props.targetElement.getBoundingClientRect();
 | 
			
		||||
	const myRect = el.value.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
	let left = props.targetElement.offsetWidth;
 | 
			
		||||
	let top = (parentRect.top - rootRect.top) - 8;
 | 
			
		||||
	if (rootRect.left + left + myRect.width >= (window.innerWidth - SCROLLBAR_THICKNESS)) {
 | 
			
		||||
		left = -myRect.width;
 | 
			
		||||
	}
 | 
			
		||||
	if (rootRect.top + top + myRect.height >= (window.innerHeight - SCROLLBAR_THICKNESS)) {
 | 
			
		||||
		top = top - ((rootRect.top + top + myRect.height) - (window.innerHeight - SCROLLBAR_THICKNESS));
 | 
			
		||||
	}
 | 
			
		||||
	el.value.style.left = left + 'px';
 | 
			
		||||
	el.value.style.top = top + 'px';
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -46,13 +56,22 @@ watch(() => props.targetElement, () => {
 | 
			
		|||
	setPosition();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const ro = new ResizeObserver((entries, observer) => {
 | 
			
		||||
	setPosition();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	ro.observe(el.value);
 | 
			
		||||
	setPosition();
 | 
			
		||||
	nextTick(() => {
 | 
			
		||||
		setPosition();
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onUnmounted(() => {
 | 
			
		||||
	ro.disconnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineExpose({
 | 
			
		||||
	checkHit: (ev: MouseEvent) => {
 | 
			
		||||
		return (ev.target === el.value || el.value.contains(ev.target));
 | 
			
		||||
| 
						 | 
				
			
			@ -60,8 +79,8 @@ defineExpose({
 | 
			
		|||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.sfhdhdhr {
 | 
			
		||||
<style lang="scss" module>
 | 
			
		||||
.root {
 | 
			
		||||
	position: absolute;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -125,7 +125,7 @@ function onBgClick() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
if (type === 'drawer') {
 | 
			
		||||
	maxHeight = window.innerHeight / 1.5;
 | 
			
		||||
	maxHeight = (window.innerHeight - SCROLLBAR_THICKNESS) / 1.5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const keymap = {
 | 
			
		||||
| 
						 | 
				
			
			@ -133,6 +133,7 @@ const keymap = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
const MARGIN = 16;
 | 
			
		||||
const SCROLLBAR_THICKNESS = 16;
 | 
			
		||||
 | 
			
		||||
const align = () => {
 | 
			
		||||
	if (props.src == null) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -170,15 +171,15 @@ const align = () => {
 | 
			
		|||
 | 
			
		||||
	if (fixed) {
 | 
			
		||||
		// 画面から横にはみ出る場合
 | 
			
		||||
		if (left + width > window.innerWidth) {
 | 
			
		||||
			left = window.innerWidth - width;
 | 
			
		||||
		if (left + width > (window.innerWidth - SCROLLBAR_THICKNESS)) {
 | 
			
		||||
			left = (window.innerWidth - SCROLLBAR_THICKNESS) - width;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const underSpace = (window.innerHeight - MARGIN) - top;
 | 
			
		||||
		const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - top;
 | 
			
		||||
		const upperSpace = (srcRect.top - MARGIN);
 | 
			
		||||
 | 
			
		||||
		// 画面から縦にはみ出る場合
 | 
			
		||||
		if (top + height > (window.innerHeight - MARGIN)) {
 | 
			
		||||
		if (top + height > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
 | 
			
		||||
			if (props.noOverlap && props.anchor.x === 'center') {
 | 
			
		||||
				if (underSpace >= (upperSpace / 3)) {
 | 
			
		||||
					maxHeight = underSpace;
 | 
			
		||||
| 
						 | 
				
			
			@ -187,22 +188,22 @@ const align = () => {
 | 
			
		|||
					top = (upperSpace + MARGIN) - height;
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				top = (window.innerHeight - MARGIN) - height;
 | 
			
		||||
				top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			maxHeight = underSpace;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// 画面から横にはみ出る場合
 | 
			
		||||
		if (left + width - window.pageXOffset > window.innerWidth) {
 | 
			
		||||
			left = window.innerWidth - width + window.pageXOffset - 1;
 | 
			
		||||
		if (left + width - window.pageXOffset > (window.innerWidth - SCROLLBAR_THICKNESS)) {
 | 
			
		||||
			left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset - 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const underSpace = (window.innerHeight - MARGIN) - (top - window.pageYOffset);
 | 
			
		||||
		const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.pageYOffset);
 | 
			
		||||
		const upperSpace = (srcRect.top - MARGIN);
 | 
			
		||||
 | 
			
		||||
		// 画面から縦にはみ出る場合
 | 
			
		||||
		if (top + height - window.pageYOffset > (window.innerHeight - MARGIN)) {
 | 
			
		||||
		if (top + height - window.pageYOffset > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) {
 | 
			
		||||
			if (props.noOverlap && props.anchor.x === 'center') {
 | 
			
		||||
				if (underSpace >= (upperSpace / 3)) {
 | 
			
		||||
					maxHeight = underSpace;
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +212,7 @@ const align = () => {
 | 
			
		|||
					top = window.pageYOffset + ((upperSpace + MARGIN) - height);
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				top = (window.innerHeight - MARGIN) - height + window.pageYOffset - 1;
 | 
			
		||||
				top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height + window.pageYOffset - 1;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			maxHeight = underSpace;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue