diff --git a/src/data/input_text.ts b/src/data/input_text.ts
index a8ed653111..04ee6c334c 100644
--- a/src/data/input_text.ts
+++ b/src/data/input_text.ts
@@ -1,7 +1,7 @@
import { HomeAssistant } from "../types";
export const setValue = (hass: HomeAssistant, entity: string, value: string) =>
- hass.callService("input_text", "set_value", {
+ hass.callService(entity.split(".", 1)[0], "set_value", {
value,
entity_id: entity,
});
diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.js b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.js
deleted file mode 100644
index 611d496592..0000000000
--- a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.js
+++ /dev/null
@@ -1,188 +0,0 @@
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import "@polymer/paper-input/paper-input";
-import { IronResizableBehavior } from "@polymer/iron-resizable-behavior/iron-resizable-behavior";
-import { mixinBehaviors } from "@polymer/polymer/lib/legacy/class";
-
-import "../components/hui-generic-entity-row";
-import "../../../components/ha-slider";
-import { computeRTL } from "../../../common/util/compute_rtl";
-
-class HuiInputNumberEntityRow extends mixinBehaviors(
- [IronResizableBehavior],
- PolymerElement
-) {
- static get template() {
- return html`
- ${this.styleTemplate}
-
- ${this.inputNumberControlTemplate}
-
- `;
- }
-
- static get styleTemplate() {
- return html`
-
- `;
- }
-
- static get inputNumberControlTemplate() {
- return html`
-
-
-
-
- [[_value]] [[_stateObj.attributes.unit_of_measurement]]
-
-
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- _config: Object,
- _stateObj: {
- type: Object,
- computed: "_computeStateObj(hass.states, _config.entity)",
- observer: "_stateObjChanged",
- },
- _min: {
- type: Number,
- value: 0,
- },
- _max: {
- type: Number,
- value: 100,
- },
- _step: Number,
- _value: Number,
- _rtl: {
- type: String,
- computed: "_computeRTLDirection(hass)",
- },
- };
- }
-
- ready() {
- super.ready();
- if (typeof ResizeObserver === "function") {
- const ro = new ResizeObserver((entries) => {
- entries.forEach(() => {
- this._hiddenState();
- });
- });
- ro.observe(this.$.input_number_card);
- } else {
- this.addEventListener("iron-resize", this._hiddenState);
- }
- }
-
- _equals(a, b) {
- return a === b;
- }
-
- _computeStateObj(states, entityId) {
- return states && entityId in states ? states[entityId] : null;
- }
-
- setConfig(config) {
- if (!config || !config.entity) {
- throw new Error("Entity not configured.");
- }
- this._config = config;
- }
-
- _hiddenState() {
- if (
- !this.$ ||
- !this._stateObj ||
- this._stateObj.attributes.mode !== "slider"
- )
- return;
- const width = this.$.input_number_card.offsetWidth;
- const stateEl = this.shadowRoot.querySelector(".state");
- if (!stateEl) return;
- stateEl.hidden = width <= 350;
- }
-
- _stateObjChanged(stateObj, oldStateObj) {
- if (!stateObj) return;
-
- this.setProperties({
- _min: Number(stateObj.attributes.min),
- _max: Number(stateObj.attributes.max),
- _step: Number(stateObj.attributes.step),
- _value: Number(stateObj.state),
- });
- if (
- oldStateObj &&
- stateObj.attributes.mode === "slider" &&
- oldStateObj.attributes.mode !== "slider"
- ) {
- this._hiddenState();
- }
- }
-
- _selectedValueChanged() {
- if (this._value === Number(this._stateObj.state)) return;
-
- this.hass.callService("input_number", "set_value", {
- value: this._value,
- entity_id: this._stateObj.entity_id,
- });
- }
-
- _computeRTLDirection(hass) {
- return computeRTL(hass) ? "rtl" : "ltr";
- }
-}
-customElements.define("hui-input-number-entity-row", HuiInputNumberEntityRow);
diff --git a/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts
new file mode 100644
index 0000000000..f3fb9d0709
--- /dev/null
+++ b/src/panels/lovelace/entity-rows/hui-input-number-entity-row.ts
@@ -0,0 +1,162 @@
+import {
+ html,
+ LitElement,
+ TemplateResult,
+ property,
+ customElement,
+ css,
+ CSSResult,
+} from "lit-element";
+
+import "../components/hui-generic-entity-row";
+import "../../../components/ha-slider";
+import "../components/hui-warning";
+
+import { computeRTLDirection } from "../../../common/util/compute_rtl";
+import { EntityRow, EntityConfig } from "./types";
+import { HomeAssistant } from "../../../types";
+import { setValue } from "../../../data/input_text";
+
+@customElement("hui-input-number-entity-row")
+class HuiInputNumberEntityRow extends LitElement implements EntityRow {
+ @property() public hass?: HomeAssistant;
+ @property() private _config?: EntityConfig;
+ private _loaded?: boolean;
+ private _updated?: boolean;
+
+ public setConfig(config: EntityConfig): void {
+ if (!config) {
+ throw new Error("Configuration error");
+ }
+ this._config = config;
+ }
+
+ public connectedCallback(): void {
+ super.connectedCallback();
+ if (this._updated && !this._loaded) {
+ this._initialLoad();
+ }
+ }
+
+ protected firstUpdated(): void {
+ this._updated = true;
+ if (this.isConnected && !this._loaded) {
+ this._initialLoad();
+ }
+ }
+
+ protected render(): TemplateResult | void {
+ if (!this._config || !this.hass) {
+ return html``;
+ }
+
+ const stateObj = this.hass.states[this._config.entity];
+
+ if (!stateObj) {
+ return html`
+ ${this.hass.localize(
+ "ui.panel.lovelace.warning.entity_not_found",
+ "entity",
+ this._config.entity
+ )}
+ `;
+ }
+
+ return html`
+
+
+ ${stateObj.attributes.mode === "slider"
+ ? html`
+
+
+
+ ${Number(stateObj.state)}
+ ${stateObj.attributes.unit_of_measurement}
+
+
+ `
+ : html`
+
+ `}
+
+
+ `;
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ .flex {
+ display: flex;
+ align-items: center;
+ }
+ .state {
+ min-width: 45px;
+ text-align: center;
+ }
+ paper-input {
+ text-align: right;
+ }
+ `;
+ }
+
+ private async _initialLoad(): Promise {
+ this._loaded = true;
+ await this.updateComplete;
+ const element = this.shadowRoot!.querySelector(".state") as HTMLElement;
+
+ if (!element || !this.parentElement) {
+ return;
+ }
+
+ element.hidden = this.parentElement.clientWidth <= 350;
+ }
+
+ private get _inputElement(): { value: string } {
+ // linter recommended the following syntax
+ return (this.shadowRoot!.getElementById("input") as unknown) as {
+ value: string;
+ };
+ }
+
+ private _selectedValueChanged(): void {
+ const element = this._inputElement;
+ const stateObj = this.hass!.states[this._config!.entity];
+
+ if (element.value !== stateObj.state) {
+ setValue(this.hass!, stateObj.entity_id, element.value!);
+ }
+ }
+
+ private _computeRTLDirection(): string {
+ return computeRTLDirection(this.hass!);
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-input-number-entity-row": HuiInputNumberEntityRow;
+ }
+}