feat: refactor context menu to capture native events (#7858)

* feat: refactor context menu to capture native events

prevent context-menu to show in html input fields

* fix: refactor context-menu.vue for improved structure

* chore: fix format

* chore: remove dead code

* chore: fix lint

* fix: update contenteditable selector in context menu

proposed fixed by coderabitai
This commit is contained in:
mew
2026-04-28 13:36:13 +08:00
committed by GitHub
parent 36d7dc23fa
commit 99c38c93c8

View File

@@ -9,7 +9,7 @@ import type { ClassType } from '@vben-core/typings';
import type { IContextMenuItem } from './interface';
import { computed } from 'vue';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useForwardPropsEmits } from 'reka-ui';
@@ -35,6 +35,14 @@ const props = defineProps<
const emits = defineEmits<ContextMenuRootEmits>();
const NATIVE_CONTEXT_SELECTORS = [
'input',
'textarea',
'select',
'[contenteditable]:not([contenteditable="false"])',
'.allow-native-context',
].join(', ');
const delegatedProps = computed(() => {
const {
class: _cls,
@@ -59,12 +67,34 @@ function handleClick(menu: IContextMenuItem) {
}
menu?.handler?.(props.handlerData);
}
const triggerRef = ref<HTMLElement | null>(null);
function onContextMenuCapture(e: MouseEvent) {
if ((e.target as HTMLElement).closest(NATIVE_CONTEXT_SELECTORS)) {
e.stopPropagation();
}
}
onMounted(() => {
triggerRef.value?.addEventListener('contextmenu', onContextMenuCapture, {
capture: true,
});
});
onUnmounted(() => {
triggerRef.value?.removeEventListener('contextmenu', onContextMenuCapture, {
capture: true,
});
});
</script>
<template>
<ContextMenu v-bind="forwarded">
<ContextMenuTrigger as-child>
<slot></slot>
<div ref="triggerRef">
<slot></slot>
</div>
</ContextMenuTrigger>
<ContextMenuContent
:class="contentClass"