@@ -50,6 +50,9 @@ async function fetchKanjiFromJisho(reading: string): Promise<string[]> {
5050
5151 const proxyUrl = JISHO_PROXY_BASE + jishoTargetUrl ;
5252
53+ const hiragana = wanakana . toHiragana ( reading ) ;
54+ const katakana = wanakana . toKatakana ( reading ) ;
55+
5356 try {
5457 const res = await fetch ( proxyUrl ) ;
5558
@@ -63,21 +66,22 @@ async function fetchKanjiFromJisho(reading: string): Promise<string[]> {
6366 } catch ( e ) {
6467 console . error ( "Could not read error response text:" , e ) ;
6568 }
66- return [ ] ;
69+ return [ hiragana , katakana ] ;
6770 }
6871
6972 const json = ( await res . json ( ) ) as JishoResponse ;
7073
7174 if ( ! json ?. data ) {
72- return [ ] ;
75+ return [ hiragana , katakana ] ;
7376 }
7477
7578 const uniqueWords = new Set ( json . data . map ( ( e ) => e . japanese [ 0 ] . word || e . japanese [ 0 ] . reading ) ) ;
7679
77- return Array . from ( uniqueWords ) ;
80+ const results = [ hiragana , katakana , ...Array . from ( uniqueWords ) ] ;
81+ return [ ...new Set ( results ) ] ;
7882 } catch ( error ) {
7983 console . error ( "Error in fetchKanjiFromJisho:" , error ) ;
80- return [ ] ;
84+ return [ hiragana , katakana ] ;
8185 }
8286}
8387
@@ -101,8 +105,8 @@ export function IMEField() {
101105 const [ lastConversion , setLastConversion ] = createSignal < LastConversion | null > ( null ) ;
102106
103107 let ta : HTMLTextAreaElement | undefined ;
104- let itemRefs : HTMLDivElement [ ] = [ ] ;
105108 let listRef : HTMLDivElement | undefined ;
109+ let itemRefs : HTMLDivElement [ ] = [ ] ;
106110
107111 const confirmedText = createMemo ( ( ) => input ( ) . slice ( 0 , confirmedIndex ( ) ) ) ;
108112 const unconfirmedText = createMemo ( ( ) => input ( ) . slice ( confirmedIndex ( ) ) ) ;
@@ -125,6 +129,27 @@ export function IMEField() {
125129 setSelectedIndex ( 0 ) ;
126130 } ) ;
127131
132+ createEffect ( ( ) => {
133+ const index = selectedIndex ( ) ;
134+ if ( ! isMenuOpen ( ) || ! listRef || itemRefs . length === 0 ) return ;
135+
136+ const item = itemRefs [ index ] ;
137+ const container = listRef ;
138+
139+ if ( item && container ) {
140+ const itemTop = item . offsetTop ;
141+ const itemBottom = itemTop + item . offsetHeight ;
142+ const containerTop = container . scrollTop ;
143+ const containerHeight = container . clientHeight ;
144+
145+ if ( itemBottom > containerTop + containerHeight ) {
146+ container . scrollTop = itemBottom - containerHeight ;
147+ } else if ( itemTop < containerTop ) {
148+ container . scrollTop = itemTop ;
149+ }
150+ }
151+ } ) ;
152+
128153 function commitSuggestion ( idx : number ) {
129154 const val = input ( ) ;
130155 const start = compositionStart ( ) ;
@@ -161,31 +186,6 @@ export function IMEField() {
161186 }
162187 ) {
163188 if ( isMenuOpen ( ) ) {
164- const len = suggestions ( ) . length ;
165- if ( len > 0 && ( e . key === "ArrowDown" || e . key === "ArrowUp" ) ) {
166- e . preventDefault ( ) ;
167- const delta = e . key === "ArrowDown" ? 1 : - 1 ;
168- const newIndex = ( selectedIndex ( ) + delta + len ) % len ;
169- setSelectedIndex ( newIndex ) ;
170- const item = itemRefs [ newIndex ] ;
171- const container = listRef ;
172- if ( item && container ) {
173- const itop = item . offsetTop ;
174- const ibot = itop + item . offsetHeight ;
175- const ctop = container . scrollTop ;
176- const cheight = container . clientHeight ;
177- if ( ibot > ctop + cheight ) {
178- container . scrollTop = ibot - cheight ;
179- } else if ( itop < ctop ) {
180- container . scrollTop = itop ;
181- }
182- }
183- return ;
184- }
185- if ( e . key === "Enter" || e . key === " " ) {
186- e . preventDefault ( ) ;
187- commitSuggestion ( selectedIndex ( ) ) ;
188- }
189189 return ;
190190 }
191191
@@ -220,32 +220,18 @@ export function IMEField() {
220220 return ;
221221 }
222222
223- if ( e . key === " " && e . shiftKey && isComposing ( ) ) {
224- e . preventDefault ( ) ;
223+ if ( e . key === " " && isComposing ( ) ) {
225224 const start = confirmedIndex ( ) ;
226225 const pos = e . currentTarget . selectionStart ;
227226 const reading = input ( ) . slice ( start , pos ) ;
228- if ( wanakana . isHiragana ( reading ) ) {
229- const kata = wanakana . toKatakana ( reading ) ;
230- const before = input ( ) . slice ( 0 , start ) ;
231- const after = input ( ) . slice ( pos ) ;
232- const newVal = before + kata + after ;
233- setInput ( newVal ) ;
234- const end = before . length + kata . length ;
235- if ( ta ) {
236- ta . value = newVal ;
237- ta . setSelectionRange ( end , end ) ;
238- }
239- setLastConversion ( {
240- confirmed : kata ,
241- reading,
242- start,
243- end,
244- } ) ;
245- setConfirmedIndex ( end ) ;
246- setIsComposing ( false ) ;
227+
228+ if ( wanakana . isHiragana ( reading ) && reading . length ) {
229+ e . preventDefault ( ) ;
230+ setCompositionStart ( start ) ;
231+ setLookupReading ( reading ) ;
232+ setSelectedIndex ( 0 ) ;
233+ setIsMenuOpen ( true ) ;
247234 }
248- return ;
249235 }
250236 }
251237
@@ -258,18 +244,6 @@ export function IMEField() {
258244 setInput ( val ) ;
259245 setIsComposing ( val . length > confirmedIndex ( ) ) ;
260246 setLastConversion ( null ) ;
261-
262- if ( e . inputType === "insertText" && e . data === " " && isComposing ( ) ) {
263- const start = confirmedIndex ( ) ;
264- const pos = e . currentTarget . selectionStart ;
265- const reading = val . slice ( start , pos - 1 ) ;
266- if ( wanakana . isHiragana ( reading ) && reading . length ) {
267- setCompositionStart ( start ) ;
268- setLookupReading ( reading ) ;
269- setSelectedIndex ( 0 ) ;
270- setIsMenuOpen ( true ) ;
271- }
272- }
273247 }
274248
275249 function handleCompositionStart (
@@ -319,6 +293,9 @@ export function IMEField() {
319293 onCompositionStart = { handleCompositionStart }
320294 onCompositionEnd = { handleCompositionEnd }
321295 class = "caret-foreground bg-transparent text-transparent"
296+ autocorrect = "off"
297+ autocapitalize = "off"
298+ spellcheck = { false }
322299 />
323300 </ div >
324301 </ TextField >
@@ -327,20 +304,19 @@ export function IMEField() {
327304 onCloseAutoFocus = { ( e ) => {
328305 e . preventDefault ( ) ;
329306 ta ?. focus ( ) ;
330- } }
331- class = "w-[var(--kb-popper-content-width)]" >
307+ } } >
332308 < Suspense fallback = { < Spinner /> } >
333309 < Show
334310 when = { suggestions ( ) ?. length > 0 }
335311 fallback = {
336312 < div class = "text-muted-foreground px-2 py-1.5 text-sm" > No results found.</ div >
337313 } >
338314 < >
339- < div ref = { listRef } class = "max-h-[13rem ] overflow-y-auto" >
315+ < div ref = { listRef } class = "max-h-[10rem ] overflow-y-auto" >
340316 < For each = { suggestions ( ) } >
341317 { ( s , idx ) => (
342318 < DropdownMenuItem
343- ref = { ( el ) => ( itemRefs [ idx ( ) ] = el ! ) }
319+ ref = { ( el ) => ( itemRefs [ idx ( ) ] = el ) }
344320 onSelect = { ( ) => commitSuggestion ( idx ( ) ) }
345321 onFocus = { ( ) => setSelectedIndex ( idx ( ) ) }
346322 data-highlighted = { selectedIndex ( ) === idx ( ) }
0 commit comments