Fix table viz context menu (#9820)

Fixes #9700

[Screencast from 2024-04-30 15-09-17.webm](https://github.com/enso-org/enso/assets/3919101/a11ae875-7e2f-4c84-8d91-33aa1ca8bdbd)

# Important Notes
During implementation, I discovered a bug that the context menu wasn't hidden by click at background (or node) - all because of preventDefault, as it turned out.
This commit is contained in:
Adam Obuchowicz 2024-05-02 13:17:13 +02:00 committed by GitHub
parent 07b720a90a
commit 0186ed1961
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 25 additions and 26 deletions

View File

@ -104,9 +104,9 @@ const nodeShortType = computed(() =>
@pointerup.stop
@click.stop
>
<div class="resizer-right" v-on="resizeRight.stop.events"></div>
<div class="resizer-bottom" v-on="resizeBottom.stop.events"></div>
<div class="resizer-bottom-right" v-on="resizeBottomRight.stop.events"></div>
<div class="resizer-right" v-on="resizeRight.events"></div>
<div class="resizer-bottom" v-on="resizeBottom.events"></div>
<div class="resizer-bottom-right" v-on="resizeBottomRight.events"></div>
<SmallPlusButton
v-if="config.isCircularMenuVisible"
class="below-viz"

View File

@ -117,6 +117,7 @@ const agGridOptions: Ref<GridOptions & Required<Pick<GridOptions, 'defaultColDef
onColumnResized: lockColumnSize,
suppressFieldDotNotation: true,
enableRangeSelection: true,
popupParent: document.body,
})
const isRowCountSelectorVisible = computed(() => rowCount.value >= 1000)
@ -410,6 +411,7 @@ onMounted(() => {
origValidateLicense.call(this)
}
}
// TODO: consider using Vue component instead: https://ag-grid.com/vue-data-grid/getting-started/
new Grid(tableNode.value!, agGridOptions.value)
updateColumnWidths()
})

View File

@ -4,7 +4,7 @@ import { assert } from '@/util/assert'
import { Rect } from '@/util/data/rect'
import { Vec2 } from '@/util/data/vec2'
import { isPointer, pointerButtonToEventInfo, type BindingInfo } from '@/util/shortcuts'
import { expect, test, vi } from 'vitest'
import { beforeAll, expect, test, vi } from 'vitest'
import { proxyRefs, ref, type Ref } from 'vue'
function selectionWithMockData(sceneMousePos?: Ref<Vec2>) {
@ -104,7 +104,7 @@ test.each`
dragCase(new Vec2(area.right, area.top), new Vec2(area.left, area.bottom))
})
// There is no PointerEvent class in jsdom (yet).
// See https://github.com/thymikee/jest-preset-angular/issues/245#issuecomment-576296325
class MockPointerEvent extends MouseEvent {
readonly pointerId: number
constructor(type: string, options: MouseEventInit & { currentTarget?: Element | undefined }) {
@ -116,6 +116,10 @@ class MockPointerEvent extends MouseEvent {
}
}
beforeAll(() => {
;(window as any).PointerEvent = MockPointerEvent
})
function mockPointerEvent(type: string, pos: Vec2, binding: BindingInfo): PointerEvent {
const modifiersSet = new Set(binding.modifiers)
assert(isPointer(binding.key))

View File

@ -305,7 +305,7 @@ export function usePointer(
if (trackedElement != null && initialGrabPos != null && lastPos != null) {
if (handler(computePosition(e, initialGrabPos, lastPos), e, 'stop') !== false) {
e.preventDefault()
e.stopImmediatePropagation()
}
lastPos = null
@ -317,7 +317,7 @@ export function usePointer(
function doMove(e: PointerEvent) {
if (trackedElement != null && initialGrabPos != null && lastPos != null) {
if (handler(computePosition(e, initialGrabPos, lastPos), e, 'move') !== false) {
e.preventDefault()
e.stopImmediatePropagation()
}
lastPos = new Vec2(e.clientX, e.clientY)
}
@ -339,7 +339,7 @@ export function usePointer(
initialGrabPos = new Vec2(e.clientX, e.clientY)
lastPos = initialGrabPos
if (handler(computePosition(e, initialGrabPos, lastPos), e, 'start') !== false) {
e.preventDefault()
e.stopImmediatePropagation()
}
}
},
@ -362,24 +362,8 @@ export function usePointer(
},
}
const stopEvents = {
pointerdown(e: PointerEvent) {
e.stopImmediatePropagation()
events.pointerdown(e)
},
pointerup(e: PointerEvent) {
e.stopImmediatePropagation()
events.pointerup(e)
},
pointermove(e: PointerEvent) {
e.stopImmediatePropagation()
events.pointermove(e)
},
}
return proxyRefs({
events,
stop: { events: stopEvents },
dragging,
})
}

View File

@ -3,7 +3,13 @@ import {
defineKeybinds,
normalizedKeyboardSegmentLookup,
} from '@/util/shortcuts'
import { expect, test, vi, type MockInstance } from 'vitest'
import { beforeAll, expect, test, vi, type MockInstance } from 'vitest'
// See https://github.com/thymikee/jest-preset-angular/issues/245#issuecomment-576296325
class MockPointerEvent extends MouseEvent {}
beforeAll(() => {
;(window as any).PointerEvent = MockPointerEvent
})
test.each([
{ keybind: 'A', expected: { modifiers: [], key: 'A' } },

View File

@ -415,7 +415,10 @@ export function defineKeybinds<
}
if (handled && stopAndPrevent) {
event.stopImmediatePropagation()
event.preventDefault()
// We don't prevent default on PointerEvents, because it may prevent emitting
// mousedown/mouseup events, on which external libraries may rely (like AGGrid for hiding
// context menu).
if (!(event instanceof PointerEvent)) event.preventDefault()
}
return handled
}