@@ -51,30 +51,37 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
5151 * Use a resize observer as a cross browser solution to know when to initialize the intersection observer
5252 * and also to know when to center the current month in the scroller during initialization.
5353 */
54- #resizeObserver = new ResizeObserver ( ( ) => {
54+ #resizeObserver = new ResizeObserver ( async ( ) => {
5555 if ( ! this . #intersectionObserver) {
5656 this . #intersectionObserver = new IntersectionObserver (
5757 entries => {
5858 entries
5959 . filter ( entry => entry . isIntersecting )
6060 . forEach ( entry => {
6161 if ( entry . intersectionRatio >= 0.5 ) {
62- const monthView = entry . target as MonthView ;
62+ const monthView = entry . target as MonthView ,
63+ displayMonth = normalizeDateTime ( monthView . month ) ;
6364
64- // Make sure the header reflects the currently visible month
65- this . displayMonth = normalizeDateTime ( monthView . month ) ;
65+ // Do not trigger unnecessary renders
66+ if ( ! isSameDate ( this . displayMonth , displayMonth ) ) {
67+ this . displayMonth = displayMonth ;
68+ }
6669 }
6770 } ) ;
6871 } ,
6972 { root : this . scroller , threshold : [ 0 , 0.5 , 1 ] }
7073 ) ;
7174
75+ // Firefox only: wait for the scroller and month views to be rendered
76+ await new Promise ( requestAnimationFrame ) ;
77+ await new Promise ( requestAnimationFrame ) ;
78+
79+ // Center the current month initially
80+ this . #scrollToMonth( 0 ) ;
81+
7282 // Start observing month views
7383 this . #observedMonths = this . renderRoot . querySelectorAll ( 'sl-month-view' ) ;
7484 this . #observedMonths. forEach ( mv => this . #intersectionObserver?. observe ( mv ) ) ;
75-
76- // Center the current month initially
77- void this . #scrollToMonth( 0 ) ;
7885 }
7986 } ) ;
8087
@@ -189,21 +196,21 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
189196 this . previousMonth = new Date ( this . month . getFullYear ( ) , this . month . getMonth ( ) - 1 ) ;
190197 }
191198
192- if ( changes . has ( 'max' ) || changes . has ( 'min' ) || changes . has ( 'month' ) ) {
193- this . #observedMonths?. forEach ( mv => this . #intersectionObserver?. unobserve ( mv ) ) ;
194- this . #observedMonths = undefined ;
195- }
199+ // if (changes.has('max') || changes.has('min') || changes.has('month')) {
200+ // this.#observedMonths?.forEach(mv => this.#intersectionObserver?.unobserve(mv));
201+ // this.#observedMonths = undefined;
202+ // }
196203 }
197204
198205 override updated ( changes : PropertyValues < this> ) : void {
199206 super . updated ( changes ) ;
200207
201- if ( changes . has ( 'max' ) || changes . has ( 'min' ) || changes . has ( 'month' ) ) {
202- void this . #scrollToMonth( 0 ) . then ( ( ) => {
203- this . #observedMonths = this . renderRoot . querySelectorAll ( 'sl-month-view' ) ;
204- this . #observedMonths. forEach ( mv => this . #intersectionObserver ?. observe ( mv ) ) ;
205- } ) ;
206- }
208+ // if (changes.has('max') || changes.has('min') || changes.has('month')) {
209+ // this.#scrollToMonth(0);
210+
211+ // this.#observedMonths = this.renderRoot.querySelectorAll('sl-month-view' );
212+ // this.#observedMonths.forEach(mv => this.#intersectionObserver?.observe(mv) );
213+ // }
207214 }
208215
209216 override render ( ) : TemplateResult {
@@ -359,9 +366,6 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
359366 }
360367
361368 #onChange( event : SlChangeEvent < Date > ) : void {
362- event . preventDefault ( ) ;
363- event . stopPropagation ( ) ;
364-
365369 const newMonth = new Date ( event . detail . getFullYear ( ) , event . detail . getMonth ( ) ) ;
366370
367371 // Check if the new month is within min/max boundaries
@@ -387,14 +391,12 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
387391 }
388392
389393 #onPrevious( ) : void {
390- void this . #scrollToMonth( - 1 , true ) ;
391-
394+ this . #scrollToMonth( - 1 , true ) ;
392395 this . #announce( this . previousMonth ) ;
393396 }
394397
395398 #onNext( ) : void {
396- void this . #scrollToMonth( 1 , true ) ;
397-
399+ this . #scrollToMonth( 1 , true ) ;
398400 this . #announce( this . nextMonth ) ;
399401 }
400402
@@ -403,20 +405,25 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
403405 return ;
404406 }
405407
406- // Unobserve the "old" month views
408+ // Stop observing month views while we adjust the scroll position
407409 this . #observedMonths?. forEach ( mv => this . #intersectionObserver?. unobserve ( mv ) ) ;
408410 this . #observedMonths = undefined ;
409411
410412 // Update the month, so it rerenders the month-views
411413 this . month = normalizeDateTime ( this . displayMonth ) ;
412414
413- // Wait for the month views to rerender; do NOT scroll before this is done
414- await this . updateComplete ;
415+ if ( 'onscrollend' in this . scroller ! ) {
416+ await this . updateComplete ;
417+ } else {
418+ // Safari <= 26 only: wait for the scroller and month views to be rendered
419+ await new Promise ( requestAnimationFrame ) ;
420+ await new Promise ( requestAnimationFrame ) ;
421+ }
415422
416423 // Now instantly scroll back to the center month (so the user doesn't notice)
417- await this . #scrollToMonth( 0 ) ;
424+ this . #scrollToMonth( 0 ) ;
418425
419- // Observe the new month views
426+ // Start observing month views again
420427 this . #observedMonths = this . renderRoot . querySelectorAll ( 'sl-month-view' ) ;
421428 this . #observedMonths. forEach ( mv => this . #intersectionObserver?. observe ( mv ) ) ;
422429 }
@@ -486,7 +493,7 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
486493 return previousMonthNormalized >= minMonthNormalized ;
487494 }
488495
489- async #scrollToMonth( month : - 1 | 0 | 1 , smooth = false ) : Promise < void > {
496+ #scrollToMonth( month : - 1 | 0 | 1 , smooth = false ) : void {
490497 if ( ! this . scroller ) {
491498 return ;
492499 }
@@ -520,16 +527,8 @@ export class SelectDay extends LocaleMixin(ScopedElementsMixin(LitElement)) {
520527
521528 if ( smooth ) {
522529 this . scroller . scrollTo ( { left, behavior : 'smooth' } ) ;
523- } else if ( left !== this . scroller . scrollLeft ) {
524- const scrollendPromise = new Promise < void > ( resolve => {
525- this . scroller ?. addEventListener ( 'scrollend' , ( ) => resolve ( ) , { once : true } ) ;
526- } ) ;
527-
528- this . scroller . scrollTo ( { left, behavior : 'instant' } ) ;
529-
530- // Wait for the scroll to finish before continuing: this is important to avoid
531- // the intersection observer triggering too early and messing up the displayMonth
532- await scrollendPromise ;
530+ } else if ( this . scroller . scrollLeft !== left ) {
531+ this . scroller . scrollLeft = left ;
533532 }
534533 }
535534}
0 commit comments