Skip to content

Commit 760f1ba

Browse files
committed
🔮
1 parent c8907ac commit 760f1ba

File tree

1 file changed

+39
-40
lines changed

1 file changed

+39
-40
lines changed

‎packages/components/calendar/src/select-day.ts‎

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)