@@ -5,6 +5,7 @@ import { scheduleOnce } from '@ember/runloop';
55import service from '../../-private/service.ts' ;
66import {
77 add ,
8+ formatDate ,
89 getWeekdays ,
910 getWeekdaysMin ,
1011 getWeekdaysShort ,
@@ -35,9 +36,11 @@ import type {
3536 PowerCalendarDaysArgs ,
3637 PowerCalendarDaysSignature ,
3738} from '../power-calendar/days.ts' ;
39+ import { modifier } from 'ember-modifier' ;
3840
3941interface PowerCalendarMultipleDaysArgs
40- extends Omit < PowerCalendarDaysArgs , 'selected' > {
42+ extends Omit < PowerCalendarDaysArgs , 'calendar' | 'selected' > {
43+ calendar : PowerCalendarMultipleAPI ;
4144 selected ?: Date [ ] ;
4245 maxLength ?: number ;
4346}
@@ -52,6 +55,8 @@ export default class PowerCalendarMultipleDaysComponent extends Component<PowerC
5255
5356 @tracked focusedId : string | null = null ;
5457
58+ didSetup = false ;
59+
5560 get weekdayFormat ( ) : TWeekdayFormat {
5661 return this . args . weekdayFormat || 'short' ; // "min" | "short" | "long"
5762 }
@@ -151,11 +156,48 @@ export default class PowerCalendarMultipleDaysComponent extends Component<PowerC
151156 }
152157
153158 @action
154- handleKeyDown ( e : KeyboardEvent ) : void {
159+ async handleKeyDown ( e : KeyboardEvent ) : Promise < void > {
155160 const day = handleDayKeyDown ( e , this . focusedId , this . days ) ;
161+
162+ if ( ! day || ! day ?. isCurrentMonth ) {
163+ if ( this . args . calendar . actions . moveCenter ) {
164+ if (
165+ e . key === 'ArrowUp' ||
166+ e . key === 'ArrowRight' ||
167+ e . key === 'ArrowDown' ||
168+ e . key === 'ArrowLeft'
169+ ) {
170+ const currentDay = this . days . find (
171+ ( x ) => x . id === this . focusedId ,
172+ ) ?. date ;
173+
174+ if ( currentDay ) {
175+ let date = currentDay ;
176+ let step = 1 ;
177+ if ( e . key === 'ArrowUp' ) {
178+ date = add ( currentDay , - 7 , 'day' ) ;
179+ step = - 1 ;
180+ } else if ( e . key === 'ArrowLeft' ) {
181+ date = add ( currentDay , - 1 , 'day' ) ;
182+ step = - 1 ;
183+ } else if ( e . key === 'ArrowRight' ) {
184+ date = add ( currentDay , 1 , 'day' ) ;
185+ } else if ( e . key === 'ArrowDown' ) {
186+ date = add ( currentDay , 7 , 'day' ) ;
187+ }
188+
189+ await this . focusDay ( e , date , step ) ;
190+
191+ return ;
192+ }
193+ }
194+ }
195+ }
196+
156197 if ( ! day ) {
157198 return ;
158199 }
200+
159201 this . focusedId = day . id ;
160202 scheduleOnce (
161203 'afterRender' ,
@@ -171,6 +213,82 @@ export default class PowerCalendarMultipleDaysComponent extends Component<PowerC
171213 handleClick ( e , this . days , this . args . calendar ) ;
172214 }
173215
216+ setup = modifier (
217+ ( ) => {
218+ if ( this . didSetup ) {
219+ return ;
220+ }
221+
222+ this . didSetup = true ;
223+
224+ if ( this . args . autofocus ) {
225+ scheduleOnce ( 'afterRender' , this , this . initialFocus . bind ( this ) ) ;
226+ }
227+ } ,
228+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
229+ // @ts -ignore
230+ { eager : false } ,
231+ ) ;
232+
233+ initialFocus ( ) {
234+ const activeDay = this . days . find ( ( x ) => x . isSelected && ! x . isDisabled ) ;
235+
236+ if ( activeDay ) {
237+ this . focusedId = activeDay . id ;
238+ } else {
239+ const todayDay = this . days . find ( ( x ) => x . isToday && ! x . isDisabled ) ;
240+ if ( todayDay ) {
241+ this . focusedId = todayDay . id ?? '' ;
242+ } else {
243+ const firstSelectableDay = this . days . find ( ( x ) => ! x . isDisabled ) ;
244+ if ( firstSelectableDay ) {
245+ this . focusedId = firstSelectableDay . id ?? '' ;
246+ } else {
247+ this . focusedId = this . days . find ( ( x ) => ! x . isCurrentMonth ) ?. id ?? '' ;
248+ }
249+ }
250+ }
251+
252+ focusDate ( this . args . calendar . uniqueId , this . focusedId ?? '' ) ;
253+ }
254+
255+ async focusDay ( e : MouseEvent | KeyboardEvent , date : Date , step : number = 0 ) {
256+ if (
257+ dayIsDisabled (
258+ date ,
259+ this . args . calendar ,
260+ this . args . minDate ,
261+ this . args . maxDate ,
262+ this . args . disabledDates ,
263+ )
264+ ) {
265+ return ;
266+ }
267+
268+ if ( this . args . calendar . actions . moveCenter && step !== 0 ) {
269+ await this . args . calendar . actions . moveCenter (
270+ step ,
271+ 'month' ,
272+ this . args . calendar ,
273+ e ,
274+ ) ;
275+ }
276+
277+ this . focusedId = formatDate ( date , 'YYYY-MM-DD' ) ;
278+
279+ if ( step !== 0 ) {
280+ scheduleOnce (
281+ 'afterRender' ,
282+ this ,
283+ focusDate ,
284+ this . args . calendar . uniqueId ,
285+ this . focusedId ?? '' ,
286+ ) ;
287+ } else {
288+ focusDate ( this . args . calendar . uniqueId , this . focusedId ?? '' ) ;
289+ }
290+ }
291+
174292 // Methods
175293 dayIsSelected ( date : Date , calendar : CalendarAPI = this . args . calendar ) {
176294 const selected = ( calendar as PowerCalendarMultipleAPI ) . selected || [ ] ;
0 commit comments