|
212 | 212 | <script lang="ts" setup> |
213 | 213 | import { useWindowSize, watchDebounced } from "@vueuse/core"; |
214 | 214 | import { NPerformantEllipsis, NVirtualList } from "naive-ui"; |
215 | | -import { nextTick, ref } from "vue"; |
| 215 | +import { nextTick, onMounted, onUnmounted, ref } from "vue"; |
216 | 216 | import { type ComposedDatabase, DEBOUNCE_SEARCH_DELAY } from "@/types"; |
217 | 217 | import type { MaskingReason } from "@/types/proto-es/v1/sql_service_pb"; |
218 | 218 | import { type QueryRow } from "@/types/proto-es/v1/sql_service_pb"; |
@@ -351,6 +351,35 @@ watchDebounced( |
351 | 351 | { debounce: DEBOUNCE_SEARCH_DELAY } |
352 | 352 | ); |
353 | 353 |
|
| 354 | +// Handle shift+wheel for horizontal scrolling |
| 355 | +// Use capture phase to intercept before NVirtualList handles it |
| 356 | +const handleWheel = (event: WheelEvent) => { |
| 357 | + const container = containerRef.value; |
| 358 | + if (!container) return; |
| 359 | +
|
| 360 | + // Only handle shift+wheel when there's horizontal overflow |
| 361 | + const hasHorizontalOverflow = container.scrollWidth > container.clientWidth; |
| 362 | + if (!event.shiftKey || !hasHorizontalOverflow) return; |
| 363 | +
|
| 364 | + event.preventDefault(); |
| 365 | + event.stopPropagation(); |
| 366 | + container.scrollLeft += event.deltaY || event.deltaX; |
| 367 | +}; |
| 368 | +
|
| 369 | +onMounted(() => { |
| 370 | + // Use capture phase to intercept before NVirtualList |
| 371 | + containerRef.value?.addEventListener("wheel", handleWheel, { |
| 372 | + passive: false, |
| 373 | + capture: true, |
| 374 | + }); |
| 375 | +}); |
| 376 | +
|
| 377 | +onUnmounted(() => { |
| 378 | + containerRef.value?.removeEventListener("wheel", handleWheel, { |
| 379 | + capture: true, |
| 380 | + }); |
| 381 | +}); |
| 382 | +
|
354 | 383 | defineExpose({ |
355 | 384 | scrollTo: (index: number) => |
356 | 385 | virtualListRef.value?.scrollTo({ |
|
0 commit comments