diff --git a/src/__demo__/demo-app.ts b/src/__demo__/demo-app.ts index 859def59..9d525291 100644 --- a/src/__demo__/demo-app.ts +++ b/src/__demo__/demo-app.ts @@ -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; + public static override styles = [ css` :host { @@ -35,13 +42,17 @@ export class DemoApp extends RootElement { protected override render() { return html` + + + `; } + + async #showDialog() { + const dialog = await this.dialog; + + dialog?.show(); + } + + #dateUpdated({ + detail, + currentTarget, + }: CustomEvent): void { + const { id } = currentTarget as AppDatePicker; + + console.debug({ + id, + detail, + }); + } } diff --git a/src/date-picker-dialog/app-date-picker-dialog.ts b/src/date-picker-dialog/app-date-picker-dialog.ts new file mode 100644 index 00000000..1b9f3370 --- /dev/null +++ b/src/date-picker-dialog/app-date-picker-dialog.ts @@ -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; + } +} diff --git a/src/date-picker-dialog/date-picker-dialog.ts b/src/date-picker-dialog/date-picker-dialog.ts new file mode 100644 index 00000000..eb1e7a5f --- /dev/null +++ b/src/date-picker-dialog/date-picker-dialog.ts @@ -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) => { + 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` + + + +
+ ${this.resetLabel} + ${this.dismissLabel} +
+ + ${this.confirmLabel} +
+ `; + } + + public hide(): void { + this.open = false; + } + + public show(): void { + this.open = true; + } + + #onClosed = () => { + this.hide(); + }; + + #onClosing = ({ + detail: { + action, + ...rest + }, + }: CustomEvent): void => { + console.debug({ action, rest }); + + if (action === 'set') { + this.value = toDateString(this.#valueAsDate); + } + }; + + #onDatePickerDateUpdated({ + detail: { + valueAsDate, + }, + }: CustomEvent) { + this.#valueAsDate = valueAsDate; + } + + #onDatePickerFirstUpdated({ + detail: { + valueAsDate, + }, + }: CustomEvent) { + this.#valueAsDate = valueAsDate; + } + + #onResetClick() { + this.value = undefined; + } +} + +// FIXME: Do not close dialog when enter/ space or select new year diff --git a/src/date-picker-dialog/stylings.ts b/src/date-picker-dialog/stylings.ts index e487e59f..ba903a89 100644 --- a/src/date-picker-dialog/stylings.ts +++ b/src/date-picker-dialog/stylings.ts @@ -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; } `; @@ -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; +} `;