Skip to content

Commit

Permalink
feat: implement AppDatePickerDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
motss committed Nov 14, 2021
1 parent c411e13 commit 4d41bba
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 2 deletions.
34 changes: 33 additions & 1 deletion src/__demo__/demo-app.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import '../date-picker-dialog/app-date-picker-dialog.js';
import '../date-picker-input/app-date-picker-input.js';
import '../date-picker/app-date-picker.js';

import { css, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { customElement, queryAsync } from 'lit/decorators.js';

import type { AppDatePicker } from '../date-picker/app-date-picker.js';
import type { AppDatePickerDialog } from '../date-picker-dialog/app-date-picker-dialog.js';
import { appDatePickerDialogName } from '../date-picker-dialog/constants.js';
import { RootElement } from '../root-element/root-element.js';
import type { CustomEventDetail } from '../typings.js';

@customElement('demo-app')
export class DemoApp extends RootElement {
@queryAsync(appDatePickerDialogName) dialog!: Promise<AppDatePickerDialog>;

public static override styles = [
css`
:host {
Expand Down Expand Up @@ -35,13 +42,17 @@ export class DemoApp extends RootElement {
protected override render() {
return html`
<app-date-picker
id="datePicker1"
min="1970-01-01"
.max=${'2020-02-02'}
.value=${'2020-02-02' as never}
@date-updated=${this.#dateUpdated}
></app-date-picker>
<app-date-picker
id="datePicker2"
.min=${'1970-01-01'}
@date-updated=${this.#dateUpdated}
></app-date-picker>
<app-date-picker-input
Expand All @@ -51,9 +62,30 @@ export class DemoApp extends RootElement {
.value=${'2020-02-02'}
></app-date-picker-input>
<button @click=${this.#showDialog}>Open</button>
<app-date-picker-dialog></app-date-picker-dialog>
<!-- <app-date-picker-input></app-date-picker-input> -->
<!-- <app-datepicker-dialog class="datepicker-dialog"></app-datepicker-dialog> -->
<!-- <button class="open-btn" type="button">Open datepicker</button> -->
`;
}

async #showDialog() {
const dialog = await this.dialog;

dialog?.show();
}

#dateUpdated({
detail,
currentTarget,
}: CustomEvent<CustomEventDetail['date-updated']['detail']>): void {
const { id } = currentTarget as AppDatePicker;

console.debug({
id,
detail,
});
}
}
13 changes: 13 additions & 0 deletions src/date-picker-dialog/app-date-picker-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { customElement } from 'lit/decorators.js';

import { appDatePickerDialogName } from './constants.js';
import { DatePickerDialog } from './date-picker-dialog.js';

@customElement(appDatePickerDialogName)
export class AppDatePickerDialog extends DatePickerDialog {}

declare global {
interface HTMLElementTagNameMap {
[appDatePickerDialogName]: AppDatePickerDialog;
}
}
154 changes: 154 additions & 0 deletions src/date-picker-dialog/date-picker-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import '@material/mwc-button';
import '@material/mwc-dialog';
import '../date-picker/app-date-picker.js';
import './app-date-picker-dialog-base.js';

import type { ReactiveElement, TemplateResult } from 'lit';
import { adoptStyles, html } from 'lit';
import { property } from 'lit/decorators.js';

import { toDateString } from '../helpers/to-date-string.js';
import { toResolvedDate } from '../helpers/to-resolved-date.js';
import { DatePickerMinMaxMixin } from '../mixins/date-picker-min-max-mixin.js';
import { DatePickerMixin } from '../mixins/date-picker-mixin.js';
import { RootElement } from '../root-element/root-element.js';
import type { CustomEventDetail } from '../typings.js';
import { datePickerDialogStyling } from './stylings.js';
import type { DatePickerDialogProperties, DialogClosingEventDetail } from './typings.js';

export class DatePickerDialog extends DatePickerMixin(DatePickerMinMaxMixin(RootElement)) implements DatePickerDialogProperties {
@property({ type: String }) public confirmLabel = 'set';
@property({ type: String }) public dismissLabel = 'cancel';
@property({ type: String }) public resetLabel = 'reset';
@property({ type: Boolean }) public open = false;

#disconnect: () => void = () => void 0;
#valueAsDate: Date = toResolvedDate();

public static override styles = [
datePickerDialogStyling,
];

public constructor() {
super();

const closing = (ev: CustomEvent<DialogClosingEventDetail>) => {
this.#onClosing(ev);
};

this.addEventListener('closing' as never, closing);

this.#disconnect = () => {
this.removeEventListener('closing' as never, closing);
};
}

public override disconnectedCallback() {
super.disconnectedCallback();

this.#disconnect();
}

protected override createRenderRoot(): Element | ShadowRoot {
const renderRoot = this as unknown as ShadowRoot;

adoptStyles(
renderRoot,
(this.constructor as typeof ReactiveElement).elementStyles
);

return renderRoot;
}

protected override render(): TemplateResult<1> {
return html`
<app-date-picker-dialog-base
?open=${this.open}
@closing=${this.#onClosing}
@closed=${this.#onClosed}
>
<app-date-picker
?showWeekNumber=${this.showWeekNumber}
.disabledDates=${this.disabledDates}
.disabledDays=${this.disabledDays}
.firstDayOfWeek=${this.firstDayOfWeek}
.landscape=${this.landscape}
.locale=${this.locale}
.max=${this.max}
.min=${this.min}
.nextMonthLabel=${this.nextMonthLabel}
.previousMonthLabel=${this.previousMonthLabel}
.selectedDateLabel=${this.selectedDateLabel}
.startView=${this.startView}
.value=${this.value}
.weekLabel=${this.weekLabel}
.weekNumberType=${this.weekNumberType}
.yearDropdownLabel=${this.yearDropdownLabel}
@date-updated=${this.#onDatePickerDateUpdated}
@first-updated=${this.#onDatePickerFirstUpdated}
></app-date-picker>
<div class=secondary-actions slot=secondaryAction>
<mwc-button
@click=${this.#onResetClick}
>${this.resetLabel}</mwc-button>
<mwc-button
dialogAction=cancel
>${this.dismissLabel}</mwc-button>
</div>
<mwc-button
dialogAction=set
slot=primaryAction
>${this.confirmLabel}</mwc-button>
</app-date-picker-dialog-base>
`;
}

public hide(): void {
this.open = false;
}

public show(): void {
this.open = true;
}

#onClosed = () => {
this.hide();
};

#onClosing = ({
detail: {
action,
...rest
},
}: CustomEvent<DialogClosingEventDetail>): void => {
console.debug({ action, rest });

if (action === 'set') {
this.value = toDateString(this.#valueAsDate);
}
};

#onDatePickerDateUpdated({
detail: {
valueAsDate,
},
}: CustomEvent<CustomEventDetail['date-updated']['detail']>) {
this.#valueAsDate = valueAsDate;
}

#onDatePickerFirstUpdated({
detail: {
valueAsDate,
},
}: CustomEvent<CustomEventDetail['first-updated']['detail']>) {
this.#valueAsDate = valueAsDate;
}

#onResetClick() {
this.value = undefined;
}
}

// FIXME: Do not close dialog when enter/ space or select new year
21 changes: 20 additions & 1 deletion src/date-picker-dialog/stylings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,20 @@ import { appDatePickerDialogName } from './constants.js';
export const datePickerDialogBaseStyling = css`
:host {
display: block;
--date-picker-dialog-base-color: #000;
--mdc-dialog-min-width: 256px;
--mdc-dialog-content-ink-color: var(--date-picker-dialog-color, var(--date-picker-dialog-base-color));
--mdc-theme-primary: var(--date-picker-dialog-color, var(--date-picker-dialog-base-color));
}
.mdc-dialog .mdc-dialog__surface,
.mdc-dialog .mdc-dialog__content {
overflow: initial;
}
.mdc-dialog__content {
.mdc-dialog .mdc-dialog__content {
background-color: inherit;
padding: 0;
}
`;
Expand All @@ -16,4 +27,12 @@ export const datePickerDialogStyling = css`
${unsafeCSS(appDatePickerDialogName)} {
display: block;
}
${unsafeCSS(appDatePickerDialogName)} app-date-picker {
background-color: var(--mdc-theme-surface);
}
${unsafeCSS(appDatePickerDialogName)} .secondary-actions mwc-button + mwc-button {
margin: 0 0 0 8px;
}
`;

0 comments on commit 4d41bba

Please sign in to comment.