Skip to content

Commit

Permalink
refactor: add focusElement() helper
Browse files Browse the repository at this point in the history
  • Loading branch information
motss committed May 30, 2021
1 parent 24ae97f commit f07c919
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 16 deletions.
24 changes: 20 additions & 4 deletions src/date-picker/date-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { calendarViews,MAX_DATE } from '../constants.js';
import { adjustOutOfRangeValue } from '../helpers/adjust-out-of-range-value.js';
import { dateValidator } from '../helpers/date-validator.js';
import { dispatchCustomEvent } from '../helpers/dispatch-custom-event.js';
import { focusElement } from '../helpers/focus-element.js';
import { isInTargetMonth } from '../helpers/is-in-current-month.js';
import { splitString } from '../helpers/split-string.js';
import { toDateString } from '../helpers/to-date-string.js';
Expand Down Expand Up @@ -60,10 +61,17 @@ export class DatePicker extends DatePickerMixin(DatePickerMinMaxMixin(LitElement

//#region private properties
#formatters: Formatters;
#shouldUpdateFocusInNavigationButtons = false;

@queryAsync('.month-dropdown')
private readonly _monthDropdown!: Promise<HTMLButtonElement | null>;

@queryAsync('[data-navigation="previous"]')
private readonly _navigationPrevious!: Promise<HTMLButtonElement | null>;

@queryAsync('[data-navigation="next"]')
private readonly _navigationNext!: Promise<HTMLButtonElement | null>;

private readonly _TODAY_DATE: Date;
//#endregion private properties

Expand Down Expand Up @@ -174,11 +182,18 @@ export class DatePicker extends DatePickerMixin(DatePickerMinMaxMixin(LitElement
protected async updated(
changedProperties: DatePickerChangedProperties
): Promise<void> {
if (changedProperties.has('startView') && this.startView === 'calendar') {
const monthDropdown = await this._monthDropdown;
if (this.startView === 'calendar') {
if (changedProperties.has('startView')) {
await focusElement(this._monthDropdown);
}

if (changedProperties.has('_currentDate') && this.#shouldUpdateFocusInNavigationButtons) {
const currentDate = this._currentDate;

isInTargetMonth(this._min, currentDate) && focusElement(this._navigationNext);
isInTargetMonth(this._max, currentDate) && focusElement(this._navigationPrevious);

if (monthDropdown) {
monthDropdown.focus();
this.#shouldUpdateFocusInNavigationButtons = false;
}
}
}
Expand Down Expand Up @@ -338,6 +353,7 @@ export class DatePicker extends DatePickerMixin(DatePickerMinMaxMixin(LitElement
);

this._currentDate = newCurrentDate;
this.#shouldUpdateFocusInNavigationButtons = true;
};

#updateSelectedAndCurrentDate = (maybeDate: Date | number | string): void => {
Expand Down
13 changes: 13 additions & 0 deletions src/helpers/focus-element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export async function focusElement<T extends HTMLElement | null>(
asyncSelector: Promise<T>,
thenCallback?: (element: NonNullable<T>) => void | Promise<void>
): Promise<T> {
const resolvedElement = await asyncSelector;

if (resolvedElement) {
resolvedElement.focus();
thenCallback?.(resolvedElement as NonNullable<T>);
}

return resolvedElement;
}
8 changes: 2 additions & 6 deletions src/month-calendar/month-calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { classMap } from 'lit/directives/class-map.js';
import { navigationKeySetGrid } from '../constants.js';
import { computeNextSelectedDate } from '../helpers/compute-next-selected-date.js';
import { dispatchCustomEvent } from '../helpers/dispatch-custom-event.js';
import { focusElement } from '../helpers/focus-element.js';
import { isInTargetMonth } from '../helpers/is-in-current-month.js';
import { toClosestTarget } from '../helpers/to-closest-target.js';
import { toResolvedDate } from '../helpers/to-resolved-date.js';
Expand Down Expand Up @@ -68,12 +69,7 @@ export class MonthCalendar extends LitElement implements MonthCalendarProperties

protected async updated(): Promise<void> {
if (this.#shouldFocusSelectedDate) {
const selectedCalendarDay = await this.selectedCalendarDay;

if (selectedCalendarDay) {
selectedCalendarDay.focus();
}

await focusElement(this.selectedCalendarDay);
this.#shouldFocusSelectedDate = false;
}
}
Expand Down
8 changes: 2 additions & 6 deletions src/year-grid/year-grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { classMap } from 'lit/directives/class-map.js';

import { MAX_DATE, navigationKeySetGrid } from '../constants.js';
import { dispatchCustomEvent } from '../helpers/dispatch-custom-event.js';
import { focusElement } from '../helpers/focus-element.js';
import { toClosestTarget } from '../helpers/to-closest-target.js';
import { toResolvedDate } from '../helpers/to-resolved-date.js';
import { toYearList } from '../helpers/to-year-list.js';
Expand Down Expand Up @@ -59,12 +60,7 @@ export class YearGrid extends LitElement implements YearGridProperties {
}

protected async firstUpdated(): Promise<void> {
const selectedYearGridButton = await this.selectedYearGridButton;

if (selectedYearGridButton) {
selectedYearGridButton.focus();
selectedYearGridButton.scrollIntoView();
}
await focusElement(this.selectedYearGridButton, element => element.scrollIntoView());
}

protected render(): TemplateResult | typeof nothing {
Expand Down

0 comments on commit f07c919

Please sign in to comment.