diff --git a/src/dialogs/more-info/controls/more-info-alarm_control_panel.js b/src/dialogs/more-info/controls/more-info-alarm_control_panel.js
deleted file mode 100644
index 99be49908f..0000000000
--- a/src/dialogs/more-info/controls/more-info-alarm_control_panel.js
+++ /dev/null
@@ -1,281 +0,0 @@
-import "@material/mwc-button";
-import "@polymer/iron-flex-layout/iron-flex-layout-classes";
-import "@polymer/paper-input/paper-input";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-/* eslint-plugin-disable lit */
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import { fireEvent } from "../../../common/dom/fire_event";
-import { FORMAT_NUMBER } from "../../../data/alarm_control_panel";
-import LocalizeMixin from "../../../mixins/localize-mixin";
-
-class MoreInfoAlarmControlPanel extends LocalizeMixin(PolymerElement) {
- static get template() {
- return html`
-
-
-
-
-
-
-
-
-
- 1
- 4
- 7
-
-
- 2
- 5
- 8
- 0
-
-
- 3
- 6
- 9
-
- [[localize('ui.card.alarm_control_panel.clear_code')]]
-
-
-
-
-
-
-
-
-
- [[localize('ui.card.alarm_control_panel.disarm')]]
-
-
-
-
- [[localize('ui.card.alarm_control_panel.arm_home')]]
-
-
- [[localize('ui.card.alarm_control_panel.arm_away')]]
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- stateObj: {
- type: Object,
- observer: "_stateObjChanged",
- },
- _enteredCode: {
- type: String,
- value: "",
- },
- _codeFormat: {
- type: String,
- value: "",
- },
- _codeValid: {
- type: Boolean,
- computed:
- "_validateCode(_enteredCode, _codeFormat, _armVisible, _codeArmRequired)",
- },
- _disarmVisible: {
- type: Boolean,
- value: false,
- },
- _armVisible: {
- type: Boolean,
- value: false,
- },
- _inputEnabled: {
- type: Boolean,
- value: false,
- },
- _inputMode: {
- type: String,
- computed: "_getInputMode(_codeFormat)",
- },
- };
- }
-
- constructor() {
- super();
- this._armedStates = [
- "armed_home",
- "armed_away",
- "armed_night",
- "armed_custom_bypass",
- ];
- }
-
- _stateObjChanged(newVal, oldVal) {
- if (newVal) {
- const state = newVal.state;
- const props = {
- _codeFormat: newVal.attributes.code_format,
- _armVisible: state === "disarmed",
- _codeArmRequired: newVal.attributes.code_arm_required,
- _disarmVisible:
- this._armedStates.includes(state) ||
- state === "pending" ||
- state === "triggered" ||
- state === "arming",
- };
- props._inputEnabled = props._disarmVisible || props._armVisible;
- this.setProperties(props);
- }
- if (oldVal) {
- setTimeout(() => {
- fireEvent(this, "iron-resize");
- }, 500);
- }
- }
-
- _getInputMode(format) {
- return this._isNumber(format) ? "numeric" : "text";
- }
-
- _isNumber(format) {
- return format === FORMAT_NUMBER;
- }
-
- _validateCode(code, format, armVisible, codeArmRequired) {
- return !format || code.length > 0 || (armVisible && !codeArmRequired);
- }
-
- _digitClicked(ev) {
- this._enteredCode += ev.target.getAttribute("data-digit");
- }
-
- _clearEnteredCode() {
- this._enteredCode = "";
- }
-
- _callService(ev) {
- const service = ev.target.getAttribute("data-service");
- const data = {
- entity_id: this.stateObj.entity_id,
- code: this._enteredCode,
- };
- this.hass.callService("alarm_control_panel", service, data).then(() => {
- this._enteredCode = "";
- });
- }
-}
-customElements.define(
- "more-info-alarm_control_panel",
- MoreInfoAlarmControlPanel
-);
diff --git a/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts b/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts
new file mode 100644
index 0000000000..1efb0094f7
--- /dev/null
+++ b/src/dialogs/more-info/controls/more-info-alarm_control_panel.ts
@@ -0,0 +1,165 @@
+import "@material/mwc-button";
+import type { HassEntity } from "home-assistant-js-websocket";
+import { css, html, LitElement, TemplateResult } from "lit";
+import { customElement, property, query } from "lit/decorators";
+import { classMap } from "lit/directives/class-map";
+import "../../../components/ha-textfield";
+import type { HaTextField } from "../../../components/ha-textfield";
+import {
+ callAlarmAction,
+ FORMAT_NUMBER,
+} from "../../../data/alarm_control_panel";
+import type { HomeAssistant } from "../../../types";
+
+const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"];
+const ARM_ACTIONS = ["arm_away", "arm_home"];
+const DISARM_ACTIONS = ["disarm"];
+
+@customElement("more-info-alarm_control_panel")
+export class MoreInfoAlarmControlPanel extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ attribute: false }) public stateObj?: HassEntity;
+
+ @query("#alarmCode") private _input?: HaTextField;
+
+ protected render(): TemplateResult {
+ if (!this.hass || !this.stateObj) {
+ return html``;
+ }
+
+ return html`
+ ${!this.stateObj.attributes.code_format
+ ? ""
+ : html`
+
+
+
+ `}
+ ${this.stateObj.attributes.code_format !== FORMAT_NUMBER
+ ? ""
+ : html`
+
+ ${BUTTONS.map((value) =>
+ value === ""
+ ? html``
+ : html`
+
+ ${value === "clear"
+ ? this.hass!.localize(
+ `ui.card.alarm_control_panel.clear_code`
+ )
+ : value}
+
+ `
+ )}
+
+ `}
+
+ ${(this.stateObj.state === "disarmed"
+ ? ARM_ACTIONS
+ : DISARM_ACTIONS
+ ).map(
+ (stateAction) => html`
+
+ ${this.hass!.localize(
+ `ui.card.alarm_control_panel.${stateAction}`
+ )}
+
+ `
+ )}
+
+ `;
+ }
+
+ private _handlePadClick(e: MouseEvent): void {
+ const val = (e.currentTarget! as any).value;
+ this._input!.value = val === "clear" ? "" : this._input!.value + val;
+ }
+
+ private _handleActionClick(e: MouseEvent): void {
+ const input = this._input;
+ callAlarmAction(
+ this.hass!,
+ this.stateObj!.entity_id,
+ (e.currentTarget! as any).action,
+ input?.value || undefined
+ );
+ if (input) {
+ input.value = "";
+ }
+ }
+
+ static styles = css`
+ ha-textfield {
+ display: block;
+ margin: 8px;
+ max-width: 150px;
+ text-align: center;
+ }
+
+ #keypad {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ margin: auto;
+ width: 100%;
+ max-width: 300px;
+ }
+
+ #keypad mwc-button {
+ padding: 8px;
+ width: 30%;
+ box-sizing: border-box;
+ }
+
+ .actions {
+ margin: 0;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+
+ .actions mwc-button {
+ margin: 0 4px 4px;
+ }
+
+ mwc-button#disarm {
+ color: var(--error-color);
+ }
+
+ mwc-button.numberkey {
+ --mdc-typography-button-font-size: var(--keypad-font-size, 0.875rem);
+ }
+
+ .center {
+ display: flex;
+ justify-content: center;
+ }
+ `;
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "more-info-alarm_control_panel": MoreInfoAlarmControlPanel;
+ }
+}