diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index 8f3255ad9a..0c87d17698 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -74,6 +74,7 @@ import { isExecuteSqlInNewResultTabShortcut, isExecuteSqlShortcut, isFocusSearchShortcut, + isGoToColumnShortcut, isModRShortcut, handleTabHistoryNavigationShortcut, isNewQueryShortcut, @@ -2570,8 +2571,17 @@ async function handleKeydown(e: KeyboardEvent) { if (e.defaultPrevented) return; const shortcuts = settingsStore.editorSettings.shortcuts; - const tabSwitcherDirection = tabSwitcherDirectionFromShortcut(e, shortcuts); if (showTabSwitcher.value) return; + // Grid-scoped shortcuts normally win inside DataGrid. Keep that precedence + // for a data tab even when focus is in a sibling input, where the grid's + // local listener intentionally leaves native editing untouched. + if (isGoToColumnShortcut(e, shortcuts) && contentAreaRef.value?.openGoToColumn()) { + e.preventDefault(); + e.stopPropagation(); + return; + } + + const tabSwitcherDirection = tabSwitcherDirectionFromShortcut(e, shortcuts); if (tabSwitcherDirection) { e.preventDefault(); e.stopPropagation(); diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 7e0b4323fb..de25021b90 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -2547,6 +2547,9 @@ let highlightedColumnTimer = 0; const goToColumnOpen = ref(false); const goToColumnSearch = ref(""); +const goToColumnSearchInput = ref(); +const goToColumnListRef = ref(); +const goToColumnSelectedIndex = ref(0); const columnOrderKeys = computed(() => uniqueDataGridColumnOrderKeys(props.result.columns, props.sourceColumns)); const resolvedColumnLayoutScopeKey = computed( () => @@ -2731,15 +2734,76 @@ function scrollToColumn(columnIndex: number) { gridRef.value?.focus(); } +function focusGoToColumnSearch() { + goToColumnSearchInput.value?.focus(); +} + +function scrollGoToColumnSelectionIntoView() { + void nextTick(() => { + goToColumnListRef.value?.querySelectorAll("button")[goToColumnSelectedIndex.value]?.scrollIntoView({ block: "nearest" }); + }); +} + +function openGoToColumn(): boolean { + if (!displayableColumnIndexes.value.length) return false; + + const alreadyOpen = goToColumnOpen.value; + goToColumnSearch.value = ""; + goToColumnSelectedIndex.value = 0; + goToColumnOpen.value = true; + if (alreadyOpen) void nextTick(focusGoToColumnSearch); + return true; +} + +function moveGoToColumnSelection(delta: number) { + const count = filteredGoToColumns.value.length; + if (!count) return; + goToColumnSelectedIndex.value = (goToColumnSelectedIndex.value + delta + count) % count; + scrollGoToColumnSelectionIntoView(); +} + function onGoToColumnKeydown(event: KeyboardEvent) { - if (event.key === "Escape") { + if (event.key === "ArrowDown") { + event.preventDefault(); + event.stopPropagation(); + moveGoToColumnSelection(1); + } else if (event.key === "ArrowUp") { + event.preventDefault(); + event.stopPropagation(); + moveGoToColumnSelection(-1); + } else if (event.key === "Enter") { + const selected = filteredGoToColumns.value[goToColumnSelectedIndex.value]; + if (!selected) return; + event.preventDefault(); + event.stopPropagation(); + scrollToColumn(selected.index); + } else if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); goToColumnOpen.value = false; goToColumnSearch.value = ""; } } watch(goToColumnOpen, (open) => { - if (!open) goToColumnSearch.value = ""; + if (!open) { + goToColumnSearch.value = ""; + return; + } + goToColumnSelectedIndex.value = 0; + void nextTick(() => { + focusGoToColumnSearch(); + scrollGoToColumnSelectionIntoView(); + }); +}); + +watch(goToColumnSearch, () => { + goToColumnSelectedIndex.value = 0; + scrollGoToColumnSelectionIntoView(); +}); + +watch(filteredGoToColumns, (columns) => { + if (goToColumnSelectedIndex.value >= columns.length) goToColumnSelectedIndex.value = Math.max(columns.length - 1, 0); }); function matchesTableInfoColumn(resultColumn: string, sourceColumn: string | undefined, columnName: string): boolean { @@ -9355,14 +9419,13 @@ async function onGridKeydown(event: KeyboardEvent) { openTableStructureEditor(); return; } - if (!targetAllowsNativeClipboard && displayableColumnIndexes.value.length > 0 && isGoToColumnShortcut(event, settingsStore.editorSettings.shortcuts)) { + if (!targetAllowsNativeClipboard && isGoToColumnShortcut(event, settingsStore.editorSettings.shortcuts) && openGoToColumn()) { event.preventDefault(); event.stopPropagation(); - goToColumnOpen.value = true; return; } if (!targetAllowsNativeClipboard && handleGridPaginationShortcut(event)) return; - if (isFocusSearchShortcut(event)) { + if (isFocusSearchShortcut(event) && !isGoToColumnShortcut(event, settingsStore.editorSettings.shortcuts)) { event.preventDefault(); focusSearch(); return; @@ -11721,6 +11784,7 @@ defineExpose({ setMultiRowTranspose, toggleMultiRowTranspose, focusSearch, + openGoToColumn, visibleColumnCount, displayableColumnCount, hiddenColumnCount, @@ -12292,13 +12356,23 @@ function openGridSnapshot() {
- +
-
-