@@ -2,6 +2,7 @@ import createToInput from '@scripts/creators/createToInput';
22import { show } from '@scripts/methods' ;
33import canOpenOnFocus from '@scripts/utils/canOpenOnFocus' ;
44import setContext from '@scripts/utils/setContext' ;
5+ import { clearSkipOpenOnFocus , shouldSkipOpenOnFocus } from '@scripts/utils/skipOpenOnFocus' ;
56import type { Calendar } from '@src/index' ;
67
78const handleInput = ( self : Calendar ) => {
@@ -20,6 +21,10 @@ const handleInput = (self: Calendar) => {
2021 const shouldHandleFocus = typeof self . openOnFocus === 'function' || self . openOnFocus === true ;
2122
2223 const handleOpenOnFocus = ( ) => {
24+ if ( shouldSkipOpenOnFocus ( self ) ) {
25+ clearSkipOpenOnFocus ( self ) ;
26+ return ;
27+ }
2328 if ( ! canOpenOnFocus ( self ) ) return ;
2429 handleOpenCalendar ( ) ;
2530 } ;
@@ -28,12 +33,46 @@ const handleInput = (self: Calendar) => {
2833 ( self . context . inputElement as HTMLInputElement ) . addEventListener ( 'focus' , handleOpenOnFocus ) ;
2934 }
3035
36+ const focusIntoCalendar = ( event : KeyboardEvent ) => {
37+ if ( ! self . context . isShowInInputMode ) return false ;
38+ if ( document . activeElement !== self . context . inputElement ) return false ;
39+
40+ const isFocusable = ( el : HTMLElement ) => el . tabIndex >= 0 && ! el . hasAttribute ( 'disabled' ) && el . getAttribute ( 'aria-disabled' ) !== 'true' ;
41+
42+ const walker = document . createTreeWalker ( self . context . mainElement , NodeFilter . SHOW_ELEMENT , {
43+ acceptNode : ( node ) => {
44+ const el = node as HTMLElement ;
45+ if ( ! isFocusable ( el ) ) return NodeFilter . FILTER_SKIP ;
46+ return NodeFilter . FILTER_ACCEPT ;
47+ } ,
48+ } ) ;
49+
50+ const focusTarget = ( walker . nextNode ( ) as HTMLElement | null ) ?? ( isFocusable ( self . context . mainElement ) ? self . context . mainElement : null ) ;
51+
52+ if ( ! focusTarget || focusTarget . tabIndex < 0 ) return false ;
53+
54+ event . preventDefault ( ) ;
55+ focusTarget . focus ( ) ;
56+ return true ;
57+ } ;
58+
59+ const handleKeyIntoCalendar = ( event : KeyboardEvent ) => {
60+ const isTab = event . key === 'Tab' && ! event . shiftKey ;
61+ const isArrow = [ 'ArrowUp' , 'ArrowDown' , 'ArrowLeft' , 'ArrowRight' ] . includes ( event . key ) ;
62+ if ( ! isTab && ! isArrow ) return ;
63+ focusIntoCalendar ( event ) ;
64+ } ;
65+
66+ ( self . context . inputElement as HTMLInputElement ) . addEventListener ( 'keydown' , handleKeyIntoCalendar ) ;
67+
3168 return ( ) => {
3269 ( self . context . inputElement as HTMLInputElement ) . removeEventListener ( 'click' , handleOpenCalendar ) ;
3370
3471 if ( shouldHandleFocus ) {
3572 ( self . context . inputElement as HTMLInputElement ) . removeEventListener ( 'focus' , handleOpenOnFocus ) ;
3673 }
74+
75+ ( self . context . inputElement as HTMLInputElement ) . removeEventListener ( 'keydown' , handleKeyIntoCalendar ) ;
3776 } ;
3877} ;
3978
0 commit comments