diff --git a/src/components/ha-base-time-input.ts b/src/components/ha-base-time-input.ts index 54490e047bbb..71870d27490d 100644 --- a/src/components/ha-base-time-input.ts +++ b/src/components/ha-base-time-input.ts @@ -1,10 +1,12 @@ import "@material/mwc-list/mwc-list-item"; -import { css, html, LitElement, TemplateResult } from "lit"; +import { css, html, LitElement, TemplateResult, nothing } from "lit"; import { customElement, property } from "lit/decorators"; +import { mdiClose } from "@mdi/js"; import { ifDefined } from "lit/directives/if-defined"; import { fireEvent } from "../common/dom/fire_event"; import { stopPropagation } from "../common/dom/stop_propagation"; import "./ha-select"; +import "./ha-icon-button"; import { HaTextField } from "./ha-textfield"; import "./ha-input-helper-text"; @@ -124,116 +126,128 @@ export class HaBaseTimeInput extends LitElement { */ @property() amPm: "AM" | "PM" = "AM"; + @property({ type: Boolean, reflect: true }) public clearable?: boolean; + protected render(): TemplateResult { return html` ${this.label ? html`` : ""} -
- ${this.enableDay - ? html` - +
+ ${this.enableDay + ? html` + + + ` + : ""} + + + + + + ${this.enableSecond + ? html` - - ` - : ""} + ` + : ""} + ${this.enableMillisecond + ? html` + ` + : ""} + ${this.clearable && !this.required && !this.disabled + ? html`` + : nothing} +
- - - - - ${this.enableSecond - ? html` - ` - : ""} - ${this.enableMillisecond - ? html` - ` - : ""} ${this.format === 24 ? "" : html`AM PM `} + ${this.helper + ? html`${this.helper}` + : ""}
- ${this.helper - ? html`${this.helper}` - : ""} `; } + private _clearValue(): void { + fireEvent(this, "value-changed"); + } + private _valueChanged(ev: InputEvent) { const textField = ev.currentTarget as HaTextField; this[textField.name] = @@ -302,18 +320,25 @@ export class HaBaseTimeInput extends LitElement { } static styles = css` + :host([clearable]) { + position: relative; + } :host { display: block; } + .time-input-wrap-wrap { + display: flex; + } .time-input-wrap { display: flex; border-radius: var(--mdc-shape-small, 4px) var(--mdc-shape-small, 4px) 0 0; overflow: hidden; position: relative; direction: ltr; + padding-right: 3px; } ha-textfield { - width: 40px; + width: 55px; text-align: center; --mdc-shape-small: 0; --text-field-appearance: none; @@ -335,6 +360,21 @@ export class HaBaseTimeInput extends LitElement { --mdc-shape-small: 0; width: 85px; } + :host([clearable]) .mdc-select__anchor { + padding-inline-end: var(--select-selected-text-padding-end, 12px); + } + ha-icon-button { + position: relative + --mdc-icon-button-size: 36px; + --mdc-icon-size: 20px; + color: var(--secondary-text-color); + direction: var(--direction); + display: flex; + align-items: center; + background-color:var(--mdc-text-field-fill-color, whitesmoke); + border-bottom-style: solid; + border-bottom-width: 1px; + } label { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; diff --git a/src/components/ha-selector/ha-selector-time.ts b/src/components/ha-selector/ha-selector-time.ts index ceb8d9fe93eb..bacba114fc87 100644 --- a/src/components/ha-selector/ha-selector-time.ts +++ b/src/components/ha-selector/ha-selector-time.ts @@ -27,6 +27,7 @@ export class HaTimeSelector extends LitElement { .locale=${this.hass.locale} .disabled=${this.disabled} .required=${this.required} + clearable .helper=${this.helper} .label=${this.label} enable-second diff --git a/src/components/ha-time-input.ts b/src/components/ha-time-input.ts index 29893298dc60..696dbef4aac5 100644 --- a/src/components/ha-time-input.ts +++ b/src/components/ha-time-input.ts @@ -23,6 +23,8 @@ export class HaTimeInput extends LitElement { @property({ type: Boolean, attribute: "enable-second" }) public enableSecond = false; + @property({ type: Boolean, reflect: true }) public clearable?: boolean; + protected render() { const useAMPM = useAmPm(this.locale); @@ -48,22 +50,26 @@ export class HaTimeInput extends LitElement { @value-changed=${this._timeChanged} .enableSecond=${this.enableSecond} .required=${this.required} + .clearable=${this.clearable && this.value !== undefined} .helper=${this.helper} > `; } - private _timeChanged(ev: CustomEvent<{ value: TimeChangedEvent }>) { + private _timeChanged(ev: CustomEvent<{ value?: TimeChangedEvent }>) { ev.stopPropagation(); const eventValue = ev.detail.value; const useAMPM = useAmPm(this.locale); - let value; + let value: string | undefined; + // An undefined eventValue means the time selector is being cleared, + // the `value` variable will (intentionally) be left undefined. if ( - !isNaN(eventValue.hours) || - !isNaN(eventValue.minutes) || - !isNaN(eventValue.seconds) + eventValue !== undefined && + (!isNaN(eventValue.hours) || + !isNaN(eventValue.minutes) || + !isNaN(eventValue.seconds)) ) { let hours = eventValue.hours || 0; if (eventValue && useAMPM) {