@@ -20,9 +20,13 @@ const searchTerm: Ref<string> = ref('');
2020useMagicKeys ({
2121 passive: false ,
2222 onEventFired(event ) {
23- if (event .key === ' f' && event .ctrlKey ) {
24- event .preventDefault ();
25- focus (' searchBar' );
23+ if (event .key === ' f' && (event .ctrlKey || event .metaKey )) {
24+ const fromAce = (window as any ).__fromAceEditor ;
25+ const searchBarFocused = document .activeElement ?.id === ' searchBar' ;
26+ if (fromAce || searchBarFocused ) {
27+ event .preventDefault ();
28+ focus (' searchBar' );
29+ }
2630 }
2731 },
2832});
@@ -61,10 +65,40 @@ const showSearchResultsMenu = event => {
6165 searchResultMenu .value ?.show (event , event .target );
6266 focus (' searchBar' );
6367};
68+ import {computed } from ' vue' ;
69+ let mode = useSessionStore ().currentMode ;
70+ let session = getSessionForMode (mode );
71+ const currentIndex = computed (() => {
72+ if (! session .currentSelectedElement .value || session .currentSearchResults .value .length === 0 )
73+ return 0 ;
74+ return (
75+ session .currentSearchResults .value .findIndex (
76+ r => r .path === session .currentSelectedElement .value
77+ ) + 1
78+ ); // +1 for 1-based index
79+ });
80+ const totalMatches = computed (() => session .currentSearchResults .value .length );
81+
82+ function goNext() {
83+ const results = session .currentSearchResults .value ;
84+ if (results .length === 0 ) return ;
85+
86+ const idx = results .findIndex (r => r .path === session .currentSelectedElement .value );
87+ const nextIdx = (idx + 1 ) % results .length ;
88+ session .currentSelectedElement .value = results [nextIdx ].path ;
89+ }
90+ function goPrev() {
91+ const results = session .currentSearchResults .value ;
92+ if (results .length === 0 ) return ;
93+
94+ const idx = results .findIndex (r => r .path === session .currentSelectedElement .value );
95+ const prevIdx = (idx - 1 + results .length ) % results .length ;
96+ session .currentSelectedElement .value = results [prevIdx ].path ;
97+ }
6498 </script >
6599
66100<template >
67- <span class =" p-input-icon-left ml-5" style =" width : 14rem " >
101+ <span class =" p-input-icon-left ml-5 flex items-center " style =" width : 14rem " >
68102 <i class =" pi" style =" font-size : 0.9rem " />
69103 <InputText
70104 show-clear
@@ -75,6 +109,25 @@ const showSearchResultsMenu = event => {
75109 @blur =" () => searchResultMenu.value?.hide()"
76110 id =" searchBar" />
77111 </span >
112+ <div class =" search-controls" v-if =" searchTerm" >
113+ <span class =" search-counter ml-1" >{{ currentIndex }}/{{ totalMatches }}</span >
114+ <Button
115+ v-tooltip.bottom =" 'Previous match'"
116+ class =" ml-1 p-button-sm search-nav-btn"
117+ text
118+ :disabled =" totalMatches === 0"
119+ @click =" goPrev" >
120+ <i class =" pi pi-chevron-up" />
121+ </Button >
122+ <Button
123+ v-tooltip.bottom =" 'Next match'"
124+ class =" p-button-sm search-nav-btn"
125+ text
126+ :disabled =" totalMatches === 0"
127+ @click =" goNext" >
128+ <i class =" pi pi-chevron-down" />
129+ </Button >
130+ </div >
78131 <!-- search results menu -->
79132 <Menu :popup =" true" ref =" searchResultMenu" :model =" searchResultItems" >
80133 <template #item =" slotProps " >
@@ -90,6 +143,30 @@ const showSearchResultsMenu = event => {
90143</template >
91144
92145<style scoped>
146+ .search-nav-btn {
147+ min-width : 1.6rem ;
148+ height : 1.6rem ;
149+ padding : 0 !important ;
150+ font-size : 0.75rem ;
151+ color : var (--p-primary-active-color );
152+ }
153+ .search-nav-btn :hover:enabled {
154+ background-color : var (--surface-hover );
155+ }
156+ .search-nav-btn :disabled {
157+ opacity : 0.5 ;
158+ cursor : not-allowed ;
159+ }
160+ .search-counter {
161+ font-size : 0.85rem ;
162+ color : var (--text-color );
163+ }
164+ .search-controls {
165+ display : flex ;
166+ align-items : center ;
167+ gap : 0.35rem ;
168+ margin-left : 0.5rem ;
169+ }
93170.toolbar-button {
94171 font-weight : bold ;
95172 font-size : large ;
0 commit comments